libcli:security: allow spaces after BAD:
[Samba.git] / lib / ldb / pyldb.c
blob53b855990bbf0fb86a93939d5898cbadba604888
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 "lib/replace/system/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 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg, PyLdbObject *pyldb);
61 static PyObject *PyExc_LdbError;
63 static PyTypeObject PyLdbControl;
64 static PyTypeObject PyLdbResult;
65 static PyTypeObject PyLdbSearchIterator;
66 static PyTypeObject PyLdbMessage;
67 #define pyldb_Message_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
68 static PyTypeObject PyLdbDn;
69 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
70 static PyTypeObject PyLdb;
71 static PyTypeObject PyLdbMessageElement;
72 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
74 static PyTypeObject PyLdbTree;
75 static struct ldb_message_element *PyObject_AsMessageElement(
76 TALLOC_CTX *mem_ctx,
77 PyObject *set_obj,
78 unsigned int flags,
79 const char *attr_name);
80 static PyTypeObject PyLdbBytesType;
82 #define PYARG_STR_UNI "es"
84 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
86 PyObject* result = NULL;
87 PyObject* args = NULL;
88 args = Py_BuildValue("(y#)", msg, size);
89 if (args == NULL) {
90 return NULL;
92 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
93 Py_DECREF(args);
94 return result;
97 static PyObject *richcmp(int cmp_val, int op)
99 int ret;
100 switch (op) {
101 case Py_LT: ret = cmp_val < 0; break;
102 case Py_LE: ret = cmp_val <= 0; break;
103 case Py_EQ: ret = cmp_val == 0; break;
104 case Py_NE: ret = cmp_val != 0; break;
105 case Py_GT: ret = cmp_val > 0; break;
106 case Py_GE: ret = cmp_val >= 0; break;
107 default:
108 Py_INCREF(Py_NotImplemented);
109 return Py_NotImplemented;
111 return PyBool_FromLong(ret);
115 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
117 if (self->data != NULL) {
118 char* control = ldb_control_to_string(self->mem_ctx, self->data);
119 if (control == NULL) {
120 PyErr_NoMemory();
121 return NULL;
123 return PyUnicode_FromString(control);
124 } else {
125 return PyUnicode_FromString("ldb control");
129 static void py_ldb_control_dealloc(PyLdbControlObject *self)
131 if (self->mem_ctx != NULL) {
132 talloc_free(self->mem_ctx);
134 self->data = NULL;
135 Py_TYPE(self)->tp_free(self);
138 /* Create a text (rather than bytes) interface for a LDB result object */
139 static PyObject *wrap_text(const char *type, PyObject *wrapped)
141 PyObject *mod, *cls, *constructor, *inst;
142 mod = PyImport_ImportModule("_ldb_text");
143 if (mod == NULL)
144 return NULL;
145 cls = PyObject_GetAttrString(mod, type);
146 Py_DECREF(mod);
147 if (cls == NULL) {
148 Py_DECREF(mod);
149 return NULL;
151 constructor = PyObject_GetAttrString(cls, "_wrap");
152 Py_DECREF(cls);
153 if (constructor == NULL) {
154 return NULL;
156 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
157 Py_DECREF(constructor);
158 return inst;
161 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
162 PyObject *Py_UNUSED(ignored))
164 return PyUnicode_FromString(self->data->oid);
167 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
168 PyObject *Py_UNUSED(ignored))
170 return PyBool_FromLong(self->data->critical);
173 static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
175 if (value == NULL) {
176 PyErr_SetString(PyExc_AttributeError, "cannot delete critical flag");
177 return -1;
179 if (PyObject_IsTrue(value)) {
180 self->data->critical = true;
181 } else {
182 self->data->critical = false;
184 return 0;
187 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
189 char *data = NULL;
190 const char * const kwnames[] = { "ldb", "data", NULL };
191 struct ldb_control *parsed_controls;
192 PyLdbControlObject *ret;
193 PyObject *py_ldb;
194 TALLOC_CTX *mem_ctx;
195 struct ldb_context *ldb_ctx;
197 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
198 discard_const_p(char *, kwnames),
199 &PyLdb, &py_ldb, &data))
200 return NULL;
202 mem_ctx = talloc_new(NULL);
203 if (mem_ctx == NULL) {
204 PyErr_NoMemory();
205 return NULL;
208 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
209 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
211 if (!parsed_controls) {
212 talloc_free(mem_ctx);
213 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
214 return NULL;
217 ret = PyObject_New(PyLdbControlObject, type);
218 if (ret == NULL) {
219 PyErr_NoMemory();
220 talloc_free(mem_ctx);
221 return NULL;
224 ret->mem_ctx = mem_ctx;
226 ret->data = talloc_move(mem_ctx, &parsed_controls);
227 if (ret->data == NULL) {
228 Py_DECREF(ret);
229 PyErr_NoMemory();
230 talloc_free(mem_ctx);
231 return NULL;
234 return (PyObject *)ret;
237 static PyGetSetDef py_ldb_control_getset[] = {
239 .name = discard_const_p(char, "oid"),
240 .get = (getter)py_ldb_control_get_oid,
243 .name = discard_const_p(char, "critical"),
244 .get = (getter)py_ldb_control_get_critical,
245 .set = (setter)py_ldb_control_set_critical,
247 { .name = NULL },
250 static PyTypeObject PyLdbControl = {
251 .tp_name = "ldb.control",
252 .tp_dealloc = (destructor)py_ldb_control_dealloc,
253 .tp_getattro = PyObject_GenericGetAttr,
254 .tp_basicsize = sizeof(PyLdbControlObject),
255 .tp_getset = py_ldb_control_getset,
256 .tp_doc = "LDB control.",
257 .tp_str = (reprfunc)py_ldb_control_str,
258 .tp_new = py_ldb_control_new,
259 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
262 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
264 char *msg = NULL;
265 Py_ssize_t size;
266 int result = 0;
267 if (!PyBytes_Check(self)) {
268 PyErr_Format(PyExc_TypeError,"Unexpected type");
269 return NULL;
271 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
272 if (result != 0) {
273 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
274 return NULL;
276 return PyUnicode_FromStringAndSize(msg, size);
279 static PyTypeObject PyLdbBytesType = {
280 PyVarObject_HEAD_INIT(NULL, 0)
281 .tp_name = "ldb.bytes",
282 .tp_doc = "str/bytes (with custom str)",
283 .tp_str = (reprfunc)py_ldb_bytes_str,
284 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
287 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
289 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
292 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
294 return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
298 * Create a Python object from a ldb_result.
300 * @param result LDB result to convert
301 * @return Python object with converted result (a list object)
303 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
305 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
306 PyLdbControlObject *ctrl;
307 if (ctl_ctx == NULL) {
308 PyErr_NoMemory();
309 return NULL;
312 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
313 if (ctrl == NULL) {
314 talloc_free(ctl_ctx);
315 PyErr_NoMemory();
316 return NULL;
318 ctrl->mem_ctx = ctl_ctx;
319 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
320 if (ctrl->data == NULL) {
321 Py_DECREF(ctrl);
322 PyErr_NoMemory();
323 return NULL;
325 return (PyObject*) ctrl;
329 * Create a Python object from a ldb_result.
331 * @param result LDB result to convert
332 * @return Python object with converted result (a list object)
334 static PyObject *PyLdbResult_FromResult(struct ldb_result *result, PyLdbObject *pyldb)
336 PyLdbResultObject *ret;
337 PyObject *list, *controls, *referals;
338 Py_ssize_t i;
340 if (result == NULL) {
341 Py_RETURN_NONE;
344 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
345 if (ret == NULL) {
346 PyErr_NoMemory();
347 return NULL;
350 ret->pyldb = pyldb;
351 Py_INCREF(ret->pyldb);
353 list = PyList_New(result->count);
354 if (list == NULL) {
355 PyErr_NoMemory();
356 Py_DECREF(ret);
357 return NULL;
360 for (i = 0; i < result->count; i++) {
361 PyObject *pymessage = PyLdbMessage_FromMessage(result->msgs[i], pyldb);
362 if (pymessage == NULL) {
363 Py_DECREF(ret);
364 Py_DECREF(list);
365 return NULL;
367 PyList_SetItem(list, i, pymessage);
370 ret->mem_ctx = talloc_new(NULL);
371 if (ret->mem_ctx == NULL) {
372 Py_DECREF(list);
373 Py_DECREF(ret);
374 PyErr_NoMemory();
375 return NULL;
378 ret->msgs = list;
380 if (result->controls) {
381 i = 0;
382 while (result->controls[i]) {
383 i++;
385 controls = PyList_New(i);
386 if (controls == NULL) {
387 Py_DECREF(ret);
388 Py_DECREF(list);
389 PyErr_NoMemory();
390 return NULL;
392 for (i=0; result->controls[i]; i++) {
393 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
394 if (ctrl == NULL) {
395 Py_DECREF(ret);
396 Py_DECREF(list);
397 Py_DECREF(controls);
398 PyErr_NoMemory();
399 return NULL;
401 PyList_SetItem(controls, i, ctrl);
403 } else {
405 * No controls so we keep an empty list
407 controls = PyList_New(0);
408 if (controls == NULL) {
409 Py_DECREF(ret);
410 Py_DECREF(list);
411 PyErr_NoMemory();
412 return NULL;
416 ret->controls = controls;
418 i = 0;
420 while (result->refs && result->refs[i]) {
421 i++;
424 referals = PyList_New(i);
425 if (referals == NULL) {
426 Py_DECREF(ret);
427 Py_DECREF(list);
428 PyErr_NoMemory();
429 return NULL;
432 for (i = 0;result->refs && result->refs[i]; i++) {
433 PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
435 ret->referals = referals;
436 return (PyObject *)ret;
441 * PyErr_interal_LDB_DN_OR_RAISE does exactly what
442 * PyErr__LDB_DN_OR_RAISE does, but rather than going through the
443 * Python layer to import the Dn object, it directly uses the the
444 * address of the PyTypeObject. This is faster, but can only be done
445 * in pyldb.c.
447 #define PyErr_internal_LDB_DN_OR_RAISE(_py_obj, dn) do { \
448 PyLdbDnObject *_py_dn = NULL; \
449 if (_py_obj == NULL || !pyldb_Dn_Check(_py_obj)) { \
450 PyErr_SetString(PyExc_TypeError, "ldb Dn object required"); \
451 return NULL; \
453 _py_dn = (PyLdbDnObject *)_py_obj; \
454 dn = pyldb_Dn_AS_DN(_py_dn); \
455 if (_py_dn->pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn)) { \
456 PyErr_SetString(PyExc_RuntimeError, \
457 "Dn has a stale LDB connection"); \
458 return NULL; \
460 } while(0)
463 static PyObject *py_ldb_dn_validate(PyObject *self,
464 PyObject *Py_UNUSED(ignored))
466 struct ldb_dn *dn = NULL;
467 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
468 return PyBool_FromLong(ldb_dn_validate(dn));
471 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
472 PyObject *Py_UNUSED(ignored))
474 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
477 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
478 PyObject *Py_UNUSED(ignored))
480 return PyBool_FromLong(ldb_dn_is_special(self->dn));
483 static PyObject *py_ldb_dn_is_null(PyObject *self,
484 PyObject *Py_UNUSED(ignored))
486 struct ldb_dn *dn = NULL;
487 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
488 return PyBool_FromLong(ldb_dn_is_null(dn));
491 static PyObject *py_ldb_dn_get_casefold(PyObject *self,
492 PyObject *Py_UNUSED(ignored))
494 const char *s = NULL;
495 struct ldb_dn *dn = NULL;
496 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
497 s = ldb_dn_get_casefold(dn);
498 if (s == NULL) {
499 PyErr_NoMemory();
500 return NULL;
502 return PyUnicode_FromString(s);
505 static PyObject *py_ldb_dn_get_linearized(PyObject *self,
506 PyObject *Py_UNUSED(ignored))
508 struct ldb_dn *dn = NULL;
509 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
510 return PyUnicode_FromString(ldb_dn_get_linearized(dn));
513 static PyObject *py_ldb_dn_canonical_str(PyObject *self,
514 PyObject *Py_UNUSED(ignored))
516 struct ldb_dn *dn = NULL;
517 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
518 return PyUnicode_FromString(ldb_dn_canonical_string(dn, dn));
521 static PyObject *py_ldb_dn_canonical_ex_str(PyObject *self,
522 PyObject *Py_UNUSED(ignored))
524 struct ldb_dn *dn = NULL;
525 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
526 return PyUnicode_FromString(ldb_dn_canonical_ex_string(dn, dn));
529 static PyObject *py_ldb_dn_extended_str(PyObject *self, PyObject *args, PyObject *kwargs)
531 const char * const kwnames[] = { "mode", NULL };
532 int mode = 1;
533 struct ldb_dn *dn = NULL;
534 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
535 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
536 discard_const_p(char *, kwnames),
537 &mode)) {
538 return NULL;
540 return PyUnicode_FromString(ldb_dn_get_extended_linearized(dn, dn, mode));
543 static PyObject *py_ldb_dn_get_extended_component(PyObject *self, PyObject *args)
545 char *name;
546 const struct ldb_val *val = NULL;
547 struct ldb_dn *dn = NULL;
548 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
550 if (!PyArg_ParseTuple(args, "s", &name)) {
551 return NULL;
553 val = ldb_dn_get_extended_component(dn, name);
554 if (val == NULL) {
555 Py_RETURN_NONE;
558 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
561 static PyObject *py_ldb_dn_set_extended_component(PyObject *self, PyObject *args)
563 char *name;
564 int err;
565 uint8_t *value = NULL;
566 Py_ssize_t size = 0;
567 struct ldb_dn *dn = NULL;
568 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
570 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
571 return NULL;
573 if (value == NULL) {
574 err = ldb_dn_set_extended_component(dn, name, NULL);
575 } else {
576 struct ldb_val val;
577 val.data = (uint8_t *)value;
578 val.length = size;
579 err = ldb_dn_set_extended_component(dn, name, &val);
582 if (err != LDB_SUCCESS) {
583 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
584 return NULL;
587 Py_RETURN_NONE;
590 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
592 PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
593 PyObject *repr, *result;
594 if (str == NULL)
595 return NULL;
596 repr = PyObject_Repr(str);
597 if (repr == NULL) {
598 Py_DECREF(str);
599 return NULL;
601 result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
602 Py_DECREF(str);
603 Py_DECREF(repr);
604 return result;
607 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
609 char *name;
611 if (!PyArg_ParseTuple(args, "s", &name))
612 return NULL;
614 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
617 static PyObject *py_ldb_dn_richcmp(PyObject *pydn1, PyObject *pydn2, int op)
619 int ret;
620 struct ldb_dn *dn1 = NULL;
621 struct ldb_dn *dn2 = NULL;
622 if (!pyldb_Dn_Check(pydn2)) {
623 Py_INCREF(Py_NotImplemented);
624 return Py_NotImplemented;
626 PyErr_internal_LDB_DN_OR_RAISE(pydn1, dn1);
627 PyErr_internal_LDB_DN_OR_RAISE(pydn2, dn2);
629 ret = ldb_dn_compare(dn1, dn2);
630 return richcmp(ret, op);
633 static PyObject *py_ldb_dn_get_parent(PyObject *self,
634 PyObject *Py_UNUSED(ignored))
636 struct ldb_dn *dn = NULL;
637 struct ldb_dn *parent;
638 PyLdbDnObject *py_ret = NULL;
639 PyLdbDnObject *dn_self = NULL;
640 TALLOC_CTX *mem_ctx = NULL;
642 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
644 if (ldb_dn_get_comp_num(dn) < 1) {
645 Py_RETURN_NONE;
648 mem_ctx = talloc_new(NULL);
649 if (mem_ctx == NULL) {
650 PyErr_NoMemory();
651 return NULL;
654 parent = ldb_dn_get_parent(mem_ctx, dn);
655 if (parent == NULL) {
656 PyErr_NoMemory();
657 talloc_free(mem_ctx);
658 return NULL;
661 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
662 if (py_ret == NULL) {
663 PyErr_NoMemory();
664 talloc_free(mem_ctx);
665 return NULL;
667 dn_self = (PyLdbDnObject *)self;
669 py_ret->mem_ctx = mem_ctx;
670 py_ret->dn = parent;
671 py_ret->pyldb = dn_self->pyldb;
672 Py_INCREF(py_ret->pyldb);
673 return (PyObject *)py_ret;
676 static PyObject *py_ldb_dn_add_child(PyObject *self, PyObject *args)
678 PyObject *py_other = NULL;
679 struct ldb_dn *dn = NULL;
680 struct ldb_dn *other = NULL;
681 TALLOC_CTX *tmp_ctx = NULL;
682 bool ok;
684 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
686 if (!PyArg_ParseTuple(args, "O", &py_other)) {
687 return NULL;
691 * pyldb_Object_AsDn only uses tmp_ctx if py_other is str/bytes, in
692 * which case it allocates a struct ldb_dn. If py_other is a PyLdbDn,
693 * tmp_ctx is unused and the underlying dn is borrowed.
695 * The pieces of other are reassembled onto dn using dn itself as a
696 * talloc context (ldb_dn_add_child assumes all dns are talloc
697 * contexts), after which we don't need any temporary DN we made.
699 tmp_ctx = talloc_new(NULL);
700 if (tmp_ctx == NULL) {
701 PyErr_NoMemory();
702 return NULL;
705 ok = pyldb_Object_AsDn(tmp_ctx,
706 py_other,
707 ldb_dn_get_ldb_context(dn),
708 &other);
709 if (!ok) {
710 TALLOC_FREE(tmp_ctx);
711 return NULL;
714 ok = ldb_dn_add_child(dn, other);
715 TALLOC_FREE(tmp_ctx);
716 if (!ok) {
717 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
718 return NULL;
720 Py_RETURN_TRUE;
723 static PyObject *py_ldb_dn_add_base(PyObject *self, PyObject *args)
725 PyObject *py_other = NULL;
726 struct ldb_dn *other = NULL;
727 struct ldb_dn *dn = NULL;
728 TALLOC_CTX *tmp_ctx = NULL;
729 bool ok;
731 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
733 if (!PyArg_ParseTuple(args, "O", &py_other)) {
734 return NULL;
738 * As noted in py_ldb_dn_add_child() comments, if py_other is a
739 * string, other is an ephemeral struct ldb_dn, but if py_other is a
740 * python DN, other points to the corresponding long-lived DN.
742 tmp_ctx = talloc_new(NULL);
743 if (tmp_ctx == NULL) {
744 PyErr_NoMemory();
745 return NULL;
747 ok = pyldb_Object_AsDn(tmp_ctx,
748 py_other,
749 ldb_dn_get_ldb_context(dn),
750 &other);
751 if (!ok) {
752 TALLOC_FREE(tmp_ctx);
753 return NULL;
756 ok = ldb_dn_add_base(dn, other);
757 TALLOC_FREE(tmp_ctx);
758 if (!ok) {
759 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
760 return NULL;
762 Py_RETURN_TRUE;
765 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn, PyLdbObject *pyldb);
767 static PyObject *py_ldb_dn_copy_method(PyObject *self, PyObject *args)
769 struct ldb_dn *dn = NULL;
770 PyLdbObject *pyldb = NULL;
771 PyObject *obj = Py_None;
772 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
774 if (!PyArg_ParseTuple(args, "|O", &obj)) {
775 return NULL;
778 if (obj == Py_None) {
780 * With no argument, or None, dn.copy() uses its own ldb.
782 * There is not much reason to do this, other than as a
783 * convenience in this situation:
785 * >>> msg.dn = dn.copy(msg.ldb)
787 * when you don't know whether msg has a dn or not (if msg.ldb
788 * is None, msg will now belong to this dn's ldb).
790 pyldb = ((PyLdbDnObject *)self)->pyldb;
791 } else if (PyObject_TypeCheck(obj, &PyLdb)) {
792 pyldb = (PyLdbObject *)obj;
793 } else {
794 PyErr_Format(PyExc_TypeError,
795 "Expected Ldb or None");
796 return NULL;
798 if (pyldb != ((PyLdbDnObject *)self)->pyldb) {
800 * This is unfortunate, but we can't make a copy of the dn directly,
801 * since the opaque struct ldb_dn has a pointer to the ldb it knows,
802 * and it is the WRONG ONE.
804 * Instead we go via string serialisation.
806 char *dn_str = NULL;
807 struct ldb_dn *new_dn = NULL;
808 dn_str = ldb_dn_get_extended_linearized(pyldb->mem_ctx, dn, 1);
809 if (dn_str == NULL) {
810 PyErr_Format(PyExc_RuntimeError,
811 "Could not linearize DN");
812 return NULL;
814 new_dn = ldb_dn_new(pyldb->mem_ctx,
815 pyldb->ldb_ctx,
816 dn_str);
818 if (new_dn == NULL) {
819 PyErr_Format(PyExc_RuntimeError,
820 "Could not re-parse DN '%s'",
821 dn_str);
822 TALLOC_FREE(dn_str);
823 return NULL;
825 TALLOC_FREE(dn_str);
826 dn = new_dn;
828 return py_ldb_dn_copy(dn, pyldb);
831 static PyObject *py_ldb_dn_remove_base_components(PyObject *self, PyObject *args)
833 struct ldb_dn *dn = NULL;
834 int i;
835 bool ok;
836 if (!PyArg_ParseTuple(args, "i", &i)) {
837 return NULL;
840 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
842 ok = ldb_dn_remove_base_components(dn, i);
843 if (!ok) {
844 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
845 return NULL;
848 Py_RETURN_TRUE;
851 static PyObject *py_ldb_dn_is_child_of(PyObject *self, PyObject *args)
853 PyObject *py_base;
854 struct ldb_dn *dn, *base;
855 if (!PyArg_ParseTuple(args, "O", &py_base)) {
856 return NULL;
859 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
861 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
862 return NULL;
864 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
867 static PyObject *py_ldb_dn_get_component_name(PyObject *self, PyObject *args)
869 struct ldb_dn *dn = NULL;
870 const char *name;
871 unsigned int num = 0;
873 if (!PyArg_ParseTuple(args, "I", &num)) {
874 return NULL;
877 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
879 name = ldb_dn_get_component_name(dn, num);
880 if (name == NULL) {
881 Py_RETURN_NONE;
884 return PyUnicode_FromString(name);
887 static PyObject *py_ldb_dn_get_component_value(PyObject *self, PyObject *args)
889 struct ldb_dn *dn = NULL;
890 const struct ldb_val *val;
891 unsigned int num = 0;
893 if (!PyArg_ParseTuple(args, "I", &num)) {
894 return NULL;
897 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
899 val = ldb_dn_get_component_val(dn, num);
900 if (val == NULL) {
901 Py_RETURN_NONE;
904 return PyStr_FromLdbValue(val);
907 static PyObject *py_ldb_dn_set_component(PyObject *self, PyObject *args)
909 unsigned int num = 0;
910 char *name = NULL, *value = NULL;
911 struct ldb_val val = { 0 };
912 int err;
913 Py_ssize_t size = 0;
914 struct ldb_dn *dn = NULL;
916 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
918 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size)) {
919 return NULL;
922 val.data = (unsigned char*) value;
923 val.length = size;
925 err = ldb_dn_set_component(dn, num, name, val);
926 if (err != LDB_SUCCESS) {
927 PyErr_SetString(PyExc_TypeError, "Failed to set component");
928 return NULL;
931 Py_RETURN_NONE;
934 static PyObject *py_ldb_dn_get_rdn_name(PyObject *self,
935 PyObject *Py_UNUSED(ignored))
937 struct ldb_dn *dn = NULL;
938 const char *name;
940 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
942 name = ldb_dn_get_rdn_name(dn);
943 if (name == NULL) {
944 Py_RETURN_NONE;
947 return PyUnicode_FromString(name);
950 static PyObject *py_ldb_dn_get_rdn_value(PyObject *self,
951 PyObject *Py_UNUSED(ignored))
953 struct ldb_dn *dn = NULL;
954 const struct ldb_val *val;
956 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
958 val = ldb_dn_get_rdn_val(dn);
959 if (val == NULL) {
960 Py_RETURN_NONE;
963 return PyStr_FromLdbValue(val);
966 static PyMethodDef py_ldb_dn_methods[] = {
967 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
968 "S.validate() -> bool\n"
969 "Validate DN is correct." },
970 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
971 "S.is_valid() -> bool\n" },
972 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
973 "S.is_special() -> bool\n"
974 "Check whether this is a special LDB DN." },
975 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
976 "Check whether this is a null DN." },
977 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
978 NULL },
979 { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
980 py_ldb_dn_get_linearized),
981 METH_NOARGS,
982 NULL },
983 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
984 "S.canonical_str() -> string\n"
985 "Canonical version of this DN (like a posix path)." },
986 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
987 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
988 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
989 "S.canonical_ex_str() -> string\n"
990 "Canonical version of this DN (like a posix path, with terminating newline)." },
991 { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
992 py_ldb_dn_extended_str),
993 METH_VARARGS | METH_KEYWORDS,
994 "S.extended_str(mode=1) -> string\n"
995 "Extended version of this DN" },
996 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
997 "S.parent() -> dn\n"
998 "Get the parent for this DN." },
999 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
1000 "S.add_child(dn) -> bool\n"
1001 "Add a child DN to this DN." },
1002 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
1003 "S.add_base(dn) -> bool\n"
1004 "Add a base DN to this DN." },
1005 { "copy", (PyCFunction)py_ldb_dn_copy_method, METH_VARARGS,
1006 "dn.copy(ldb) -> dn\n"
1007 "Make a copy of this DN, attached to the given ldb object." },
1008 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
1009 "S.remove_base_components(int) -> bool\n"
1010 "Remove a number of DN components from the base of this DN." },
1011 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
1012 "S.check_special(name) -> bool\n\n"
1013 "Check if name is a special DN name"},
1014 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
1015 "S.get_extended_component(name) -> string\n\n"
1016 "returns a DN extended component as a binary string"},
1017 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
1018 "S.set_extended_component(name, value) -> None\n\n"
1019 "set a DN extended component as a binary string"},
1020 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
1021 "S.get_component_name(num) -> string\n"
1022 "get the attribute name of the specified component" },
1023 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
1024 "S.get_component_value(num) -> string\n"
1025 "get the attribute value of the specified component as a binary string" },
1026 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
1027 "S.set_component(num, name, value) -> None\n"
1028 "set the attribute name and value of the specified component" },
1029 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
1030 "S.get_rdn_name() -> string\n"
1031 "get the RDN attribute name" },
1032 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
1033 "S.get_rdn_value() -> string\n"
1034 "get the RDN attribute value as a binary string" },
1039 static PyObject *py_ldb_dn_get_ldb(PyLdbDnObject *self, void *closure)
1041 if (self->pyldb == NULL) {
1042 Py_RETURN_NONE;
1044 Py_INCREF(self->pyldb);
1045 return (PyObject *)self->pyldb;
1049 static PyGetSetDef py_ldb_dn_getset[] = {
1051 .name = discard_const_p(char, "ldb"),
1052 .get = (getter)py_ldb_dn_get_ldb,
1053 .doc = discard_const_p( /* for Py 3.6; 3.7+ have const char* */
1054 char, "returns the associated ldb object (or None)")
1056 { .name = NULL },
1060 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
1062 struct ldb_dn *dn = pyldb_Dn_AS_DN(self);
1063 if (dn == NULL || self->pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn)) {
1064 return -1;
1067 return ldb_dn_get_comp_num(dn);
1071 copy a DN as a python object
1073 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn, PyLdbObject *pyldb)
1075 TALLOC_CTX *mem_ctx = NULL;
1076 struct ldb_dn *new_dn = NULL;
1077 PyLdbDnObject *py_ret;
1079 if (ldb_dn_get_ldb_context(dn) != pyldb->ldb_ctx) {
1081 * We can't do this, because we can't (for now) change the ldb
1082 * pointer of the underlying dn returned by ldb_dn_copy().
1084 * This error means someone editing this file got confused,
1085 * which is quite understandable.
1087 PyErr_SetString(PyExc_RuntimeError,
1088 "py_ldb_dn_copy can't copy to a new LDB");
1089 return NULL;
1092 mem_ctx = talloc_new(NULL);
1093 if (mem_ctx == NULL) {
1094 return PyErr_NoMemory();
1097 new_dn = ldb_dn_copy(mem_ctx, dn);
1098 if (new_dn == NULL) {
1099 talloc_free(mem_ctx);
1100 return PyErr_NoMemory();
1103 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
1104 if (py_ret == NULL) {
1105 talloc_free(mem_ctx);
1106 PyErr_NoMemory();
1107 return NULL;
1109 py_ret->mem_ctx = mem_ctx;
1110 py_ret->dn = new_dn;
1112 py_ret->pyldb = pyldb;
1113 Py_INCREF(py_ret->pyldb);
1114 return (PyObject *)py_ret;
1117 static PyObject *py_ldb_dn_concat(PyObject *self, PyObject *py_other)
1119 TALLOC_CTX *mem_ctx = NULL;
1120 struct ldb_dn *dn = NULL;
1121 struct ldb_dn *other = NULL;
1123 struct ldb_dn *new_dn = NULL;
1124 PyLdbDnObject *py_ret = NULL;
1127 PyErr_internal_LDB_DN_OR_RAISE(self, dn);
1128 PyErr_internal_LDB_DN_OR_RAISE(py_other, other);
1130 mem_ctx = talloc_new(NULL);
1131 if (mem_ctx == NULL) {
1132 return PyErr_NoMemory();
1135 new_dn = ldb_dn_copy(mem_ctx, dn);
1136 if (new_dn == NULL) {
1137 talloc_free(mem_ctx);
1138 return PyErr_NoMemory();
1141 if (!ldb_dn_add_base(new_dn, other)) {
1142 PyErr_SetString(PyExc_RuntimeError, "unable to concatenate DNs");
1143 talloc_free(mem_ctx);
1144 return NULL;
1147 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
1148 if (py_ret == NULL) {
1149 talloc_free(mem_ctx);
1150 PyErr_NoMemory();
1151 return NULL;
1153 py_ret->mem_ctx = mem_ctx;
1154 py_ret->dn = new_dn;
1156 py_ret->pyldb = ((PyLdbDnObject *)self)->pyldb;
1157 Py_INCREF(py_ret->pyldb);
1159 return (PyObject *)py_ret;
1162 static PySequenceMethods py_ldb_dn_seq = {
1163 .sq_length = (lenfunc)py_ldb_dn_len,
1164 .sq_concat = (binaryfunc)py_ldb_dn_concat,
1167 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1169 struct ldb_dn *ret = NULL;
1170 char *str = NULL;
1171 PyObject *py_ldb = NULL;
1172 struct ldb_context *ldb_ctx = NULL;
1173 TALLOC_CTX *mem_ctx = NULL;
1174 PyLdbDnObject *py_ret = NULL;
1175 const char * const kwnames[] = { "ldb", "dn", NULL };
1177 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!"PYARG_STR_UNI,
1178 discard_const_p(char *, kwnames),
1179 &PyLdb, &py_ldb, "utf8", &str))
1180 goto out;
1182 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
1184 mem_ctx = talloc_new(NULL);
1185 if (mem_ctx == NULL) {
1186 PyErr_NoMemory();
1187 goto out;
1190 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
1191 if (!ldb_dn_validate(ret)) {
1192 talloc_free(mem_ctx);
1193 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
1194 goto out;
1197 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
1198 if (py_ret == NULL) {
1199 talloc_free(mem_ctx);
1200 PyErr_NoMemory();
1201 goto out;
1203 py_ret->mem_ctx = mem_ctx;
1204 py_ret->dn = ret;
1205 py_ret->pyldb = (PyLdbObject *)py_ldb;
1206 Py_INCREF(py_ret->pyldb);
1207 out:
1208 if (str != NULL) {
1209 PyMem_Free(discard_const_p(char, str));
1211 return (PyObject *)py_ret;
1214 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
1216 talloc_free(self->mem_ctx);
1217 Py_DECREF(self->pyldb);
1218 PyObject_Del(self);
1221 static PyTypeObject PyLdbDn = {
1222 .tp_name = "ldb.Dn",
1223 .tp_methods = py_ldb_dn_methods,
1224 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
1225 .tp_repr = (reprfunc)py_ldb_dn_repr,
1226 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
1227 .tp_as_sequence = &py_ldb_dn_seq,
1228 .tp_getset = py_ldb_dn_getset,
1229 .tp_doc = "A LDB distinguished name.",
1230 .tp_new = py_ldb_dn_new,
1231 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
1232 .tp_basicsize = sizeof(PyLdbDnObject),
1233 .tp_flags = Py_TPFLAGS_DEFAULT,
1236 /* Debug */
1237 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
1238 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
1240 PyObject *fn = (PyObject *)context;
1241 PyObject *result = NULL;
1242 result = PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
1243 Py_XDECREF(result);
1246 static PyObject *py_ldb_debug_func;
1248 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
1250 PyObject *cb;
1251 struct ldb_context *ldb_ctx;
1253 if (!PyArg_ParseTuple(args, "O", &cb))
1254 return NULL;
1256 if (py_ldb_debug_func != NULL) {
1257 Py_DECREF(py_ldb_debug_func);
1260 Py_INCREF(cb);
1261 /* FIXME: DECREF cb when exiting program */
1262 py_ldb_debug_func = cb;
1263 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1264 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
1265 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
1266 ldb_ctx);
1268 Py_RETURN_NONE;
1271 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1273 unsigned int perms;
1274 if (!PyArg_ParseTuple(args, "I", &perms))
1275 return NULL;
1277 ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
1279 Py_RETURN_NONE;
1282 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1284 char *modules_dir;
1285 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1286 return NULL;
1288 ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
1290 Py_RETURN_NONE;
1293 static PyObject *py_ldb_transaction_start(PyLdbObject *self,
1294 PyObject *Py_UNUSED(ignored))
1296 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1297 int ldb_err;
1298 ldb_err = ldb_transaction_start(ldb_ctx);
1299 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1300 Py_RETURN_NONE;
1303 static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
1304 PyObject *Py_UNUSED(ignored))
1306 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1307 int ldb_err;
1308 ldb_err = ldb_transaction_commit(ldb_ctx);
1309 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1310 Py_RETURN_NONE;
1313 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
1314 PyObject *Py_UNUSED(ignored))
1316 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1317 int ldb_err;
1318 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1319 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1320 Py_RETURN_NONE;
1323 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
1324 PyObject *Py_UNUSED(ignored))
1326 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1327 int ldb_err;
1328 ldb_err = ldb_transaction_cancel(ldb_ctx);
1329 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1330 Py_RETURN_NONE;
1333 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
1334 PyObject *Py_UNUSED(ignored))
1336 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1337 int ldb_err;
1338 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1339 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1340 Py_RETURN_NONE;
1343 static PyObject *py_ldb_repr(PyLdbObject *self)
1345 return PyUnicode_FromString("<ldb connection>");
1348 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1349 PyObject *Py_UNUSED(ignored))
1351 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1352 if (dn == NULL)
1353 Py_RETURN_NONE;
1354 return py_ldb_dn_copy(dn, self);
1358 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1359 PyObject *Py_UNUSED(ignored))
1361 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1362 if (dn == NULL)
1363 Py_RETURN_NONE;
1364 return py_ldb_dn_copy(dn, self);
1367 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1368 PyObject *Py_UNUSED(ignored))
1370 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1371 if (dn == NULL)
1372 Py_RETURN_NONE;
1373 return py_ldb_dn_copy(dn, self);
1376 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1377 PyObject *Py_UNUSED(ignored))
1379 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1380 if (dn == NULL)
1381 Py_RETURN_NONE;
1382 return py_ldb_dn_copy(dn, self);
1385 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1386 const char *paramname)
1388 const char **ret;
1389 Py_ssize_t i;
1390 if (!PyList_Check(list)) {
1391 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1392 return NULL;
1394 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1395 if (ret == NULL) {
1396 PyErr_NoMemory();
1397 return NULL;
1400 for (i = 0; i < PyList_Size(list); i++) {
1401 const char *str = NULL;
1402 Py_ssize_t size;
1403 PyObject *item = PyList_GetItem(list, i);
1404 if (!PyUnicode_Check(item)) {
1405 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1406 talloc_free(ret);
1407 return NULL;
1409 str = PyUnicode_AsUTF8AndSize(item, &size);
1410 if (str == NULL) {
1411 talloc_free(ret);
1412 return NULL;
1414 ret[i] = talloc_strndup(ret, str, size);
1416 ret[i] = NULL;
1417 return ret;
1420 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs);
1422 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1424 const char * const kwnames[] = { "url", "flags", "options", NULL };
1425 char *url = NULL;
1426 PyObject *py_options = NULL;
1427 unsigned int flags = 0;
1429 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1430 discard_const_p(char *, kwnames),
1431 &url, &flags, &py_options)) {
1432 return -1;
1435 if (url != NULL) {
1436 /* py_ldb_connect returns py_None on success, NULL on error */
1437 PyObject *result = py_ldb_connect(self, args, kwargs);
1438 if (result == NULL) {
1439 return -1;
1441 Py_DECREF(result);
1442 } else {
1443 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1444 ldb_set_flags(ldb, flags);
1447 return 0;
1450 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1452 TALLOC_CTX *mem_ctx = NULL;
1453 PyLdbObject *ret;
1454 struct ldb_context *ldb;
1456 mem_ctx = talloc_new(NULL);
1457 if (mem_ctx == NULL) {
1458 return PyErr_NoMemory();
1461 ldb = ldb_init(mem_ctx, NULL);
1462 if (ldb == NULL) {
1463 talloc_free(mem_ctx);
1464 PyErr_NoMemory();
1465 return NULL;
1468 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1469 if (ret == NULL) {
1470 talloc_free(mem_ctx);
1471 PyErr_NoMemory();
1472 return NULL;
1474 ret->mem_ctx = mem_ctx;
1476 ret->ldb_ctx = ldb;
1477 return (PyObject *)ret;
1480 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1482 char *url = NULL;
1483 unsigned int flags = 0;
1484 PyObject *py_options = Py_None;
1485 int ret;
1486 const char **options;
1487 const char * const kwnames[] = { "url", "flags", "options", NULL };
1488 struct ldb_context *ldb_ctx;
1490 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1491 discard_const_p(char *, kwnames),
1492 &url, &flags, &py_options))
1493 return NULL;
1495 if (py_options == Py_None) {
1496 options = NULL;
1497 } else {
1498 options = PyList_AsStrList(NULL, py_options, "options");
1499 if (options == NULL)
1500 return NULL;
1503 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1504 ret = ldb_connect(ldb_ctx, url, flags, options);
1505 talloc_free(options);
1507 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1509 Py_RETURN_NONE;
1512 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1514 PyObject *py_msg;
1515 PyObject *py_controls = Py_None;
1516 struct ldb_context *ldb_ctx;
1517 struct ldb_request *req;
1518 struct ldb_control **parsed_controls;
1519 struct ldb_message *msg;
1520 int ret;
1521 TALLOC_CTX *mem_ctx;
1522 bool validate=true;
1523 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1525 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1526 discard_const_p(char *, kwnames),
1527 &py_msg, &py_controls, &validate))
1528 return NULL;
1530 mem_ctx = talloc_new(NULL);
1531 if (mem_ctx == NULL) {
1532 PyErr_NoMemory();
1533 return NULL;
1535 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1537 if (py_controls == Py_None) {
1538 parsed_controls = NULL;
1539 } else {
1540 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1541 if (controls == NULL) {
1542 talloc_free(mem_ctx);
1543 return NULL;
1545 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1546 if (controls[0] != NULL && parsed_controls == NULL) {
1547 talloc_free(mem_ctx);
1548 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1549 return NULL;
1551 talloc_free(controls);
1554 if (!pyldb_Message_Check(py_msg)) {
1555 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1556 talloc_free(mem_ctx);
1557 return NULL;
1559 msg = pyldb_Message_AsMessage(py_msg);
1561 if (validate) {
1562 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1563 if (ret != LDB_SUCCESS) {
1564 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1565 talloc_free(mem_ctx);
1566 return NULL;
1570 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1571 NULL, ldb_op_default_callback, NULL);
1572 if (ret != LDB_SUCCESS) {
1573 PyErr_SetString(PyExc_TypeError, "failed to build request");
1574 talloc_free(mem_ctx);
1575 return NULL;
1578 /* do request and autostart a transaction */
1579 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1581 ret = ldb_transaction_start(ldb_ctx);
1582 if (ret != LDB_SUCCESS) {
1583 talloc_free(mem_ctx);
1584 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1585 return NULL;
1588 ret = ldb_request(ldb_ctx, req);
1589 if (ret == LDB_SUCCESS) {
1590 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1593 if (ret == LDB_SUCCESS) {
1594 ret = ldb_transaction_commit(ldb_ctx);
1595 } else {
1596 ldb_transaction_cancel(ldb_ctx);
1599 talloc_free(mem_ctx);
1600 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1602 Py_RETURN_NONE;
1607 * Obtain a ldb message from a Python Dictionary object.
1609 * @param mem_ctx Memory context
1610 * @param py_obj Python Dictionary object
1611 * @param ldb_ctx LDB context
1612 * @param mod_flags Flags to be set on every message element
1613 * @return ldb_message on success or NULL on failure
1615 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1616 PyObject *py_obj,
1617 struct ldb_context *ldb_ctx,
1618 unsigned int mod_flags)
1620 struct ldb_message *msg;
1621 unsigned int msg_pos = 0;
1622 Py_ssize_t dict_pos = 0;
1623 PyObject *key, *value;
1624 struct ldb_message_element *msg_el;
1625 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1627 msg = ldb_msg_new(mem_ctx);
1628 if (msg == NULL) {
1629 PyErr_NoMemory();
1630 return NULL;
1632 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1633 if (msg->elements == NULL) {
1634 PyErr_NoMemory();
1635 TALLOC_FREE(msg);
1636 return NULL;
1639 if (dn_value) {
1640 struct ldb_dn *dn = NULL;
1641 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &dn)) {
1642 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1643 TALLOC_FREE(msg);
1644 return NULL;
1646 if (dn == NULL) {
1647 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1648 TALLOC_FREE(msg);
1649 return NULL;
1651 msg->dn = talloc_reference(msg, dn);
1652 if (msg->dn == NULL) {
1653 talloc_free(mem_ctx);
1654 PyErr_NoMemory();
1655 return NULL;
1657 } else {
1658 PyErr_SetString(PyExc_TypeError, "no dn set");
1659 TALLOC_FREE(msg);
1660 return NULL;
1663 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1664 const char *key_str = PyUnicode_AsUTF8(key);
1665 if (ldb_attr_cmp(key_str, "dn") != 0) {
1666 msg_el = PyObject_AsMessageElement(msg->elements, value,
1667 mod_flags, key_str);
1668 if (msg_el == NULL) {
1669 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1670 TALLOC_FREE(msg);
1671 return NULL;
1673 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1676 * PyObject_AsMessageElement might have returned a
1677 * reference to an existing MessageElement, and so left
1678 * the name and flags unchanged. Thus if those members
1679 * aren’t set, we’ll assume that the user forgot to
1680 * initialize them.
1682 if (msg->elements[msg_pos].name == NULL) {
1683 /* No name was set — set it now. */
1684 msg->elements[msg_pos].name = talloc_strdup(msg->elements, key_str);
1685 if (msg->elements[msg_pos].name == NULL) {
1686 PyErr_NoMemory();
1687 TALLOC_FREE(msg);
1688 return NULL;
1691 if (msg->elements[msg_pos].flags == 0) {
1692 /* No flags were set — set them now. */
1693 msg->elements[msg_pos].flags = mod_flags;
1696 msg_pos++;
1700 msg->num_elements = msg_pos;
1702 return msg;
1705 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1707 PyObject *py_obj;
1708 int ret;
1709 struct ldb_context *ldb_ctx;
1710 struct ldb_request *req;
1711 struct ldb_message *msg = NULL;
1712 PyObject *py_controls = Py_None;
1713 TALLOC_CTX *mem_ctx;
1714 struct ldb_control **parsed_controls;
1715 const char * const kwnames[] = { "message", "controls", NULL };
1717 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1718 discard_const_p(char *, kwnames),
1719 &py_obj, &py_controls))
1720 return NULL;
1722 mem_ctx = talloc_new(NULL);
1723 if (mem_ctx == NULL) {
1724 PyErr_NoMemory();
1725 return NULL;
1727 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1729 if (py_controls == Py_None) {
1730 parsed_controls = NULL;
1731 } else {
1732 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1733 if (controls == NULL) {
1734 talloc_free(mem_ctx);
1735 return NULL;
1737 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1738 if (controls[0] != NULL && parsed_controls == NULL) {
1739 talloc_free(mem_ctx);
1740 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1741 return NULL;
1743 talloc_free(controls);
1746 if (pyldb_Message_Check(py_obj)) {
1747 msg = pyldb_Message_AsMessage(py_obj);
1748 } else if (PyDict_Check(py_obj)) {
1749 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1750 } else {
1751 PyErr_SetString(PyExc_TypeError,
1752 "Dictionary or LdbMessage object expected!");
1755 if (!msg) {
1756 /* we should have a PyErr already set */
1757 talloc_free(mem_ctx);
1758 return NULL;
1761 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1762 if (ret != LDB_SUCCESS) {
1763 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1764 talloc_free(mem_ctx);
1765 return NULL;
1768 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1769 NULL, ldb_op_default_callback, NULL);
1770 if (ret != LDB_SUCCESS) {
1771 PyErr_SetString(PyExc_TypeError, "failed to build request");
1772 talloc_free(mem_ctx);
1773 return NULL;
1776 /* do request and autostart a transaction */
1777 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1779 ret = ldb_transaction_start(ldb_ctx);
1780 if (ret != LDB_SUCCESS) {
1781 talloc_free(mem_ctx);
1782 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1783 return NULL;
1786 ret = ldb_request(ldb_ctx, req);
1787 if (ret == LDB_SUCCESS) {
1788 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1791 if (ret == LDB_SUCCESS) {
1792 ret = ldb_transaction_commit(ldb_ctx);
1793 } else {
1794 ldb_transaction_cancel(ldb_ctx);
1797 talloc_free(mem_ctx);
1798 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1800 Py_RETURN_NONE;
1803 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1805 PyObject *py_dn;
1806 struct ldb_dn *dn;
1807 int ret;
1808 struct ldb_context *ldb_ctx;
1809 struct ldb_request *req;
1810 PyObject *py_controls = Py_None;
1811 TALLOC_CTX *mem_ctx;
1812 struct ldb_control **parsed_controls;
1813 const char * const kwnames[] = { "dn", "controls", NULL };
1815 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1816 discard_const_p(char *, kwnames),
1817 &py_dn, &py_controls))
1818 return NULL;
1820 mem_ctx = talloc_new(NULL);
1821 if (mem_ctx == NULL) {
1822 PyErr_NoMemory();
1823 return NULL;
1825 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1827 if (py_controls == Py_None) {
1828 parsed_controls = NULL;
1829 } else {
1830 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1831 if (controls == NULL) {
1832 talloc_free(mem_ctx);
1833 return NULL;
1835 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1836 if (controls[0] != NULL && parsed_controls == NULL) {
1837 talloc_free(mem_ctx);
1838 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1839 return NULL;
1841 talloc_free(controls);
1844 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1845 talloc_free(mem_ctx);
1846 return NULL;
1849 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1850 NULL, ldb_op_default_callback, NULL);
1851 if (ret != LDB_SUCCESS) {
1852 PyErr_SetString(PyExc_TypeError, "failed to build request");
1853 talloc_free(mem_ctx);
1854 return NULL;
1857 /* do request and autostart a transaction */
1858 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1860 ret = ldb_transaction_start(ldb_ctx);
1861 if (ret != LDB_SUCCESS) {
1862 talloc_free(mem_ctx);
1863 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1864 return NULL;
1867 ret = ldb_request(ldb_ctx, req);
1868 if (ret == LDB_SUCCESS) {
1869 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1872 if (ret == LDB_SUCCESS) {
1873 ret = ldb_transaction_commit(ldb_ctx);
1874 } else {
1875 ldb_transaction_cancel(ldb_ctx);
1878 talloc_free(mem_ctx);
1879 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1881 Py_RETURN_NONE;
1884 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1886 PyObject *py_dn1, *py_dn2;
1887 struct ldb_dn *dn1, *dn2;
1888 int ret;
1889 TALLOC_CTX *mem_ctx;
1890 PyObject *py_controls = Py_None;
1891 struct ldb_control **parsed_controls;
1892 struct ldb_context *ldb_ctx;
1893 struct ldb_request *req;
1894 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1896 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1898 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1899 discard_const_p(char *, kwnames),
1900 &py_dn1, &py_dn2, &py_controls))
1901 return NULL;
1904 mem_ctx = talloc_new(NULL);
1905 if (mem_ctx == NULL) {
1906 PyErr_NoMemory();
1907 return NULL;
1910 if (py_controls == Py_None) {
1911 parsed_controls = NULL;
1912 } else {
1913 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1914 if (controls == NULL) {
1915 talloc_free(mem_ctx);
1916 return NULL;
1918 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1919 if (controls[0] != NULL && parsed_controls == NULL) {
1920 talloc_free(mem_ctx);
1921 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1922 return NULL;
1924 talloc_free(controls);
1928 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1929 talloc_free(mem_ctx);
1930 return NULL;
1933 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1934 talloc_free(mem_ctx);
1935 return NULL;
1938 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1939 NULL, ldb_op_default_callback, NULL);
1940 if (ret != LDB_SUCCESS) {
1941 PyErr_SetString(PyExc_TypeError, "failed to build request");
1942 talloc_free(mem_ctx);
1943 return NULL;
1946 /* do request and autostart a transaction */
1947 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1949 ret = ldb_transaction_start(ldb_ctx);
1950 if (ret != LDB_SUCCESS) {
1951 talloc_free(mem_ctx);
1952 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1953 return NULL;
1956 ret = ldb_request(ldb_ctx, req);
1957 if (ret == LDB_SUCCESS) {
1958 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1961 if (ret == LDB_SUCCESS) {
1962 ret = ldb_transaction_commit(ldb_ctx);
1963 } else {
1964 ldb_transaction_cancel(ldb_ctx);
1967 talloc_free(mem_ctx);
1968 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1970 Py_RETURN_NONE;
1973 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1975 char *name;
1976 if (!PyArg_ParseTuple(args, "s", &name))
1977 return NULL;
1979 ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1981 Py_RETURN_NONE;
1984 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1986 char *attribute, *syntax;
1987 unsigned int flags;
1988 int ret;
1989 struct ldb_context *ldb_ctx;
1991 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1992 return NULL;
1994 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1995 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1997 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1999 Py_RETURN_NONE;
2002 static PyObject *ldb_ldif_to_pyobject(PyLdbObject *pyldb, struct ldb_ldif *ldif)
2004 PyObject *obj = NULL;
2005 PyObject *result = NULL;
2006 struct ldb_context *ldb = pyldb->ldb_ctx;
2008 if (ldif == NULL) {
2009 Py_RETURN_NONE;
2012 switch (ldif->changetype) {
2013 case LDB_CHANGETYPE_NONE:
2014 case LDB_CHANGETYPE_ADD:
2015 obj = PyLdbMessage_FromMessage(ldif->msg, pyldb);
2016 break;
2017 case LDB_CHANGETYPE_MODIFY:
2018 obj = PyLdbMessage_FromMessage(ldif->msg, pyldb);
2019 break;
2020 case LDB_CHANGETYPE_DELETE:
2021 if (ldif->msg->num_elements != 0) {
2022 PyErr_Format(PyExc_ValueError,
2023 "CHANGETYPE(DELETE) with num_elements=%u",
2024 ldif->msg->num_elements);
2025 return NULL;
2027 obj = pyldb_Dn_FromDn(ldif->msg->dn, pyldb);
2028 break;
2029 case LDB_CHANGETYPE_MODRDN: {
2030 struct ldb_dn *olddn = NULL;
2031 PyObject *olddn_obj = NULL;
2032 bool deleteoldrdn = false;
2033 PyObject *deleteoldrdn_obj = NULL;
2034 struct ldb_dn *newdn = NULL;
2035 PyObject *newdn_obj = NULL;
2036 int ret;
2038 ret = ldb_ldif_parse_modrdn(ldb,
2039 ldif,
2040 ldif,
2041 &olddn,
2042 NULL,
2043 &deleteoldrdn,
2044 NULL,
2045 &newdn);
2046 if (ret != LDB_SUCCESS) {
2047 PyErr_Format(PyExc_ValueError,
2048 "ldb_ldif_parse_modrdn() failed");
2049 return NULL;
2052 olddn_obj = pyldb_Dn_FromDn(olddn, pyldb);
2053 if (olddn_obj == NULL) {
2054 return NULL;
2056 if (deleteoldrdn) {
2057 deleteoldrdn_obj = Py_True;
2058 } else {
2059 deleteoldrdn_obj = Py_False;
2061 newdn_obj = pyldb_Dn_FromDn(newdn, pyldb);
2062 if (newdn_obj == NULL) {
2063 deleteoldrdn_obj = NULL;
2064 Py_CLEAR(olddn_obj);
2065 return NULL;
2068 obj = Py_BuildValue(discard_const_p(char, "{s:O,s:O,s:O}"),
2069 "olddn", olddn_obj,
2070 "deleteoldrdn", deleteoldrdn_obj,
2071 "newdn", newdn_obj);
2072 Py_CLEAR(olddn_obj);
2073 deleteoldrdn_obj = NULL;
2074 Py_CLEAR(newdn_obj);
2076 break;
2077 default:
2078 PyErr_Format(PyExc_NotImplementedError,
2079 "Unsupported LDB_CHANGETYPE(%u)",
2080 ldif->changetype);
2081 return NULL;
2084 if (obj == NULL) {
2085 return NULL;
2088 /* We don't want this being attached * to the 'ldb' any more */
2089 result = Py_BuildValue(discard_const_p(char, "(iO)"),
2090 ldif->changetype,
2091 obj);
2092 Py_CLEAR(obj);
2093 return result;
2097 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
2099 int changetype;
2100 PyObject *py_msg;
2101 struct ldb_ldif ldif;
2102 PyObject *ret;
2103 char *string;
2104 TALLOC_CTX *mem_ctx;
2106 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
2107 return NULL;
2109 if (!pyldb_Message_Check(py_msg)) {
2110 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
2111 return NULL;
2114 ldif.msg = pyldb_Message_AsMessage(py_msg);
2115 ldif.changetype = changetype;
2117 mem_ctx = talloc_new(NULL);
2118 if (mem_ctx == NULL) {
2119 return PyErr_NoMemory();
2122 string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
2123 if (!string) {
2124 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
2125 talloc_free(mem_ctx);
2126 return NULL;
2129 ret = PyUnicode_FromString(string);
2131 talloc_free(mem_ctx);
2133 return ret;
2136 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
2138 PyObject *list, *ret;
2139 struct ldb_ldif *ldif;
2140 const char *s;
2141 struct ldb_dn *last_dn = NULL;
2143 TALLOC_CTX *mem_ctx;
2145 if (!PyArg_ParseTuple(args, "s", &s))
2146 return NULL;
2148 mem_ctx = talloc_new(NULL);
2149 if (!mem_ctx) {
2150 Py_RETURN_NONE;
2153 list = PyList_New(0);
2154 if (list == NULL) {
2155 talloc_free(mem_ctx);
2156 return NULL;
2159 while (s && *s != '\0') {
2160 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
2161 talloc_steal(mem_ctx, ldif);
2162 if (ldif) {
2163 int res = 0;
2164 PyObject *py_ldif = ldb_ldif_to_pyobject(self, ldif);
2165 if (py_ldif == NULL) {
2166 Py_CLEAR(list);
2167 if (PyErr_Occurred() == NULL) {
2168 PyErr_BadArgument();
2170 talloc_free(mem_ctx);
2171 return NULL;
2173 res = PyList_Append(list, py_ldif);
2174 Py_CLEAR(py_ldif);
2175 if (res == -1) {
2176 Py_CLEAR(list);
2177 talloc_free(mem_ctx);
2178 return NULL;
2180 last_dn = ldif->msg->dn;
2181 } else {
2182 const char *last_dn_str = NULL;
2183 const char *err_string = NULL;
2184 if (last_dn == NULL) {
2185 PyErr_SetString(PyExc_ValueError,
2186 "unable to parse LDIF "
2187 "string at first chunk");
2188 Py_CLEAR(list);
2189 talloc_free(mem_ctx);
2190 return NULL;
2193 last_dn_str
2194 = ldb_dn_get_linearized(last_dn);
2196 err_string
2197 = talloc_asprintf(mem_ctx,
2198 "unable to parse ldif "
2199 "string AFTER %s",
2200 last_dn_str);
2202 PyErr_SetString(PyExc_ValueError,
2203 err_string);
2204 talloc_free(mem_ctx);
2205 Py_CLEAR(list);
2206 return NULL;
2209 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
2210 ret = PyObject_GetIter(list);
2211 Py_DECREF(list);
2212 return ret;
2215 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
2217 int ldb_ret;
2218 PyObject *py_msg_old;
2219 PyObject *py_msg_new;
2220 struct ldb_message *diff;
2221 struct ldb_context *ldb;
2222 PyObject *py_ret;
2223 TALLOC_CTX *mem_ctx = NULL;
2225 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
2226 return NULL;
2228 if (!pyldb_Message_Check(py_msg_old)) {
2229 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
2230 return NULL;
2233 if (!pyldb_Message_Check(py_msg_new)) {
2234 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
2235 return NULL;
2238 mem_ctx = talloc_new(NULL);
2239 if (mem_ctx == NULL) {
2240 PyErr_NoMemory();
2241 return NULL;
2244 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2245 ldb_ret = ldb_msg_difference(ldb, mem_ctx,
2246 pyldb_Message_AsMessage(py_msg_old),
2247 pyldb_Message_AsMessage(py_msg_new),
2248 &diff);
2249 if (ldb_ret != LDB_SUCCESS) {
2250 talloc_free(mem_ctx);
2251 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
2252 return NULL;
2255 diff = ldb_msg_copy(mem_ctx, diff);
2256 if (diff == NULL) {
2257 talloc_free(mem_ctx);
2258 PyErr_NoMemory();
2259 return NULL;
2262 py_ret = PyLdbMessage_FromMessage(diff, self);
2264 talloc_free(mem_ctx);
2266 return py_ret;
2269 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
2271 const struct ldb_schema_attribute *a;
2272 struct ldb_val old_val;
2273 struct ldb_val new_val;
2274 TALLOC_CTX *mem_ctx;
2275 PyObject *ret;
2276 char *element_name;
2277 PyObject *val;
2278 Py_ssize_t size;
2279 int result;
2281 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
2282 return NULL;
2284 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
2285 old_val.length = size;
2287 if (result != 0) {
2288 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
2289 return NULL;
2292 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
2294 if (a == NULL) {
2295 Py_RETURN_NONE;
2298 mem_ctx = talloc_new(NULL);
2299 if (mem_ctx == NULL) {
2300 PyErr_NoMemory();
2301 return NULL;
2304 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
2305 talloc_free(mem_ctx);
2306 Py_RETURN_NONE;
2309 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
2311 talloc_free(mem_ctx);
2313 return ret;
2316 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2318 PyObject *py_base = Py_None;
2319 int scope = LDB_SCOPE_DEFAULT;
2320 char *expr = NULL;
2321 PyObject *py_attrs = Py_None;
2322 PyObject *py_controls = Py_None;
2323 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
2324 int ret;
2325 struct ldb_result *res;
2326 struct ldb_request *req;
2327 const char **attrs;
2328 struct ldb_context *ldb_ctx;
2329 struct ldb_control **parsed_controls;
2330 struct ldb_dn *base;
2331 PyObject *py_ret;
2332 TALLOC_CTX *mem_ctx;
2334 /* type "int" rather than "enum" for "scope" is intentional */
2335 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
2336 discard_const_p(char *, kwnames),
2337 &py_base, &scope, &expr, &py_attrs, &py_controls))
2338 return NULL;
2341 mem_ctx = talloc_new(NULL);
2342 if (mem_ctx == NULL) {
2343 PyErr_NoMemory();
2344 return NULL;
2346 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2348 if (py_attrs == Py_None) {
2349 attrs = NULL;
2350 } else {
2351 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
2352 if (attrs == NULL) {
2353 talloc_free(mem_ctx);
2354 return NULL;
2358 if (py_base == Py_None) {
2359 base = ldb_get_default_basedn(ldb_ctx);
2360 } else {
2361 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
2362 talloc_free(mem_ctx);
2363 return NULL;
2367 if (py_controls == Py_None) {
2368 parsed_controls = NULL;
2369 } else {
2370 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
2371 if (controls == NULL) {
2372 talloc_free(mem_ctx);
2373 return NULL;
2375 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
2376 if (controls[0] != NULL && parsed_controls == NULL) {
2377 talloc_free(mem_ctx);
2378 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2379 return NULL;
2381 talloc_free(controls);
2384 res = talloc_zero(mem_ctx, struct ldb_result);
2385 if (res == NULL) {
2386 PyErr_NoMemory();
2387 talloc_free(mem_ctx);
2388 return NULL;
2391 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
2392 base,
2393 scope,
2394 expr,
2395 attrs,
2396 parsed_controls,
2397 res,
2398 ldb_search_default_callback,
2399 NULL);
2401 if (ret != LDB_SUCCESS) {
2402 talloc_free(mem_ctx);
2403 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2404 return NULL;
2407 talloc_steal(req, attrs);
2409 ret = ldb_request(ldb_ctx, req);
2411 if (ret == LDB_SUCCESS) {
2412 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2415 if (ret != LDB_SUCCESS) {
2416 talloc_free(mem_ctx);
2417 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2418 return NULL;
2421 py_ret = PyLdbResult_FromResult(res, self);
2423 talloc_free(mem_ctx);
2425 return py_ret;
2428 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
2430 if (reply->py_iter != NULL) {
2431 DLIST_REMOVE(reply->py_iter->state.next, reply);
2432 if (reply->py_iter->state.result == reply) {
2433 reply->py_iter->state.result = NULL;
2435 reply->py_iter = NULL;
2438 Py_CLEAR(reply->obj);
2440 return 0;
2443 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2444 struct ldb_reply *ares)
2446 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2447 struct ldb_result result = { .msgs = NULL };
2448 struct py_ldb_search_iterator_reply *reply = NULL;
2450 if (ares == NULL) {
2451 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2454 if (ares->error != LDB_SUCCESS) {
2455 int ret = ares->error;
2456 TALLOC_FREE(ares);
2457 return ldb_request_done(req, ret);
2460 reply = talloc_zero(py_iter->mem_ctx,
2461 struct py_ldb_search_iterator_reply);
2462 if (reply == NULL) {
2463 TALLOC_FREE(ares);
2464 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2466 reply->py_iter = py_iter;
2467 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2469 switch (ares->type) {
2470 case LDB_REPLY_ENTRY:
2471 reply->obj = PyLdbMessage_FromMessage(ares->message, py_iter->ldb);
2472 if (reply->obj == NULL) {
2473 TALLOC_FREE(ares);
2474 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2476 DLIST_ADD_END(py_iter->state.next, reply);
2477 TALLOC_FREE(ares);
2478 return LDB_SUCCESS;
2480 case LDB_REPLY_REFERRAL:
2481 reply->obj = PyUnicode_FromString(ares->referral);
2482 if (reply->obj == NULL) {
2483 TALLOC_FREE(ares);
2484 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2486 DLIST_ADD_END(py_iter->state.next, reply);
2487 TALLOC_FREE(ares);
2488 return LDB_SUCCESS;
2490 case LDB_REPLY_DONE:
2491 result = (struct ldb_result) { .controls = ares->controls };
2492 reply->obj = PyLdbResult_FromResult(&result, py_iter->ldb);
2493 if (reply->obj == NULL) {
2494 TALLOC_FREE(ares);
2495 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2497 py_iter->state.result = reply;
2498 TALLOC_FREE(ares);
2499 return ldb_request_done(req, LDB_SUCCESS);
2502 TALLOC_FREE(ares);
2503 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2506 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2508 PyObject *py_base = Py_None;
2509 int scope = LDB_SCOPE_DEFAULT;
2510 int timeout = 0;
2511 char *expr = NULL;
2512 PyObject *py_attrs = Py_None;
2513 PyObject *py_controls = Py_None;
2514 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2515 int ret;
2516 const char **attrs;
2517 struct ldb_context *ldb_ctx;
2518 struct ldb_control **parsed_controls;
2519 struct ldb_dn *base;
2520 PyLdbSearchIteratorObject *py_iter;
2522 /* type "int" rather than "enum" for "scope" is intentional */
2523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2524 discard_const_p(char *, kwnames),
2525 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2526 return NULL;
2528 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2529 if (py_iter == NULL) {
2530 PyErr_NoMemory();
2531 return NULL;
2533 py_iter->ldb = self;
2534 Py_INCREF(self);
2535 ZERO_STRUCT(py_iter->state);
2536 py_iter->mem_ctx = talloc_new(NULL);
2537 if (py_iter->mem_ctx == NULL) {
2538 Py_DECREF(py_iter);
2539 PyErr_NoMemory();
2540 return NULL;
2543 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2545 if (py_attrs == Py_None) {
2546 attrs = NULL;
2547 } else {
2548 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2549 if (attrs == NULL) {
2550 Py_DECREF(py_iter);
2551 PyErr_NoMemory();
2552 return NULL;
2556 if (py_base == Py_None) {
2557 base = ldb_get_default_basedn(ldb_ctx);
2558 } else {
2559 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2560 Py_DECREF(py_iter);
2561 PyErr_NoMemory();
2562 return NULL;
2566 if (py_controls == Py_None) {
2567 parsed_controls = NULL;
2568 } else {
2569 const char **controls = NULL;
2571 controls = PyList_AsStrList(py_iter->mem_ctx,
2572 py_controls, "controls");
2573 if (controls == NULL) {
2574 Py_DECREF(py_iter);
2575 PyErr_NoMemory();
2576 return NULL;
2579 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2580 py_iter->mem_ctx,
2581 controls);
2582 if (controls[0] != NULL && parsed_controls == NULL) {
2583 Py_DECREF(py_iter);
2584 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2585 return NULL;
2587 talloc_free(controls);
2590 ret = ldb_build_search_req(&py_iter->state.req,
2591 ldb_ctx,
2592 py_iter->mem_ctx,
2593 base,
2594 scope,
2595 expr,
2596 attrs,
2597 parsed_controls,
2598 py_iter,
2599 py_ldb_search_iterator_callback,
2600 NULL);
2601 if (ret != LDB_SUCCESS) {
2602 Py_DECREF(py_iter);
2603 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2604 return NULL;
2607 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2609 ret = ldb_request(ldb_ctx, py_iter->state.req);
2610 if (ret != LDB_SUCCESS) {
2611 Py_DECREF(py_iter);
2612 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2613 return NULL;
2616 return (PyObject *)py_iter;
2619 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2621 char *name;
2622 void *data;
2624 if (!PyArg_ParseTuple(args, "s", &name))
2625 return NULL;
2627 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2629 if (data == NULL)
2630 Py_RETURN_NONE;
2632 if (data == (void *)1) {
2634 * This value is sometimes used to indicate that a opaque is
2635 * set.
2637 Py_RETURN_TRUE;
2642 * Let’s hope the opaque data is actually a talloc pointer,
2643 * otherwise calling this would be Very Bad.
2645 const bool *opaque = talloc_get_type(data, bool);
2646 if (opaque != NULL) {
2647 return PyBool_FromLong(*opaque);
2652 const unsigned long long *opaque = talloc_get_type(
2653 data, unsigned long long);
2654 if (opaque != NULL) {
2655 return PyLong_FromUnsignedLongLong(*opaque);
2660 const char *opaque = talloc_get_type(data, char);
2661 if (opaque != NULL) {
2662 return PyUnicode_FromString(opaque);
2666 PyErr_SetString(PyExc_ValueError, "Unsupported type for opaque");
2667 return NULL;
2670 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2672 char *name;
2673 PyObject *data;
2674 void *value = NULL;
2675 int ret;
2677 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2678 return NULL;
2680 if (data == Py_None) {
2681 value = NULL;
2682 } else if (PyBool_Check(data)) {
2683 bool *opaque = NULL;
2684 bool b;
2686 const int is_true = PyObject_IsTrue(data);
2687 if (is_true == -1) {
2688 return NULL;
2690 b = is_true;
2693 opaque = talloc(self->ldb_ctx, bool);
2694 if (opaque == NULL) {
2695 return PyErr_NoMemory();
2697 *opaque = b;
2698 value = opaque;
2699 } else if (PyLong_Check(data)) {
2700 unsigned long long *opaque = NULL;
2701 const unsigned long long n = PyLong_AsUnsignedLongLong(data);
2702 if (n == -1 && PyErr_Occurred()) {
2703 return NULL;
2706 opaque = talloc(self->ldb_ctx, unsigned long long);
2707 if (opaque == NULL) {
2708 return PyErr_NoMemory();
2710 *opaque = n;
2711 value = opaque;
2712 } else if (PyUnicode_Check(data)) {
2713 char *opaque = NULL;
2714 const char *s = PyUnicode_AsUTF8(data);
2715 if (s == NULL) {
2716 return NULL;
2719 opaque = talloc_strdup(self->ldb_ctx, s);
2720 if (opaque == NULL) {
2721 return PyErr_NoMemory();
2725 * Assign the right type to the talloc pointer, so that
2726 * py_ldb_get_opaque() can recognize it.
2728 talloc_set_name_const(opaque, "char");
2730 value = opaque;
2731 } else {
2732 PyErr_SetString(PyExc_ValueError,
2733 "Unsupported type for opaque");
2734 return NULL;
2737 ret = ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, value);
2738 if (ret) {
2739 PyErr_SetLdbError(PyExc_LdbError,
2740 ret,
2741 pyldb_Ldb_AS_LDBCONTEXT(self));
2742 return NULL;
2745 Py_RETURN_NONE;
2748 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2750 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2751 int type, ret;
2752 uint64_t value;
2754 if (!PyArg_ParseTuple(args, "i", &type))
2755 return NULL;
2757 /* FIXME: More interpretation */
2759 ret = ldb_sequence_number(ldb, type, &value);
2761 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2763 return PyLong_FromLongLong(value);
2766 static PyObject *py_ldb_whoami(PyLdbObject *self, PyObject *args)
2768 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2769 struct ldb_result *res = NULL;
2770 struct ldb_extended *ext_res = NULL;
2771 size_t len = 0;
2772 int ret;
2774 ret = ldb_extended(ldb, LDB_EXTENDED_WHOAMI_OID, NULL, &res);
2775 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2777 ext_res = res->extended;
2778 if (ext_res == NULL) {
2779 PyErr_SetString(PyExc_TypeError, "Got no exop reply");
2780 return NULL;
2783 if (strcmp(ext_res->oid, LDB_EXTENDED_WHOAMI_OID) != 0) {
2784 PyErr_SetString(PyExc_TypeError, "Got wrong reply OID");
2785 return NULL;
2788 len = talloc_get_size(ext_res->data);
2789 if (len == 0) {
2790 Py_RETURN_NONE;
2793 return PyUnicode_FromStringAndSize(ext_res->data, len);
2796 static PyObject *py_ldb_disconnect(PyLdbObject *self, PyObject *args)
2798 size_t ref_count;
2799 void *parent = NULL;
2800 TALLOC_CTX *mem_ctx = NULL;
2801 struct ldb_context *ldb = NULL;
2803 if (self->ldb_ctx == NULL) {
2804 /* It is hard to see how we'd get here. */
2805 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
2806 return NULL;
2809 ref_count = talloc_reference_count(self->ldb_ctx);
2811 if (ref_count != 0) {
2812 PyErr_SetString(PyExc_RuntimeError,
2813 "ldb.disconnect() not possible as "
2814 "object still has C (or second "
2815 "python object) references");
2816 return NULL;
2819 parent = talloc_parent(self->ldb_ctx);
2821 if (parent != self->mem_ctx) {
2822 PyErr_SetString(PyExc_RuntimeError,
2823 "ldb.disconnect() not possible as "
2824 "object is not talloc owned by this "
2825 "python object!");
2826 return NULL;
2830 * This recapitulates py_ldb_new(), cleaning out all the
2831 * connections and state, but leaving the python object in a
2832 * workable condition.
2834 mem_ctx = talloc_new(NULL);
2835 if (mem_ctx == NULL) {
2836 return PyErr_NoMemory();
2839 ldb = ldb_init(mem_ctx, NULL);
2840 if (ldb == NULL) {
2841 talloc_free(mem_ctx);
2842 PyErr_NoMemory();
2843 return NULL;
2847 * Notice we allocate the new mem_ctx and ldb before freeing
2848 * the old one. This has two purposes: 1, the python object
2849 * will still be consistent if an exception happens, and 2, it
2850 * ensures the new ldb can't have the same memory address as
2851 * the old one, and ldb address equality is a guard we use in
2852 * Python DNs and such. Repeated calls to disconnect() *can* make
2853 * this happen, so we don't advise doing that.
2855 TALLOC_FREE(self->mem_ctx);
2857 self->mem_ctx = mem_ctx;
2858 self->ldb_ctx = ldb;
2860 Py_RETURN_NONE;
2864 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2865 .name = "TEST",
2866 .read_fn = ldb_handler_copy,
2867 .write_clear_fn = ldb_handler_copy,
2868 .write_hex_fn = ldb_handler_copy,
2871 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2872 PyObject *Py_UNUSED(ignored))
2874 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2875 int ret;
2877 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2879 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2881 Py_RETURN_NONE;
2885 static PyMethodDef py_ldb_methods[] = {
2886 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2887 "S.set_debug(callback) -> None\n"
2888 "Set callback for LDB debug messages.\n"
2889 "The callback should accept a debug level and debug text." },
2890 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2891 "S.set_create_perms(mode) -> None\n"
2892 "Set mode to use when creating new LDB files." },
2893 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2894 "S.set_modules_dir(path) -> None\n"
2895 "Set path LDB should search for modules" },
2896 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2897 "S.transaction_start() -> None\n"
2898 "Start a new transaction." },
2899 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2900 "S.transaction_prepare_commit() -> None\n"
2901 "prepare to commit a new transaction (2-stage commit)." },
2902 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2903 "S.transaction_commit() -> None\n"
2904 "commit a new transaction." },
2905 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2906 "S.transaction_cancel() -> None\n"
2907 "cancel a new transaction." },
2908 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2909 NULL },
2910 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2911 NULL },
2912 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2913 NULL },
2914 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2915 NULL },
2916 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2917 NULL },
2918 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2919 METH_VARARGS|METH_KEYWORDS,
2920 "S.connect(url, flags=0, options=None) -> None\n"
2921 "Connect to a LDB URL." },
2922 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2923 METH_VARARGS|METH_KEYWORDS,
2924 "S.modify(message, controls=None, validate=False) -> None\n"
2925 "Modify an entry." },
2926 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2927 METH_VARARGS|METH_KEYWORDS,
2928 "S.add(message, controls=None) -> None\n"
2929 "Add an entry." },
2930 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2931 METH_VARARGS|METH_KEYWORDS,
2932 "S.delete(dn, controls=None) -> None\n"
2933 "Remove an entry." },
2934 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2935 METH_VARARGS|METH_KEYWORDS,
2936 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2937 "Rename an entry." },
2938 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2939 METH_VARARGS|METH_KEYWORDS,
2940 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2941 "Search in a database.\n"
2942 "\n"
2943 ":param base: Optional base DN to search\n"
2944 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2945 ":param expression: Optional search expression\n"
2946 ":param attrs: Attributes to return (defaults to all)\n"
2947 ":param controls: Optional list of controls\n"
2948 ":return: ldb.Result object\n"
2950 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2951 py_ldb_search_iterator),
2952 METH_VARARGS|METH_KEYWORDS,
2953 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2954 "Search in a database.\n"
2955 "\n"
2956 ":param base: Optional base DN to search\n"
2957 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2958 ":param expression: Optional search expression\n"
2959 ":param attrs: Attributes to return (defaults to all)\n"
2960 ":param controls: Optional list of controls\n"
2961 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2962 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2964 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2965 NULL },
2966 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2967 NULL },
2968 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2969 NULL },
2970 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2971 "S.parse_ldif(ldif) -> iter(messages)\n"
2972 "Parse a string formatted using LDIF." },
2973 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2974 "S.write_ldif(message, changetype) -> ldif\n"
2975 "Print the message as a string formatted using LDIF." },
2976 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2977 "S.msg_diff(Message) -> Message\n"
2978 "Return an LDB Message of the difference between two Message objects." },
2979 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2980 "S.get_opaque(name) -> value\n"
2981 "Get an opaque value set on this LDB connection. \n"
2982 ":note: The returned value may not be useful in Python."
2984 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2985 "S.set_opaque(name, value) -> None\n"
2986 "Set an opaque value on this LDB connection. \n"
2987 ":note: Passing incorrect values may cause crashes." },
2988 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2989 "S.sequence_number(type) -> value\n"
2990 "Return the value of the sequence according to the requested type" },
2991 { "whoami",
2992 (PyCFunction)py_ldb_whoami,
2993 METH_NOARGS,
2994 "S.whoami() -> value\n"
2995 "Return the RFC4532 whoami string",
2997 { "disconnect",
2998 (PyCFunction)py_ldb_disconnect,
2999 METH_NOARGS,
3000 "S.disconnect() -> None\n"
3001 "Make this Ldb object unusable, disconnect and free the "
3002 "underlying LDB, releasing any file handles and sockets.",
3004 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
3005 "S._register_test_extensions() -> None\n"
3006 "Register internal extensions used in testing" },
3007 {0},
3010 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
3012 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
3013 struct ldb_dn *dn;
3014 struct ldb_result *result;
3015 unsigned int count;
3016 int ret;
3018 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
3019 return -1;
3022 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
3023 NULL);
3024 if (ret != LDB_SUCCESS) {
3025 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
3026 return -1;
3029 count = result->count;
3031 talloc_free(result);
3033 if (count > 1) {
3034 PyErr_Format(PyExc_RuntimeError,
3035 "Searching for [%s] dn gave %u results!",
3036 ldb_dn_get_linearized(dn),
3037 count);
3038 return -1;
3041 return count;
3044 static PySequenceMethods py_ldb_seq = {
3045 .sq_contains = (objobjproc)py_ldb_contains,
3048 static void py_ldb_dealloc(PyLdbObject *self)
3050 talloc_free(self->mem_ctx);
3051 Py_TYPE(self)->tp_free(self);
3054 static PyTypeObject PyLdb = {
3055 .tp_name = "ldb.Ldb",
3056 .tp_methods = py_ldb_methods,
3057 .tp_repr = (reprfunc)py_ldb_repr,
3058 .tp_new = py_ldb_new,
3059 .tp_init = (initproc)py_ldb_init,
3060 .tp_dealloc = (destructor)py_ldb_dealloc,
3061 .tp_getattro = PyObject_GenericGetAttr,
3062 .tp_basicsize = sizeof(PyLdbObject),
3063 .tp_doc = "Connection to a LDB database.",
3064 .tp_as_sequence = &py_ldb_seq,
3065 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3068 static void py_ldb_result_dealloc(PyLdbResultObject *self)
3070 talloc_free(self->mem_ctx);
3071 Py_CLEAR(self->msgs);
3072 Py_CLEAR(self->referals);
3073 Py_CLEAR(self->controls);
3074 Py_DECREF(self->pyldb);
3075 Py_TYPE(self)->tp_free(self);
3078 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
3080 Py_INCREF(self->msgs);
3081 return self->msgs;
3084 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
3086 Py_INCREF(self->controls);
3087 return self->controls;
3090 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
3092 Py_INCREF(self->referals);
3093 return self->referals;
3096 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
3098 Py_ssize_t size;
3099 if (self->msgs == NULL) {
3100 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
3101 return NULL;
3103 size = PyList_Size(self->msgs);
3104 return PyLong_FromLong(size);
3107 static PyGetSetDef py_ldb_result_getset[] = {
3109 .name = discard_const_p(char, "controls"),
3110 .get = (getter)py_ldb_result_get_controls,
3113 .name = discard_const_p(char, "msgs"),
3114 .get = (getter)py_ldb_result_get_msgs,
3117 .name = discard_const_p(char, "referals"),
3118 .get = (getter)py_ldb_result_get_referals,
3121 .name = discard_const_p(char, "count"),
3122 .get = (getter)py_ldb_result_get_count,
3124 { .name = NULL },
3127 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
3129 return PyObject_GetIter(self->msgs);
3132 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
3134 return PySequence_Size(self->msgs);
3137 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
3139 return PySequence_GetItem(self->msgs, idx);
3142 static PySequenceMethods py_ldb_result_seq = {
3143 .sq_length = (lenfunc)py_ldb_result_len,
3144 .sq_item = (ssizeargfunc)py_ldb_result_find,
3147 static PyObject *py_ldb_result_repr(PyLdbObject *self)
3149 return PyUnicode_FromString("<ldb result>");
3153 static PyTypeObject PyLdbResult = {
3154 .tp_name = "ldb.Result",
3155 .tp_repr = (reprfunc)py_ldb_result_repr,
3156 .tp_dealloc = (destructor)py_ldb_result_dealloc,
3157 .tp_iter = (getiterfunc)py_ldb_result_iter,
3158 .tp_getset = py_ldb_result_getset,
3159 .tp_getattro = PyObject_GenericGetAttr,
3160 .tp_basicsize = sizeof(PyLdbResultObject),
3161 .tp_as_sequence = &py_ldb_result_seq,
3162 .tp_doc = "LDB result.",
3163 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3166 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
3168 Py_CLEAR(self->state.exception);
3169 TALLOC_FREE(self->mem_ctx);
3170 ZERO_STRUCT(self->state);
3171 Py_CLEAR(self->ldb);
3172 Py_TYPE(self)->tp_free(self);
3175 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
3177 PyObject *py_ret = NULL;
3179 if (self->state.req == NULL) {
3180 PyErr_SetString(PyExc_RuntimeError,
3181 "ldb.SearchIterator request already finished");
3182 return NULL;
3186 * TODO: do we want a non-blocking mode?
3187 * In future we may add an optional 'nonblocking'
3188 * argument to search_iterator().
3190 * For now we keep it simple and wait for at
3191 * least one reply.
3194 while (self->state.next == NULL) {
3195 int ret;
3197 if (self->state.result != NULL) {
3199 * We (already) got a final result from the server.
3201 * We stop the iteration and let
3202 * py_ldb_search_iterator_result() will deliver
3203 * the result details.
3205 TALLOC_FREE(self->state.req);
3206 PyErr_SetNone(PyExc_StopIteration);
3207 return NULL;
3210 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
3211 if (ret != LDB_SUCCESS) {
3212 struct ldb_context *ldb_ctx;
3213 TALLOC_FREE(self->state.req);
3214 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
3216 * We stop the iteration and let
3217 * py_ldb_search_iterator_result() will deliver
3218 * the exception.
3220 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
3221 ret, ldb_errstring(ldb_ctx));
3222 PyErr_SetNone(PyExc_StopIteration);
3223 return NULL;
3227 py_ret = self->state.next->obj;
3228 self->state.next->obj = NULL;
3229 /* no TALLOC_FREE() as self->state.next is a list */
3230 talloc_free(self->state.next);
3231 return py_ret;
3234 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
3235 PyObject *Py_UNUSED(ignored))
3237 PyObject *py_ret = NULL;
3239 if (self->state.req != NULL) {
3240 PyErr_SetString(PyExc_RuntimeError,
3241 "ldb.SearchIterator request running");
3242 return NULL;
3245 if (self->state.next != NULL) {
3246 PyErr_SetString(PyExc_RuntimeError,
3247 "ldb.SearchIterator not fully consumed.");
3248 return NULL;
3251 if (self->state.exception != NULL) {
3252 PyErr_SetObject(PyExc_LdbError, self->state.exception);
3253 Py_DECREF(self->state.exception);
3254 self->state.exception = NULL;
3255 return NULL;
3258 if (self->state.result == NULL) {
3259 PyErr_SetString(PyExc_RuntimeError,
3260 "ldb.SearchIterator result already consumed");
3261 return NULL;
3264 py_ret = self->state.result->obj;
3265 self->state.result->obj = NULL;
3266 TALLOC_FREE(self->state.result);
3267 return py_ret;
3270 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
3271 PyObject *Py_UNUSED(ignored))
3273 if (self->state.req == NULL) {
3274 PyErr_SetString(PyExc_RuntimeError,
3275 "ldb.SearchIterator request already finished");
3276 return NULL;
3279 Py_CLEAR(self->state.exception);
3280 TALLOC_FREE(self->mem_ctx);
3281 ZERO_STRUCT(self->state);
3282 Py_RETURN_NONE;
3285 static PyMethodDef py_ldb_search_iterator_methods[] = {
3286 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
3287 "S.result() -> ldb.Result (without msgs and referrals)\n" },
3288 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
3289 "S.abandon()\n" },
3293 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
3295 return PyUnicode_FromString("<ldb search iterator>");
3298 static PyTypeObject PyLdbSearchIterator = {
3299 .tp_name = "ldb.SearchIterator",
3300 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
3301 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
3302 .tp_iter = PyObject_SelfIter,
3303 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
3304 .tp_methods = py_ldb_search_iterator_methods,
3305 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
3306 .tp_doc = "LDB search_iterator.",
3307 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3311 * Create a ldb_message_element from a Python object.
3313 * This will accept any sequence objects that contains strings, or
3314 * a string object.
3316 * A reference to set_obj might be borrowed.
3318 * @param mem_ctx Memory context
3319 * @param set_obj Python object to convert
3320 * @param flags ldb_message_element flags to set, if a new element is returned
3321 * @param attr_name Name of the attribute to set, if a new element is returned
3322 * @return New ldb_message_element, allocated as child of mem_ctx
3324 static struct ldb_message_element *PyObject_AsMessageElement(
3325 TALLOC_CTX *mem_ctx,
3326 PyObject *set_obj,
3327 unsigned int flags,
3328 const char *attr_name)
3330 struct ldb_message_element *me;
3331 const char *msg = NULL;
3332 Py_ssize_t size;
3333 int result;
3335 if (pyldb_MessageElement_Check(set_obj)) {
3336 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
3337 /* We have to talloc_reference() the memory context, not the pointer
3338 * which may not actually be it's own context */
3339 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
3340 return pyldb_MessageElement_AsMessageElement(set_obj);
3342 return NULL;
3345 me = talloc(mem_ctx, struct ldb_message_element);
3346 if (me == NULL) {
3347 PyErr_NoMemory();
3348 return NULL;
3351 me->name = talloc_strdup(me, attr_name);
3352 if (me->name == NULL) {
3353 PyErr_NoMemory();
3354 talloc_free(me);
3355 return NULL;
3357 me->flags = flags;
3358 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
3359 me->num_values = 1;
3360 me->values = talloc_array(me, struct ldb_val, me->num_values);
3361 if (PyBytes_Check(set_obj)) {
3362 char *_msg = NULL;
3363 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
3364 if (result != 0) {
3365 talloc_free(me);
3366 return NULL;
3368 msg = _msg;
3369 } else {
3370 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3371 if (msg == NULL) {
3372 talloc_free(me);
3373 return NULL;
3376 me->values[0].data = talloc_memdup(me,
3377 (const uint8_t *)msg,
3378 size+1);
3379 me->values[0].length = size;
3380 } else if (PySequence_Check(set_obj)) {
3381 Py_ssize_t i;
3382 me->num_values = PySequence_Size(set_obj);
3383 me->values = talloc_array(me, struct ldb_val, me->num_values);
3384 for (i = 0; i < me->num_values; i++) {
3385 PyObject *obj = PySequence_GetItem(set_obj, i);
3386 if (PyBytes_Check(obj)) {
3387 char *_msg = NULL;
3388 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3389 if (result != 0) {
3390 talloc_free(me);
3391 return NULL;
3393 msg = _msg;
3394 } else if (PyUnicode_Check(obj)) {
3395 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3396 if (msg == NULL) {
3397 talloc_free(me);
3398 return NULL;
3400 } else {
3401 PyErr_Format(PyExc_TypeError,
3402 "Expected string as element %zd in list", i);
3403 talloc_free(me);
3404 return NULL;
3406 me->values[i].data = talloc_memdup(me,
3407 (const uint8_t *)msg,
3408 size+1);
3409 me->values[i].length = size;
3411 } else {
3412 PyErr_Format(PyExc_TypeError,
3413 "String or List type expected for '%s' attribute", attr_name);
3414 talloc_free(me);
3415 me = NULL;
3418 return me;
3422 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3423 struct ldb_message_element *me)
3425 Py_ssize_t i;
3426 PyObject *result;
3428 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3429 result = PyList_New(me->num_values);
3430 if (result == NULL) {
3431 return NULL;
3434 for (i = 0; i < me->num_values; i++) {
3435 PyObject *obj = NULL;
3436 int ret;
3438 obj = PyObject_FromLdbValue(&me->values[i]);
3439 if (obj == NULL) {
3440 Py_DECREF(result);
3441 return NULL;
3444 ret = PyList_SetItem(result, i, obj);
3445 if (ret) {
3446 Py_DECREF(obj);
3447 Py_DECREF(result);
3448 return NULL;
3452 return result;
3455 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3457 unsigned int i;
3458 if (!PyArg_ParseTuple(args, "I", &i))
3459 return NULL;
3460 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3461 Py_RETURN_NONE;
3463 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3466 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3468 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3469 return PyLong_FromLong(el->flags);
3472 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3474 unsigned int flags;
3475 struct ldb_message_element *el;
3476 if (!PyArg_ParseTuple(args, "I", &flags))
3477 return NULL;
3479 el = pyldb_MessageElement_AsMessageElement(self);
3480 el->flags = flags;
3481 Py_RETURN_NONE;
3484 static PyMethodDef py_ldb_msg_element_methods[] = {
3485 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3486 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3487 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3488 {0},
3491 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3493 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3496 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3498 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3499 if (idx < 0 || idx >= el->num_values) {
3500 PyErr_SetString(PyExc_IndexError, "Out of range");
3501 return NULL;
3503 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3506 static PySequenceMethods py_ldb_msg_element_seq = {
3507 .sq_length = (lenfunc)py_ldb_msg_element_len,
3508 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3511 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3513 int ret;
3514 if (!pyldb_MessageElement_Check(other)) {
3515 Py_INCREF(Py_NotImplemented);
3516 return Py_NotImplemented;
3518 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3519 pyldb_MessageElement_AsMessageElement(other));
3520 return richcmp(ret, op);
3523 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3525 PyObject *el = ldb_msg_element_to_set(NULL,
3526 pyldb_MessageElement_AsMessageElement(self));
3527 PyObject *ret = PyObject_GetIter(el);
3528 Py_DECREF(el);
3529 return ret;
3532 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3534 TALLOC_CTX *ret_mem_ctx = NULL;
3535 PyLdbMessageElementObject *ret;
3537 ret_mem_ctx = talloc_new(NULL);
3538 if (ret_mem_ctx == NULL) {
3539 return PyErr_NoMemory();
3542 if (talloc_reference(ret_mem_ctx, mem_ctx) == NULL) {
3543 talloc_free(ret_mem_ctx);
3544 PyErr_NoMemory();
3545 return NULL;
3548 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3549 if (ret == NULL) {
3550 talloc_free(ret_mem_ctx);
3551 PyErr_NoMemory();
3552 return NULL;
3554 ret->mem_ctx = ret_mem_ctx;
3555 ret->el = el;
3556 return (PyObject *)ret;
3559 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3561 PyObject *py_elements = NULL;
3562 struct ldb_message_element *el;
3563 unsigned int flags = 0;
3564 char *name = NULL;
3565 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3566 PyLdbMessageElementObject *ret;
3567 TALLOC_CTX *mem_ctx;
3568 const char *msg = NULL;
3569 Py_ssize_t size;
3570 int result;
3572 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3573 discard_const_p(char *, kwnames),
3574 &py_elements, &flags, &name))
3575 return NULL;
3577 mem_ctx = talloc_new(NULL);
3578 if (mem_ctx == NULL) {
3579 PyErr_NoMemory();
3580 return NULL;
3583 el = talloc_zero(mem_ctx, struct ldb_message_element);
3584 if (el == NULL) {
3585 PyErr_NoMemory();
3586 talloc_free(mem_ctx);
3587 return NULL;
3590 if (py_elements != NULL) {
3591 Py_ssize_t i;
3592 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3593 char *_msg = NULL;
3594 el->num_values = 1;
3595 el->values = talloc_array(el, struct ldb_val, 1);
3596 if (el->values == NULL) {
3597 talloc_free(mem_ctx);
3598 PyErr_NoMemory();
3599 return NULL;
3601 if (PyBytes_Check(py_elements)) {
3602 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3603 msg = _msg;
3604 } else {
3605 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3606 result = (msg == NULL) ? -1 : 0;
3608 if (result != 0) {
3609 talloc_free(mem_ctx);
3610 return NULL;
3612 el->values[0].data = talloc_memdup(el->values,
3613 (const uint8_t *)msg, size + 1);
3614 el->values[0].length = size;
3615 } else if (PySequence_Check(py_elements)) {
3616 el->num_values = PySequence_Size(py_elements);
3617 el->values = talloc_array(el, struct ldb_val, el->num_values);
3618 if (el->values == NULL) {
3619 talloc_free(mem_ctx);
3620 PyErr_NoMemory();
3621 return NULL;
3623 for (i = 0; i < el->num_values; i++) {
3624 PyObject *item = PySequence_GetItem(py_elements, i);
3625 if (item == NULL) {
3626 talloc_free(mem_ctx);
3627 return NULL;
3629 if (PyBytes_Check(item)) {
3630 char *_msg = NULL;
3631 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3632 msg = _msg;
3633 } else if (PyUnicode_Check(item)) {
3634 msg = PyUnicode_AsUTF8AndSize(item, &size);
3635 result = (msg == NULL) ? -1 : 0;
3636 } else {
3637 PyErr_Format(PyExc_TypeError,
3638 "Expected string as element %zd in list", i);
3639 result = -1;
3641 if (result != 0) {
3642 talloc_free(mem_ctx);
3643 return NULL;
3645 el->values[i].data = talloc_memdup(el,
3646 (const uint8_t *)msg, size+1);
3647 el->values[i].length = size;
3649 } else {
3650 PyErr_SetString(PyExc_TypeError,
3651 "Expected string or list");
3652 talloc_free(mem_ctx);
3653 return NULL;
3657 el->flags = flags;
3658 if (name != NULL) {
3659 el->name = talloc_strdup(el, name);
3660 if (el->name == NULL) {
3661 talloc_free(mem_ctx);
3662 return PyErr_NoMemory();
3666 ret = PyObject_New(PyLdbMessageElementObject, type);
3667 if (ret == NULL) {
3668 talloc_free(mem_ctx);
3669 return NULL;
3672 ret->mem_ctx = mem_ctx;
3673 ret->el = el;
3674 return (PyObject *)ret;
3677 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3679 char *element_str = NULL;
3680 Py_ssize_t i;
3681 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3682 PyObject *ret, *repr;
3684 for (i = 0; i < el->num_values; i++) {
3685 PyObject *o = py_ldb_msg_element_find(self, i);
3686 repr = PyObject_Repr(o);
3687 if (element_str == NULL)
3688 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3689 else
3690 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3691 Py_DECREF(repr);
3693 if (element_str == NULL) {
3694 return PyErr_NoMemory();
3698 if (element_str != NULL) {
3699 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3700 talloc_free(element_str);
3701 } else {
3702 ret = PyUnicode_FromString("MessageElement([])");
3705 return ret;
3708 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3710 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3712 if (el->num_values == 1)
3713 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3714 else
3715 Py_RETURN_NONE;
3718 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3720 talloc_free(self->mem_ctx);
3721 PyObject_Del(self);
3724 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3726 return wrap_text("MessageElementTextWrapper", self);
3729 static PyGetSetDef py_ldb_msg_element_getset[] = {
3731 .name = discard_const_p(char, "text"),
3732 .get = (getter)py_ldb_msg_element_get_text,
3734 { .name = NULL }
3737 static PyTypeObject PyLdbMessageElement = {
3738 .tp_name = "ldb.MessageElement",
3739 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3740 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3741 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3742 .tp_str = (reprfunc)py_ldb_msg_element_str,
3743 .tp_methods = py_ldb_msg_element_methods,
3744 .tp_getset = py_ldb_msg_element_getset,
3745 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3746 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3747 .tp_as_sequence = &py_ldb_msg_element_seq,
3748 .tp_new = py_ldb_msg_element_new,
3749 .tp_flags = Py_TPFLAGS_DEFAULT,
3750 .tp_doc = "An element of a Message",
3754 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3756 PyObject *py_ldb;
3757 PyObject *py_dict;
3758 PyObject *py_ret;
3759 struct ldb_message *msg;
3760 struct ldb_context *ldb_ctx;
3761 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3763 if (!PyArg_ParseTuple(args, "O!O!|I",
3764 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3765 &mod_flags)) {
3766 return NULL;
3769 /* mask only flags we are going to use */
3770 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3771 if (!mod_flags) {
3772 PyErr_SetString(PyExc_ValueError,
3773 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3774 " expected as mod_flag value");
3775 return NULL;
3778 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3780 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3781 if (!msg) {
3782 return NULL;
3785 py_ret = PyLdbMessage_FromMessage(msg, (PyLdbObject *)py_ldb);
3787 talloc_unlink(ldb_ctx, msg);
3789 return py_ret;
3793 #define pyldb_Message_as_message(pyobj) ((PyLdbMessageObject *)pyobj)->msg
3795 #define pyldb_Message_get_pyldb(pyobj) ((PyLdbMessageObject *)pyobj)->pyldb
3798 * PyErr_LDB_MESSAGE_OR_RAISE does 3 things:
3799 * 1. checks that a PyObject is really a PyLdbMessageObject.
3800 * 2. checks that the ldb that the PyLdbMessageObject knows is the ldb that
3801 * its dn knows -- but only if the underlying message has a DN.
3802 * 3. sets message to the relevant struct ldb_message *.
3804 * We need to do all this to ensure the message belongs to the right
3805 * ldb, lest it be freed before we are ready.
3807 #define PyErr_LDB_MESSAGE_OR_RAISE(_py_obj, message) do { \
3808 PyLdbMessageObject *_py_message = NULL; \
3809 struct ldb_dn *_dn = NULL; \
3810 if (_py_obj == NULL || !pyldb_Message_Check(_py_obj)) { \
3811 PyErr_SetString(PyExc_TypeError, \
3812 "ldb Message object required"); \
3813 return NULL; \
3815 _py_message = (PyLdbMessageObject *)_py_obj; \
3816 message = pyldb_Message_as_message(_py_message); \
3817 _dn = message->dn; \
3818 if (_dn != NULL && \
3819 (_py_message->pyldb->ldb_ctx != ldb_dn_get_ldb_context(_dn))) { \
3820 PyErr_SetString(PyExc_RuntimeError, \
3821 "Message has a stale LDB connection"); \
3822 return NULL; \
3824 } while(0)
3827 static PyObject *py_ldb_msg_remove_attr(PyObject *self, PyObject *args)
3829 char *name;
3830 struct ldb_message *msg = NULL;
3831 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3833 if (!PyArg_ParseTuple(args, "s", &name)) {
3834 return NULL;
3837 ldb_msg_remove_attr(msg, name);
3839 Py_RETURN_NONE;
3842 static PyObject *py_ldb_msg_keys(PyObject *self,
3843 PyObject *Py_UNUSED(ignored))
3845 struct ldb_message *msg = NULL;
3846 Py_ssize_t i, j = 0;
3847 PyObject *obj = NULL;
3849 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3851 obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3852 if (obj == NULL) {
3853 return NULL;
3856 if (msg->dn != NULL) {
3857 PyObject *py_dn = NULL;
3858 int ret;
3860 py_dn = PyUnicode_FromString("dn");
3861 if (py_dn == NULL) {
3862 Py_DECREF(obj);
3863 return NULL;
3866 ret = PyList_SetItem(obj, j, py_dn);
3867 if (ret) {
3868 Py_DECREF(py_dn);
3869 Py_DECREF(obj);
3870 return NULL;
3873 j++;
3875 for (i = 0; i < msg->num_elements; i++) {
3876 PyObject *py_name = NULL;
3877 int ret;
3879 py_name = PyUnicode_FromString(msg->elements[i].name);
3880 if (py_name == NULL) {
3881 Py_DECREF(obj);
3882 return NULL;
3885 ret = PyList_SetItem(obj, j, py_name);
3886 if (ret) {
3887 Py_DECREF(py_name);
3888 Py_DECREF(obj);
3889 return NULL;
3892 j++;
3894 return obj;
3897 static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name)
3899 struct ldb_message_element *el = NULL;
3900 const char *name = NULL;
3901 struct ldb_message *msg = pyldb_Message_as_message(self);
3902 struct ldb_dn *dn = msg->dn;
3904 if (dn != NULL && (self->pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn))) {
3905 return -1;
3908 name = PyUnicode_AsUTF8(py_name);
3909 if (name == NULL) {
3910 return -1;
3912 if (!ldb_attr_cmp(name, "dn")) {
3913 return 1;
3915 el = ldb_msg_find_element(msg, name);
3916 return el != NULL ? 1 : 0;
3919 static PyObject *py_ldb_msg_getitem(PyObject *self, PyObject *py_name)
3921 struct ldb_message_element *el = NULL;
3922 const char *name = NULL;
3923 struct ldb_message *msg = NULL;
3924 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3926 name = PyUnicode_AsUTF8(py_name);
3927 if (name == NULL) {
3928 return NULL;
3930 if (!ldb_attr_cmp(name, "dn")) {
3931 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
3933 el = ldb_msg_find_element(msg, name);
3934 if (el == NULL) {
3935 PyErr_SetString(PyExc_KeyError, "No such element");
3936 return NULL;
3939 return PyLdbMessageElement_FromMessageElement(el, msg->elements);
3942 static PyObject *py_ldb_msg_get(PyObject *self, PyObject *args, PyObject *kwargs)
3944 PyObject *def = NULL;
3945 const char *kwnames[] = { "name", "default", "idx", NULL };
3946 const char *name = NULL;
3947 int idx = -1;
3948 struct ldb_message_element *el;
3949 struct ldb_message *msg = NULL;
3950 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3952 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3953 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3954 return NULL;
3957 if (strcasecmp(name, "dn") == 0) {
3958 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
3961 el = ldb_msg_find_element(msg, name);
3963 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3964 if (def != NULL) {
3965 Py_INCREF(def);
3966 return def;
3968 Py_RETURN_NONE;
3971 if (idx == -1) {
3972 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3975 return PyObject_FromLdbValue(&el->values[idx]);
3978 static PyObject *py_ldb_msg_items(PyObject *self,
3979 PyObject *Py_UNUSED(ignored))
3981 struct ldb_message *msg = NULL;
3982 Py_ssize_t i, j = 0;
3983 PyObject *l = NULL;
3985 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3987 l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3988 if (l == NULL) {
3989 return PyErr_NoMemory();
3991 if (msg->dn != NULL) {
3992 PyObject *value = NULL;
3993 int res = 0;
3994 PyObject *obj = pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
3995 if (obj == NULL) {
3996 Py_CLEAR(l);
3997 return NULL;
3999 value = Py_BuildValue("(sO)", "dn", obj);
4000 Py_CLEAR(obj);
4001 if (value == NULL) {
4002 Py_CLEAR(l);
4003 return NULL;
4005 res = PyList_SetItem(l, 0, value);
4006 if (res == -1) {
4007 Py_CLEAR(l);
4008 return NULL;
4010 j++;
4012 for (i = 0; i < msg->num_elements; i++, j++) {
4013 PyObject *value = NULL;
4014 int res = 0;
4015 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i],
4016 msg->elements);
4017 if (py_el == NULL) {
4018 Py_CLEAR(l);
4019 return NULL;
4021 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
4022 Py_CLEAR(py_el);
4023 if (value == NULL ) {
4024 Py_CLEAR(l);
4025 return NULL;
4027 res = PyList_SetItem(l, j, value);
4028 if (res == -1) {
4029 Py_CLEAR(l);
4030 return NULL;
4033 return l;
4036 static PyObject *py_ldb_msg_elements(PyObject *self,
4037 PyObject *Py_UNUSED(ignored))
4039 Py_ssize_t i = 0;
4040 PyObject *l = NULL;
4041 struct ldb_message *msg = NULL;
4042 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4044 l = PyList_New(msg->num_elements);
4045 if (l == NULL) {
4046 return NULL;
4048 for (i = 0; i < msg->num_elements; i++) {
4049 PyObject *msg_el = NULL;
4050 int ret;
4052 msg_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
4053 if (msg_el == NULL) {
4054 Py_DECREF(l);
4055 return NULL;
4058 ret = PyList_SetItem(l, i, msg_el);
4059 if (ret) {
4060 Py_DECREF(msg_el);
4061 Py_DECREF(l);
4062 return NULL;
4065 return l;
4068 static PyObject *py_ldb_msg_add(PyObject *self, PyObject *args)
4070 PyLdbMessageElementObject *py_element;
4071 int i, ret;
4072 struct ldb_message_element *el;
4073 struct ldb_message_element *el_new;
4074 struct ldb_message *msg = NULL;
4075 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4077 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element)) {
4078 return NULL;
4081 el = py_element->el;
4082 if (el == NULL) {
4083 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
4084 return NULL;
4086 if (el->name == NULL) {
4087 PyErr_SetString(PyExc_ValueError,
4088 "The element has no name");
4089 return NULL;
4091 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
4092 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4094 /* now deep copy all attribute values */
4095 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
4096 if (el_new->values == NULL) {
4097 PyErr_NoMemory();
4098 return NULL;
4100 el_new->num_values = el->num_values;
4102 for (i = 0; i < el->num_values; i++) {
4103 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
4104 if (el_new->values[i].data == NULL
4105 && el->values[i].length != 0) {
4106 PyErr_NoMemory();
4107 return NULL;
4111 Py_RETURN_NONE;
4114 static PyMethodDef py_ldb_msg_methods[] = {
4115 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
4116 "Message.from_dict(ldb, dict, mod_flag) -> ldb.Message\n"
4117 "Class method to create ldb.Message object from Dictionary.\n"
4118 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
4119 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
4120 "S.keys() -> list\n\n"
4121 "Return sequence of all attribute names." },
4122 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
4123 "S.remove(name)\n\n"
4124 "Remove all entries for attributes with the specified name."},
4125 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
4126 METH_VARARGS | METH_KEYWORDS,
4127 "msg.get(name,default=None,idx=None) -> string\n"
4128 "idx is the index into the values array\n"
4129 "if idx is None, then a list is returned\n"
4130 "if idx is not None, then the element with that index is returned\n"
4131 "if you pass the special name 'dn' then the DN object is returned\n"},
4132 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
4133 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
4134 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
4135 "S.add(element)\n\n"
4136 "Add an element to this message." },
4137 {0},
4140 static PyObject *py_ldb_msg_iter(PyObject *self)
4142 PyObject *list, *iter;
4144 list = py_ldb_msg_keys(self, NULL);
4145 if (list == NULL) {
4146 return NULL;
4148 iter = PyObject_GetIter(list);
4149 Py_DECREF(list);
4150 return iter;
4153 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
4155 const char *attr_name;
4157 attr_name = PyUnicode_AsUTF8(name);
4158 if (attr_name == NULL) {
4159 PyErr_SetNone(PyExc_TypeError);
4160 return -1;
4163 if (value == NULL) {
4164 /* delitem */
4165 ldb_msg_remove_attr(self->msg, attr_name);
4166 } else {
4167 int ret;
4168 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
4169 value, 0, attr_name);
4170 if (el == NULL) {
4171 return -1;
4173 if (el->name == NULL) {
4175 * If ‘value’ is a MessageElement,
4176 * PyObject_AsMessageElement() will have returned a
4177 * reference to it without setting the name. We don’t
4178 * want to modify the original object to set the name
4179 * ourselves, but making a copy would result in
4180 * different behaviour for a caller relying on a
4181 * reference being kept. Rather than continue with a
4182 * NULL name (and probably fail later on), let’s catch
4183 * this potential mistake early.
4185 PyErr_SetString(PyExc_ValueError, "MessageElement has no name set");
4186 talloc_unlink(self->msg, el);
4187 return -1;
4189 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
4190 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
4191 if (ret != LDB_SUCCESS) {
4192 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
4193 talloc_unlink(self->msg, el);
4194 return -1;
4197 return 0;
4200 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
4202 return pyldb_Message_AsMessage(self)->num_elements;
4205 static PySequenceMethods py_ldb_msg_sequence = {
4206 .sq_contains = (objobjproc)py_ldb_msg_contains,
4209 static PyMappingMethods py_ldb_msg_mapping = {
4210 .mp_length = (lenfunc)py_ldb_msg_length,
4211 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
4212 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
4215 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
4217 const char * const kwnames[] = { "dn", NULL };
4218 struct ldb_message *ret;
4219 TALLOC_CTX *mem_ctx;
4220 PyObject *pydn = NULL;
4221 PyLdbMessageObject *py_ret;
4223 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
4224 discard_const_p(char *, kwnames),
4225 &pydn))
4226 return NULL;
4228 mem_ctx = talloc_new(NULL);
4229 if (mem_ctx == NULL) {
4230 PyErr_NoMemory();
4231 return NULL;
4234 ret = ldb_msg_new(mem_ctx);
4235 if (ret == NULL) {
4236 talloc_free(mem_ctx);
4237 PyErr_NoMemory();
4238 return NULL;
4241 if (pydn != NULL) {
4242 struct ldb_dn *dn;
4243 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
4244 talloc_free(mem_ctx);
4245 return NULL;
4247 ret->dn = talloc_reference(ret, dn);
4248 if (ret->dn == NULL) {
4249 talloc_free(mem_ctx);
4250 return PyErr_NoMemory();
4254 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
4255 if (py_ret == NULL) {
4256 PyErr_NoMemory();
4257 talloc_free(mem_ctx);
4258 return NULL;
4261 py_ret->mem_ctx = mem_ctx;
4262 py_ret->msg = ret;
4263 if (pydn != NULL) {
4264 py_ret->pyldb = ((PyLdbDnObject *)pydn)->pyldb;
4265 Py_INCREF(py_ret->pyldb);
4267 return (PyObject *)py_ret;
4270 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg, PyLdbObject *pyldb)
4272 TALLOC_CTX *mem_ctx = NULL;
4273 struct ldb_message *msg_ref = NULL;
4274 PyLdbMessageObject *ret;
4276 mem_ctx = talloc_new(NULL);
4277 if (mem_ctx == NULL) {
4278 return PyErr_NoMemory();
4281 msg_ref = talloc_reference(mem_ctx, msg);
4282 if (msg_ref == NULL) {
4283 talloc_free(mem_ctx);
4284 return PyErr_NoMemory();
4287 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
4288 if (ret == NULL) {
4289 talloc_free(mem_ctx);
4290 PyErr_NoMemory();
4291 return NULL;
4293 ret->mem_ctx = mem_ctx;
4294 ret->msg = msg_ref;
4296 ret->pyldb = pyldb;
4297 Py_INCREF(ret->pyldb);
4299 return (PyObject *)ret;
4302 static PyObject *py_ldb_msg_get_dn(PyObject *self, void *closure)
4304 struct ldb_message *msg = NULL;
4305 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4306 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
4309 static int py_ldb_msg_set_dn(PyObject *self, PyObject *value, void *closure)
4312 * no PyErr_LDB_MESSAGE_OR_RAISE here, because this returns int.
4314 * Also, since this is trying to replace the dn, we don't need to
4315 * check the old one.
4317 struct ldb_message *msg = pyldb_Message_as_message(self);
4318 struct ldb_dn *dn = NULL;
4319 PyLdbObject *pyldb = pyldb_Message_get_pyldb(self);
4320 PyLdbMessageObject *self_as_msg = (PyLdbMessageObject *)self;
4322 if (value == NULL) {
4323 PyErr_SetString(PyExc_AttributeError, "cannot delete dn");
4324 return -1;
4326 if (!pyldb_Dn_Check(value)) {
4327 PyErr_SetString(PyExc_TypeError, "expected dn");
4328 return -1;
4331 dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
4332 if (dn == NULL) {
4333 PyErr_NoMemory();
4334 return -1;
4337 if (pyldb != NULL) {
4338 if (pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn)) {
4339 PyErr_SetString(PyExc_RuntimeError,
4340 "DN is from the wrong LDB");
4341 return -1;
4343 Py_DECREF(pyldb);
4346 msg->dn = dn;
4348 self_as_msg->pyldb = ((PyLdbDnObject *)value)->pyldb;
4349 Py_INCREF(self_as_msg->pyldb);
4351 return 0;
4354 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
4356 return wrap_text("MessageTextWrapper", self);
4361 static PyObject *py_ldb_msg_get_ldb(PyLdbMessageObject *self, void *closure)
4363 if (self->pyldb == NULL) {
4364 Py_RETURN_NONE;
4366 Py_INCREF(self->pyldb);
4367 return (PyObject *)self->pyldb;
4371 static PyGetSetDef py_ldb_msg_getset[] = {
4373 .name = discard_const_p(char, "dn"),
4374 .get = (getter)py_ldb_msg_get_dn,
4375 .set = (setter)py_ldb_msg_set_dn,
4378 .name = discard_const_p(char, "text"),
4379 .get = (getter)py_ldb_msg_get_text,
4382 .name = discard_const_p(char, "ldb"),
4383 .get = (getter)py_ldb_msg_get_ldb,
4384 .doc = discard_const_p(
4385 char, "returns the associated ldb object (or None)")
4387 { .name = NULL },
4390 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
4392 PyObject *dict = PyDict_New(), *ret, *repr;
4393 const char *repr_str = NULL;
4394 if (dict == NULL) {
4395 return NULL;
4397 if (PyDict_Update(dict, (PyObject *)self) != 0) {
4398 Py_DECREF(dict);
4399 return NULL;
4401 repr = PyObject_Repr(dict);
4402 if (repr == NULL) {
4403 Py_DECREF(dict);
4404 return NULL;
4406 repr_str = PyUnicode_AsUTF8(repr);
4407 if (repr_str == NULL) {
4408 Py_DECREF(repr);
4409 Py_DECREF(dict);
4410 return NULL;
4412 ret = PyUnicode_FromFormat("Message(%s)", repr_str);
4413 Py_DECREF(repr);
4414 Py_DECREF(dict);
4415 return ret;
4418 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
4420 talloc_free(self->mem_ctx);
4421 /* The pyldb element will only be present if a DN is assigned */
4422 if (self->pyldb) {
4423 Py_DECREF(self->pyldb);
4425 PyObject_Del(self);
4428 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
4429 PyLdbMessageObject *py_msg2, int op)
4431 struct ldb_message *msg1, *msg2;
4432 unsigned int i;
4433 int ret;
4435 if (!pyldb_Message_Check(py_msg2)) {
4436 Py_INCREF(Py_NotImplemented);
4437 return Py_NotImplemented;
4440 PyErr_LDB_MESSAGE_OR_RAISE(py_msg1, msg1);
4441 PyErr_LDB_MESSAGE_OR_RAISE(py_msg2, msg2);
4443 * FIXME: this can be a non-transitive compare, unsuitable for
4444 * sorting.
4446 * supposing msg1, msg2, and msg3 have 1, 2, and 3 elements
4447 * each. msg2 has a NULL DN, while msg1 has a DN that compares
4448 * higher than msg3. Then:
4450 * msg1 < msg2, due to num_elements.
4451 * msg2 < msg3, due to num_elements.
4452 * msg1 > msg3, due to DNs.
4454 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
4455 ret = ldb_dn_compare(msg1->dn, msg2->dn);
4456 if (ret != 0) {
4457 return richcmp(ret, op);
4461 if (msg1->num_elements > msg2->num_elements) {
4462 return richcmp(1, op);
4464 if (msg1->num_elements < msg2->num_elements) {
4465 return richcmp(-1, op);
4468 for (i = 0; i < msg1->num_elements; i++) {
4469 ret = ldb_msg_element_compare_name(&msg1->elements[i],
4470 &msg2->elements[i]);
4471 if (ret != 0) {
4472 return richcmp(ret, op);
4475 ret = ldb_msg_element_compare(&msg1->elements[i],
4476 &msg2->elements[i]);
4477 if (ret != 0) {
4478 return richcmp(ret, op);
4482 return richcmp(0, op);
4485 static PyTypeObject PyLdbMessage = {
4486 .tp_name = "ldb.Message",
4487 .tp_methods = py_ldb_msg_methods,
4488 .tp_getset = py_ldb_msg_getset,
4489 .tp_as_sequence = &py_ldb_msg_sequence,
4490 .tp_as_mapping = &py_ldb_msg_mapping,
4491 .tp_basicsize = sizeof(PyLdbMessageObject),
4492 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
4493 .tp_new = py_ldb_msg_new,
4494 .tp_repr = (reprfunc)py_ldb_msg_repr,
4495 .tp_flags = Py_TPFLAGS_DEFAULT,
4496 .tp_iter = (getiterfunc)py_ldb_msg_iter,
4497 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
4498 .tp_doc = "A LDB Message",
4501 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
4503 talloc_free(self->mem_ctx);
4504 PyObject_Del(self);
4507 static PyTypeObject PyLdbTree = {
4508 .tp_name = "ldb.Tree",
4509 .tp_basicsize = sizeof(PyLdbTreeObject),
4510 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
4511 .tp_flags = Py_TPFLAGS_DEFAULT,
4512 .tp_doc = "A search tree",
4515 static PyObject *py_timestring(PyObject *module, PyObject *args)
4517 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4518 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4519 long int t_val;
4520 char *tresult;
4521 PyObject *ret;
4522 if (!PyArg_ParseTuple(args, "l", &t_val))
4523 return NULL;
4524 tresult = ldb_timestring(NULL, (time_t) t_val);
4525 if (tresult == NULL) {
4527 * Most likely EOVERFLOW from gmtime()
4529 PyErr_SetFromErrno(PyExc_OSError);
4530 return NULL;
4532 ret = PyUnicode_FromString(tresult);
4533 talloc_free(tresult);
4534 return ret;
4537 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4539 char *str;
4540 time_t t;
4541 if (!PyArg_ParseTuple(args, "s", &str)) {
4542 return NULL;
4544 t = ldb_string_to_time(str);
4546 if (t == 0 && errno != 0) {
4547 PyErr_SetFromErrno(PyExc_ValueError);
4548 return NULL;
4550 return PyLong_FromLong(t);
4553 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4555 char *name;
4556 if (!PyArg_ParseTuple(args, "s", &name))
4557 return NULL;
4558 return PyBool_FromLong(ldb_valid_attr_name(name));
4562 encode a string using RFC2254 rules
4564 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4566 char *str, *encoded;
4567 Py_ssize_t size = 0;
4568 struct ldb_val val;
4569 PyObject *ret;
4571 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4572 return NULL;
4573 val.data = (uint8_t *)str;
4574 val.length = size;
4576 encoded = ldb_binary_encode(NULL, val);
4577 if (encoded == NULL) {
4578 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4579 return NULL;
4581 ret = PyUnicode_FromString(encoded);
4582 talloc_free(encoded);
4583 return ret;
4587 decode a string using RFC2254 rules
4589 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4591 char *str;
4592 struct ldb_val val;
4593 PyObject *ret;
4595 if (!PyArg_ParseTuple(args, "s", &str))
4596 return NULL;
4598 val = ldb_binary_decode(NULL, str);
4599 if (val.data == NULL) {
4600 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4601 return NULL;
4603 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4604 talloc_free(val.data);
4605 return ret;
4608 static PyMethodDef py_ldb_global_methods[] = {
4609 { "timestring", py_timestring, METH_VARARGS,
4610 "S.timestring(int) -> string\n\n"
4611 "Generate a LDAP time string from a UNIX timestamp" },
4612 { "string_to_time", py_string_to_time, METH_VARARGS,
4613 "S.string_to_time(string) -> int\n\n"
4614 "Parse a LDAP time string into a UNIX timestamp." },
4615 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4616 "S.valid_attr_name(name) -> bool\n\n"
4617 "Check whether the supplied name is a valid attribute name." },
4618 { "binary_encode", py_binary_encode, METH_VARARGS,
4619 "S.binary_encode(string) -> string\n\n"
4620 "Perform a RFC2254 binary encoding on a string" },
4621 { "binary_decode", py_binary_decode, METH_VARARGS,
4622 "S.binary_decode(string) -> string\n\n"
4623 "Perform a RFC2254 binary decode on a string" },
4627 #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."
4629 static struct PyModuleDef moduledef = {
4630 PyModuleDef_HEAD_INIT,
4631 .m_name = "ldb",
4632 .m_doc = MODULE_DOC,
4633 .m_size = -1,
4634 .m_methods = py_ldb_global_methods,
4637 static PyObject* module_init(void)
4639 PyObject *m;
4641 PyLdbBytesType.tp_base = &PyBytes_Type;
4642 if (PyType_Ready(&PyLdbBytesType) < 0) {
4643 return NULL;
4646 if (PyType_Ready(&PyLdbDn) < 0)
4647 return NULL;
4649 if (PyType_Ready(&PyLdbMessage) < 0)
4650 return NULL;
4652 if (PyType_Ready(&PyLdbMessageElement) < 0)
4653 return NULL;
4655 if (PyType_Ready(&PyLdb) < 0)
4656 return NULL;
4658 if (PyType_Ready(&PyLdbTree) < 0)
4659 return NULL;
4661 if (PyType_Ready(&PyLdbResult) < 0)
4662 return NULL;
4664 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4665 return NULL;
4667 if (PyType_Ready(&PyLdbControl) < 0)
4668 return NULL;
4670 m = PyModule_Create(&moduledef);
4671 if (m == NULL)
4672 return NULL;
4674 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4676 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4677 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4678 ADD_LDB_INT(SEQ_NEXT);
4679 ADD_LDB_INT(SCOPE_DEFAULT);
4680 ADD_LDB_INT(SCOPE_BASE);
4681 ADD_LDB_INT(SCOPE_ONELEVEL);
4682 ADD_LDB_INT(SCOPE_SUBTREE);
4684 ADD_LDB_INT(CHANGETYPE_NONE);
4685 ADD_LDB_INT(CHANGETYPE_ADD);
4686 ADD_LDB_INT(CHANGETYPE_DELETE);
4687 ADD_LDB_INT(CHANGETYPE_MODIFY);
4688 ADD_LDB_INT(CHANGETYPE_MODRDN);
4690 ADD_LDB_INT(FLAG_MOD_ADD);
4691 ADD_LDB_INT(FLAG_MOD_REPLACE);
4692 ADD_LDB_INT(FLAG_MOD_DELETE);
4693 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4695 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4696 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4697 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4698 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4700 ADD_LDB_INT(SUCCESS);
4701 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4702 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4703 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4704 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4705 ADD_LDB_INT(ERR_COMPARE_FALSE);
4706 ADD_LDB_INT(ERR_COMPARE_TRUE);
4707 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4708 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4709 ADD_LDB_INT(ERR_REFERRAL);
4710 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4711 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4712 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4713 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4714 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4715 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4716 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4717 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4718 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4719 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4720 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4721 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4722 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4723 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4724 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4725 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4726 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4727 ADD_LDB_INT(ERR_BUSY);
4728 ADD_LDB_INT(ERR_UNAVAILABLE);
4729 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4730 ADD_LDB_INT(ERR_LOOP_DETECT);
4731 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4732 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4733 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4734 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4735 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4736 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4737 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4738 ADD_LDB_INT(ERR_OTHER);
4740 ADD_LDB_INT(FLG_RDONLY);
4741 ADD_LDB_INT(FLG_NOSYNC);
4742 ADD_LDB_INT(FLG_RECONNECT);
4743 ADD_LDB_INT(FLG_NOMMAP);
4744 ADD_LDB_INT(FLG_SHOW_BINARY);
4745 ADD_LDB_INT(FLG_ENABLE_TRACING);
4746 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4748 ADD_LDB_INT(PACKING_FORMAT);
4749 ADD_LDB_INT(PACKING_FORMAT_V2);
4751 /* Historical misspelling */
4752 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4754 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4756 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4757 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4759 Py_INCREF(&PyLdb);
4760 Py_INCREF(&PyLdbDn);
4761 Py_INCREF(&PyLdbMessage);
4762 Py_INCREF(&PyLdbMessageElement);
4763 Py_INCREF(&PyLdbTree);
4764 Py_INCREF(&PyLdbResult);
4765 Py_INCREF(&PyLdbControl);
4767 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4768 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4769 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4770 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4771 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4772 PyModule_AddObject(m, "Result", (PyObject *)&PyLdbResult);
4773 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4775 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4777 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4779 ADD_LDB_STRING(SYNTAX_DN);
4780 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4781 ADD_LDB_STRING(SYNTAX_INTEGER);
4782 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4783 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4784 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4785 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4786 ADD_LDB_STRING(OID_COMPARATOR_AND);
4787 ADD_LDB_STRING(OID_COMPARATOR_OR);
4789 return m;
4792 PyMODINIT_FUNC PyInit_ldb(void);
4793 PyMODINIT_FUNC PyInit_ldb(void)
4795 return module_init();