tests: Check that we return the posix type in query_directory
[samba4-gss.git] / lib / ldb / pyldb.c
blobbf4332882066cb03bd43472fa46e9149b8addd6a
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 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1346 const char *url = ldb_get_opaque(ldb_ctx, "ldb_url");
1347 if (url == NULL) {
1348 url = "no connection";
1350 return PyUnicode_FromFormat("<ldb connection %s>", url);
1353 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1354 PyObject *Py_UNUSED(ignored))
1356 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1357 if (dn == NULL)
1358 Py_RETURN_NONE;
1359 return py_ldb_dn_copy(dn, self);
1363 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1364 PyObject *Py_UNUSED(ignored))
1366 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1367 if (dn == NULL)
1368 Py_RETURN_NONE;
1369 return py_ldb_dn_copy(dn, self);
1372 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1373 PyObject *Py_UNUSED(ignored))
1375 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1376 if (dn == NULL)
1377 Py_RETURN_NONE;
1378 return py_ldb_dn_copy(dn, self);
1381 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1382 PyObject *Py_UNUSED(ignored))
1384 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1385 if (dn == NULL)
1386 Py_RETURN_NONE;
1387 return py_ldb_dn_copy(dn, self);
1390 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1391 const char *paramname)
1393 const char **ret;
1394 Py_ssize_t i;
1395 if (!PyList_Check(list)) {
1396 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1397 return NULL;
1399 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1400 if (ret == NULL) {
1401 PyErr_NoMemory();
1402 return NULL;
1405 for (i = 0; i < PyList_Size(list); i++) {
1406 const char *str = NULL;
1407 Py_ssize_t size;
1408 PyObject *item = PyList_GetItem(list, i);
1409 if (!PyUnicode_Check(item)) {
1410 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1411 talloc_free(ret);
1412 return NULL;
1414 str = PyUnicode_AsUTF8AndSize(item, &size);
1415 if (str == NULL) {
1416 talloc_free(ret);
1417 return NULL;
1419 ret[i] = talloc_strndup(ret, str, size);
1421 ret[i] = NULL;
1422 return ret;
1425 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs);
1427 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1429 const char * const kwnames[] = { "url", "flags", "options", NULL };
1430 char *url = NULL;
1431 PyObject *py_options = NULL;
1432 unsigned int flags = 0;
1434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1435 discard_const_p(char *, kwnames),
1436 &url, &flags, &py_options)) {
1437 return -1;
1440 if (url != NULL) {
1441 /* py_ldb_connect returns py_None on success, NULL on error */
1442 PyObject *result = py_ldb_connect(self, args, kwargs);
1443 if (result == NULL) {
1444 return -1;
1446 Py_DECREF(result);
1447 } else {
1448 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1449 ldb_set_flags(ldb, flags);
1452 return 0;
1455 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1457 TALLOC_CTX *mem_ctx = NULL;
1458 PyLdbObject *ret;
1459 struct ldb_context *ldb;
1461 mem_ctx = talloc_new(NULL);
1462 if (mem_ctx == NULL) {
1463 return PyErr_NoMemory();
1466 ldb = ldb_init(mem_ctx, NULL);
1467 if (ldb == NULL) {
1468 talloc_free(mem_ctx);
1469 PyErr_NoMemory();
1470 return NULL;
1473 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1474 if (ret == NULL) {
1475 talloc_free(mem_ctx);
1476 PyErr_NoMemory();
1477 return NULL;
1479 ret->mem_ctx = mem_ctx;
1481 ret->ldb_ctx = ldb;
1482 return (PyObject *)ret;
1485 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1487 char *url = NULL;
1488 unsigned int flags = 0;
1489 PyObject *py_options = Py_None;
1490 int ret;
1491 const char **options;
1492 const char * const kwnames[] = { "url", "flags", "options", NULL };
1493 struct ldb_context *ldb_ctx;
1495 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1496 discard_const_p(char *, kwnames),
1497 &url, &flags, &py_options))
1498 return NULL;
1500 if (py_options == Py_None) {
1501 options = NULL;
1502 } else {
1503 options = PyList_AsStrList(NULL, py_options, "options");
1504 if (options == NULL)
1505 return NULL;
1508 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1509 ret = ldb_connect(ldb_ctx, url, flags, options);
1510 talloc_free(options);
1512 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1514 Py_RETURN_NONE;
1517 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1519 PyObject *py_msg;
1520 PyObject *py_controls = Py_None;
1521 struct ldb_context *ldb_ctx;
1522 struct ldb_request *req;
1523 struct ldb_control **parsed_controls;
1524 struct ldb_message *msg;
1525 int ret;
1526 TALLOC_CTX *mem_ctx;
1527 bool validate=true;
1528 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1530 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1531 discard_const_p(char *, kwnames),
1532 &py_msg, &py_controls, &validate))
1533 return NULL;
1535 mem_ctx = talloc_new(NULL);
1536 if (mem_ctx == NULL) {
1537 PyErr_NoMemory();
1538 return NULL;
1540 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1542 if (py_controls == Py_None) {
1543 parsed_controls = NULL;
1544 } else {
1545 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1546 if (controls == NULL) {
1547 talloc_free(mem_ctx);
1548 return NULL;
1550 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1551 if (controls[0] != NULL && parsed_controls == NULL) {
1552 talloc_free(mem_ctx);
1553 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1554 return NULL;
1556 talloc_free(controls);
1559 if (!pyldb_Message_Check(py_msg)) {
1560 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1561 talloc_free(mem_ctx);
1562 return NULL;
1564 msg = pyldb_Message_AsMessage(py_msg);
1566 if (validate) {
1567 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1568 if (ret != LDB_SUCCESS) {
1569 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1570 talloc_free(mem_ctx);
1571 return NULL;
1575 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1576 NULL, ldb_op_default_callback, NULL);
1577 if (ret != LDB_SUCCESS) {
1578 PyErr_SetString(PyExc_TypeError, "failed to build request");
1579 talloc_free(mem_ctx);
1580 return NULL;
1583 /* do request and autostart a transaction */
1584 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1586 ret = ldb_transaction_start(ldb_ctx);
1587 if (ret != LDB_SUCCESS) {
1588 talloc_free(mem_ctx);
1589 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1590 return NULL;
1593 ret = ldb_request(ldb_ctx, req);
1594 if (ret == LDB_SUCCESS) {
1595 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1598 if (ret == LDB_SUCCESS) {
1599 ret = ldb_transaction_commit(ldb_ctx);
1600 } else {
1601 ldb_transaction_cancel(ldb_ctx);
1604 talloc_free(mem_ctx);
1605 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1607 Py_RETURN_NONE;
1612 * Obtain a ldb message from a Python Dictionary object.
1614 * @param mem_ctx Memory context
1615 * @param py_obj Python Dictionary object
1616 * @param ldb_ctx LDB context
1617 * @param mod_flags Flags to be set on every message element
1618 * @return ldb_message on success or NULL on failure
1620 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1621 PyObject *py_obj,
1622 struct ldb_context *ldb_ctx,
1623 unsigned int mod_flags)
1625 struct ldb_message *msg;
1626 unsigned int msg_pos = 0;
1627 Py_ssize_t dict_pos = 0;
1628 PyObject *key, *value;
1629 struct ldb_message_element *msg_el;
1630 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1632 msg = ldb_msg_new(mem_ctx);
1633 if (msg == NULL) {
1634 PyErr_NoMemory();
1635 return NULL;
1637 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1638 if (msg->elements == NULL) {
1639 PyErr_NoMemory();
1640 TALLOC_FREE(msg);
1641 return NULL;
1644 if (dn_value) {
1645 struct ldb_dn *dn = NULL;
1646 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &dn)) {
1647 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1648 TALLOC_FREE(msg);
1649 return NULL;
1651 if (dn == NULL) {
1652 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1653 TALLOC_FREE(msg);
1654 return NULL;
1656 msg->dn = talloc_reference(msg, dn);
1657 if (msg->dn == NULL) {
1658 talloc_free(mem_ctx);
1659 PyErr_NoMemory();
1660 return NULL;
1662 } else {
1663 PyErr_SetString(PyExc_TypeError, "no dn set");
1664 TALLOC_FREE(msg);
1665 return NULL;
1668 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1669 const char *key_str = PyUnicode_AsUTF8(key);
1670 if (ldb_attr_cmp(key_str, "dn") != 0) {
1671 msg_el = PyObject_AsMessageElement(msg->elements, value,
1672 mod_flags, key_str);
1673 if (msg_el == NULL) {
1674 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1675 TALLOC_FREE(msg);
1676 return NULL;
1678 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1681 * PyObject_AsMessageElement might have returned a
1682 * reference to an existing MessageElement, and so left
1683 * the name and flags unchanged. Thus if those members
1684 * aren’t set, we’ll assume that the user forgot to
1685 * initialize them.
1687 if (msg->elements[msg_pos].name == NULL) {
1688 /* No name was set — set it now. */
1689 msg->elements[msg_pos].name = talloc_strdup(msg->elements, key_str);
1690 if (msg->elements[msg_pos].name == NULL) {
1691 PyErr_NoMemory();
1692 TALLOC_FREE(msg);
1693 return NULL;
1696 if (msg->elements[msg_pos].flags == 0) {
1697 /* No flags were set — set them now. */
1698 msg->elements[msg_pos].flags = mod_flags;
1701 msg_pos++;
1705 msg->num_elements = msg_pos;
1707 return msg;
1710 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1712 PyObject *py_obj;
1713 int ret;
1714 struct ldb_context *ldb_ctx;
1715 struct ldb_request *req;
1716 struct ldb_message *msg = NULL;
1717 PyObject *py_controls = Py_None;
1718 TALLOC_CTX *mem_ctx;
1719 struct ldb_control **parsed_controls;
1720 const char * const kwnames[] = { "message", "controls", NULL };
1722 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1723 discard_const_p(char *, kwnames),
1724 &py_obj, &py_controls))
1725 return NULL;
1727 mem_ctx = talloc_new(NULL);
1728 if (mem_ctx == NULL) {
1729 PyErr_NoMemory();
1730 return NULL;
1732 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1734 if (py_controls == Py_None) {
1735 parsed_controls = NULL;
1736 } else {
1737 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1738 if (controls == NULL) {
1739 talloc_free(mem_ctx);
1740 return NULL;
1742 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1743 if (controls[0] != NULL && parsed_controls == NULL) {
1744 talloc_free(mem_ctx);
1745 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1746 return NULL;
1748 talloc_free(controls);
1751 if (pyldb_Message_Check(py_obj)) {
1752 msg = pyldb_Message_AsMessage(py_obj);
1753 } else if (PyDict_Check(py_obj)) {
1754 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1755 } else {
1756 PyErr_SetString(PyExc_TypeError,
1757 "Dictionary or LdbMessage object expected!");
1760 if (!msg) {
1761 /* we should have a PyErr already set */
1762 talloc_free(mem_ctx);
1763 return NULL;
1766 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1767 if (ret != LDB_SUCCESS) {
1768 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1769 talloc_free(mem_ctx);
1770 return NULL;
1773 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1774 NULL, ldb_op_default_callback, NULL);
1775 if (ret != LDB_SUCCESS) {
1776 PyErr_SetString(PyExc_TypeError, "failed to build request");
1777 talloc_free(mem_ctx);
1778 return NULL;
1781 /* do request and autostart a transaction */
1782 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1784 ret = ldb_transaction_start(ldb_ctx);
1785 if (ret != LDB_SUCCESS) {
1786 talloc_free(mem_ctx);
1787 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1788 return NULL;
1791 ret = ldb_request(ldb_ctx, req);
1792 if (ret == LDB_SUCCESS) {
1793 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1796 if (ret == LDB_SUCCESS) {
1797 ret = ldb_transaction_commit(ldb_ctx);
1798 } else {
1799 ldb_transaction_cancel(ldb_ctx);
1802 talloc_free(mem_ctx);
1803 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1805 Py_RETURN_NONE;
1808 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1810 PyObject *py_dn;
1811 struct ldb_dn *dn;
1812 int ret;
1813 struct ldb_context *ldb_ctx;
1814 struct ldb_request *req;
1815 PyObject *py_controls = Py_None;
1816 TALLOC_CTX *mem_ctx;
1817 struct ldb_control **parsed_controls;
1818 const char * const kwnames[] = { "dn", "controls", NULL };
1820 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1821 discard_const_p(char *, kwnames),
1822 &py_dn, &py_controls))
1823 return NULL;
1825 mem_ctx = talloc_new(NULL);
1826 if (mem_ctx == NULL) {
1827 PyErr_NoMemory();
1828 return NULL;
1830 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1832 if (py_controls == Py_None) {
1833 parsed_controls = NULL;
1834 } else {
1835 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1836 if (controls == NULL) {
1837 talloc_free(mem_ctx);
1838 return NULL;
1840 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1841 if (controls[0] != NULL && parsed_controls == NULL) {
1842 talloc_free(mem_ctx);
1843 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1844 return NULL;
1846 talloc_free(controls);
1849 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1850 talloc_free(mem_ctx);
1851 return NULL;
1854 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1855 NULL, ldb_op_default_callback, NULL);
1856 if (ret != LDB_SUCCESS) {
1857 PyErr_SetString(PyExc_TypeError, "failed to build request");
1858 talloc_free(mem_ctx);
1859 return NULL;
1862 /* do request and autostart a transaction */
1863 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1865 ret = ldb_transaction_start(ldb_ctx);
1866 if (ret != LDB_SUCCESS) {
1867 talloc_free(mem_ctx);
1868 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1869 return NULL;
1872 ret = ldb_request(ldb_ctx, req);
1873 if (ret == LDB_SUCCESS) {
1874 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1877 if (ret == LDB_SUCCESS) {
1878 ret = ldb_transaction_commit(ldb_ctx);
1879 } else {
1880 ldb_transaction_cancel(ldb_ctx);
1883 talloc_free(mem_ctx);
1884 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1886 Py_RETURN_NONE;
1889 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1891 PyObject *py_dn1, *py_dn2;
1892 struct ldb_dn *dn1, *dn2;
1893 int ret;
1894 TALLOC_CTX *mem_ctx;
1895 PyObject *py_controls = Py_None;
1896 struct ldb_control **parsed_controls;
1897 struct ldb_context *ldb_ctx;
1898 struct ldb_request *req;
1899 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1901 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1903 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1904 discard_const_p(char *, kwnames),
1905 &py_dn1, &py_dn2, &py_controls))
1906 return NULL;
1909 mem_ctx = talloc_new(NULL);
1910 if (mem_ctx == NULL) {
1911 PyErr_NoMemory();
1912 return NULL;
1915 if (py_controls == Py_None) {
1916 parsed_controls = NULL;
1917 } else {
1918 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1919 if (controls == NULL) {
1920 talloc_free(mem_ctx);
1921 return NULL;
1923 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1924 if (controls[0] != NULL && parsed_controls == NULL) {
1925 talloc_free(mem_ctx);
1926 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
1927 return NULL;
1929 talloc_free(controls);
1933 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1934 talloc_free(mem_ctx);
1935 return NULL;
1938 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1939 talloc_free(mem_ctx);
1940 return NULL;
1943 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1944 NULL, ldb_op_default_callback, NULL);
1945 if (ret != LDB_SUCCESS) {
1946 PyErr_SetString(PyExc_TypeError, "failed to build request");
1947 talloc_free(mem_ctx);
1948 return NULL;
1951 /* do request and autostart a transaction */
1952 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1954 ret = ldb_transaction_start(ldb_ctx);
1955 if (ret != LDB_SUCCESS) {
1956 talloc_free(mem_ctx);
1957 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1958 return NULL;
1961 ret = ldb_request(ldb_ctx, req);
1962 if (ret == LDB_SUCCESS) {
1963 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1966 if (ret == LDB_SUCCESS) {
1967 ret = ldb_transaction_commit(ldb_ctx);
1968 } else {
1969 ldb_transaction_cancel(ldb_ctx);
1972 talloc_free(mem_ctx);
1973 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1975 Py_RETURN_NONE;
1978 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1980 char *name;
1981 if (!PyArg_ParseTuple(args, "s", &name))
1982 return NULL;
1984 ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1986 Py_RETURN_NONE;
1989 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1991 char *attribute, *syntax;
1992 unsigned int flags;
1993 int ret;
1994 struct ldb_context *ldb_ctx;
1996 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1997 return NULL;
1999 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2000 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
2002 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
2004 Py_RETURN_NONE;
2007 static PyObject *ldb_ldif_to_pyobject(PyLdbObject *pyldb, struct ldb_ldif *ldif)
2009 PyObject *obj = NULL;
2010 PyObject *result = NULL;
2011 struct ldb_context *ldb = pyldb->ldb_ctx;
2013 if (ldif == NULL) {
2014 Py_RETURN_NONE;
2017 switch (ldif->changetype) {
2018 case LDB_CHANGETYPE_NONE:
2019 case LDB_CHANGETYPE_ADD:
2020 obj = PyLdbMessage_FromMessage(ldif->msg, pyldb);
2021 break;
2022 case LDB_CHANGETYPE_MODIFY:
2023 obj = PyLdbMessage_FromMessage(ldif->msg, pyldb);
2024 break;
2025 case LDB_CHANGETYPE_DELETE:
2026 if (ldif->msg->num_elements != 0) {
2027 PyErr_Format(PyExc_ValueError,
2028 "CHANGETYPE(DELETE) with num_elements=%u",
2029 ldif->msg->num_elements);
2030 return NULL;
2032 obj = pyldb_Dn_FromDn(ldif->msg->dn, pyldb);
2033 break;
2034 case LDB_CHANGETYPE_MODRDN: {
2035 struct ldb_dn *olddn = NULL;
2036 PyObject *olddn_obj = NULL;
2037 bool deleteoldrdn = false;
2038 PyObject *deleteoldrdn_obj = NULL;
2039 struct ldb_dn *newdn = NULL;
2040 PyObject *newdn_obj = NULL;
2041 int ret;
2043 ret = ldb_ldif_parse_modrdn(ldb,
2044 ldif,
2045 ldif,
2046 &olddn,
2047 NULL,
2048 &deleteoldrdn,
2049 NULL,
2050 &newdn);
2051 if (ret != LDB_SUCCESS) {
2052 PyErr_Format(PyExc_ValueError,
2053 "ldb_ldif_parse_modrdn() failed");
2054 return NULL;
2057 olddn_obj = pyldb_Dn_FromDn(olddn, pyldb);
2058 if (olddn_obj == NULL) {
2059 return NULL;
2061 if (deleteoldrdn) {
2062 deleteoldrdn_obj = Py_True;
2063 } else {
2064 deleteoldrdn_obj = Py_False;
2066 newdn_obj = pyldb_Dn_FromDn(newdn, pyldb);
2067 if (newdn_obj == NULL) {
2068 deleteoldrdn_obj = NULL;
2069 Py_CLEAR(olddn_obj);
2070 return NULL;
2073 obj = Py_BuildValue(discard_const_p(char, "{s:O,s:O,s:O}"),
2074 "olddn", olddn_obj,
2075 "deleteoldrdn", deleteoldrdn_obj,
2076 "newdn", newdn_obj);
2077 Py_CLEAR(olddn_obj);
2078 deleteoldrdn_obj = NULL;
2079 Py_CLEAR(newdn_obj);
2081 break;
2082 default:
2083 PyErr_Format(PyExc_NotImplementedError,
2084 "Unsupported LDB_CHANGETYPE(%u)",
2085 ldif->changetype);
2086 return NULL;
2089 if (obj == NULL) {
2090 return NULL;
2093 /* We don't want this being attached * to the 'ldb' any more */
2094 result = Py_BuildValue(discard_const_p(char, "(iO)"),
2095 ldif->changetype,
2096 obj);
2097 Py_CLEAR(obj);
2098 return result;
2102 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
2104 int changetype;
2105 PyObject *py_msg;
2106 struct ldb_ldif ldif;
2107 PyObject *ret;
2108 char *string;
2109 TALLOC_CTX *mem_ctx;
2111 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
2112 return NULL;
2114 if (!pyldb_Message_Check(py_msg)) {
2115 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
2116 return NULL;
2119 ldif.msg = pyldb_Message_AsMessage(py_msg);
2120 ldif.changetype = changetype;
2122 mem_ctx = talloc_new(NULL);
2123 if (mem_ctx == NULL) {
2124 return PyErr_NoMemory();
2127 string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
2128 if (!string) {
2129 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
2130 talloc_free(mem_ctx);
2131 return NULL;
2134 ret = PyUnicode_FromString(string);
2136 talloc_free(mem_ctx);
2138 return ret;
2141 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
2143 PyObject *list, *ret;
2144 struct ldb_ldif *ldif;
2145 const char *s;
2146 struct ldb_dn *last_dn = NULL;
2148 TALLOC_CTX *mem_ctx;
2150 if (!PyArg_ParseTuple(args, "s", &s))
2151 return NULL;
2153 mem_ctx = talloc_new(NULL);
2154 if (!mem_ctx) {
2155 Py_RETURN_NONE;
2158 list = PyList_New(0);
2159 if (list == NULL) {
2160 talloc_free(mem_ctx);
2161 return NULL;
2164 while (s && *s != '\0') {
2165 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
2166 talloc_steal(mem_ctx, ldif);
2167 if (ldif) {
2168 int res = 0;
2169 PyObject *py_ldif = ldb_ldif_to_pyobject(self, ldif);
2170 if (py_ldif == NULL) {
2171 Py_CLEAR(list);
2172 if (PyErr_Occurred() == NULL) {
2173 PyErr_BadArgument();
2175 talloc_free(mem_ctx);
2176 return NULL;
2178 res = PyList_Append(list, py_ldif);
2179 Py_CLEAR(py_ldif);
2180 if (res == -1) {
2181 Py_CLEAR(list);
2182 talloc_free(mem_ctx);
2183 return NULL;
2185 last_dn = ldif->msg->dn;
2186 } else {
2187 const char *last_dn_str = NULL;
2188 const char *err_string = NULL;
2189 if (last_dn == NULL) {
2190 PyErr_SetString(PyExc_ValueError,
2191 "unable to parse LDIF "
2192 "string at first chunk");
2193 Py_CLEAR(list);
2194 talloc_free(mem_ctx);
2195 return NULL;
2198 last_dn_str
2199 = ldb_dn_get_linearized(last_dn);
2201 err_string
2202 = talloc_asprintf(mem_ctx,
2203 "unable to parse ldif "
2204 "string AFTER %s",
2205 last_dn_str);
2207 PyErr_SetString(PyExc_ValueError,
2208 err_string);
2209 talloc_free(mem_ctx);
2210 Py_CLEAR(list);
2211 return NULL;
2214 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
2215 ret = PyObject_GetIter(list);
2216 Py_DECREF(list);
2217 return ret;
2220 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
2222 int ldb_ret;
2223 PyObject *py_msg_old;
2224 PyObject *py_msg_new;
2225 struct ldb_message *diff;
2226 struct ldb_context *ldb;
2227 PyObject *py_ret;
2228 TALLOC_CTX *mem_ctx = NULL;
2230 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
2231 return NULL;
2233 if (!pyldb_Message_Check(py_msg_old)) {
2234 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
2235 return NULL;
2238 if (!pyldb_Message_Check(py_msg_new)) {
2239 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
2240 return NULL;
2243 mem_ctx = talloc_new(NULL);
2244 if (mem_ctx == NULL) {
2245 PyErr_NoMemory();
2246 return NULL;
2249 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2250 ldb_ret = ldb_msg_difference(ldb, mem_ctx,
2251 pyldb_Message_AsMessage(py_msg_old),
2252 pyldb_Message_AsMessage(py_msg_new),
2253 &diff);
2254 if (ldb_ret != LDB_SUCCESS) {
2255 talloc_free(mem_ctx);
2256 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
2257 return NULL;
2260 diff = ldb_msg_copy(mem_ctx, diff);
2261 if (diff == NULL) {
2262 talloc_free(mem_ctx);
2263 PyErr_NoMemory();
2264 return NULL;
2267 py_ret = PyLdbMessage_FromMessage(diff, self);
2269 talloc_free(mem_ctx);
2271 return py_ret;
2274 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
2276 const struct ldb_schema_attribute *a;
2277 struct ldb_val old_val;
2278 struct ldb_val new_val;
2279 TALLOC_CTX *mem_ctx;
2280 PyObject *ret;
2281 char *element_name;
2282 PyObject *val;
2283 Py_ssize_t size;
2284 int result;
2286 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
2287 return NULL;
2289 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
2290 old_val.length = size;
2292 if (result != 0) {
2293 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
2294 return NULL;
2297 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
2299 if (a == NULL) {
2300 Py_RETURN_NONE;
2303 mem_ctx = talloc_new(NULL);
2304 if (mem_ctx == NULL) {
2305 PyErr_NoMemory();
2306 return NULL;
2309 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
2310 talloc_free(mem_ctx);
2311 Py_RETURN_NONE;
2314 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
2316 talloc_free(mem_ctx);
2318 return ret;
2321 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2323 PyObject *py_base = Py_None;
2324 int scope = LDB_SCOPE_DEFAULT;
2325 char *expr = NULL;
2326 PyObject *py_attrs = Py_None;
2327 PyObject *py_controls = Py_None;
2328 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
2329 int ret;
2330 struct ldb_result *res;
2331 struct ldb_request *req;
2332 const char **attrs;
2333 struct ldb_context *ldb_ctx;
2334 struct ldb_control **parsed_controls;
2335 struct ldb_dn *base;
2336 PyObject *py_ret;
2337 TALLOC_CTX *mem_ctx;
2339 /* type "int" rather than "enum" for "scope" is intentional */
2340 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
2341 discard_const_p(char *, kwnames),
2342 &py_base, &scope, &expr, &py_attrs, &py_controls))
2343 return NULL;
2346 mem_ctx = talloc_new(NULL);
2347 if (mem_ctx == NULL) {
2348 PyErr_NoMemory();
2349 return NULL;
2351 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2353 if (py_attrs == Py_None) {
2354 attrs = NULL;
2355 } else {
2356 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
2357 if (attrs == NULL) {
2358 talloc_free(mem_ctx);
2359 return NULL;
2363 if (py_base == Py_None) {
2364 base = ldb_get_default_basedn(ldb_ctx);
2365 } else {
2366 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
2367 talloc_free(mem_ctx);
2368 return NULL;
2372 if (py_controls == Py_None) {
2373 parsed_controls = NULL;
2374 } else {
2375 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
2376 if (controls == NULL) {
2377 talloc_free(mem_ctx);
2378 return NULL;
2380 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
2381 if (controls[0] != NULL && parsed_controls == NULL) {
2382 talloc_free(mem_ctx);
2383 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2384 return NULL;
2386 talloc_free(controls);
2389 res = talloc_zero(mem_ctx, struct ldb_result);
2390 if (res == NULL) {
2391 PyErr_NoMemory();
2392 talloc_free(mem_ctx);
2393 return NULL;
2396 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
2397 base,
2398 scope,
2399 expr,
2400 attrs,
2401 parsed_controls,
2402 res,
2403 ldb_search_default_callback,
2404 NULL);
2406 if (ret != LDB_SUCCESS) {
2407 talloc_free(mem_ctx);
2408 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2409 return NULL;
2412 talloc_steal(req, attrs);
2414 ret = ldb_request(ldb_ctx, req);
2416 if (ret == LDB_SUCCESS) {
2417 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
2420 if (ret != LDB_SUCCESS) {
2421 talloc_free(mem_ctx);
2422 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2423 return NULL;
2426 py_ret = PyLdbResult_FromResult(res, self);
2428 talloc_free(mem_ctx);
2430 return py_ret;
2433 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
2435 if (reply->py_iter != NULL) {
2436 DLIST_REMOVE(reply->py_iter->state.next, reply);
2437 if (reply->py_iter->state.result == reply) {
2438 reply->py_iter->state.result = NULL;
2440 reply->py_iter = NULL;
2443 Py_CLEAR(reply->obj);
2445 return 0;
2448 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2449 struct ldb_reply *ares)
2451 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2452 struct ldb_result result = { .msgs = NULL };
2453 struct py_ldb_search_iterator_reply *reply = NULL;
2455 if (ares == NULL) {
2456 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2459 if (ares->error != LDB_SUCCESS) {
2460 int ret = ares->error;
2461 TALLOC_FREE(ares);
2462 return ldb_request_done(req, ret);
2465 reply = talloc_zero(py_iter->mem_ctx,
2466 struct py_ldb_search_iterator_reply);
2467 if (reply == NULL) {
2468 TALLOC_FREE(ares);
2469 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2471 reply->py_iter = py_iter;
2472 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2474 switch (ares->type) {
2475 case LDB_REPLY_ENTRY:
2476 reply->obj = PyLdbMessage_FromMessage(ares->message, py_iter->ldb);
2477 if (reply->obj == NULL) {
2478 TALLOC_FREE(ares);
2479 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2481 DLIST_ADD_END(py_iter->state.next, reply);
2482 TALLOC_FREE(ares);
2483 return LDB_SUCCESS;
2485 case LDB_REPLY_REFERRAL:
2486 reply->obj = PyUnicode_FromString(ares->referral);
2487 if (reply->obj == NULL) {
2488 TALLOC_FREE(ares);
2489 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2491 DLIST_ADD_END(py_iter->state.next, reply);
2492 TALLOC_FREE(ares);
2493 return LDB_SUCCESS;
2495 case LDB_REPLY_DONE:
2496 result = (struct ldb_result) { .controls = ares->controls };
2497 reply->obj = PyLdbResult_FromResult(&result, py_iter->ldb);
2498 if (reply->obj == NULL) {
2499 TALLOC_FREE(ares);
2500 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2502 py_iter->state.result = reply;
2503 TALLOC_FREE(ares);
2504 return ldb_request_done(req, LDB_SUCCESS);
2507 TALLOC_FREE(ares);
2508 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2511 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2513 PyObject *py_base = Py_None;
2514 int scope = LDB_SCOPE_DEFAULT;
2515 int timeout = 0;
2516 char *expr = NULL;
2517 PyObject *py_attrs = Py_None;
2518 PyObject *py_controls = Py_None;
2519 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2520 int ret;
2521 const char **attrs;
2522 struct ldb_context *ldb_ctx;
2523 struct ldb_control **parsed_controls;
2524 struct ldb_dn *base;
2525 PyLdbSearchIteratorObject *py_iter;
2527 /* type "int" rather than "enum" for "scope" is intentional */
2528 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2529 discard_const_p(char *, kwnames),
2530 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2531 return NULL;
2533 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2534 if (py_iter == NULL) {
2535 PyErr_NoMemory();
2536 return NULL;
2538 py_iter->ldb = self;
2539 Py_INCREF(self);
2540 ZERO_STRUCT(py_iter->state);
2541 py_iter->mem_ctx = talloc_new(NULL);
2542 if (py_iter->mem_ctx == NULL) {
2543 Py_DECREF(py_iter);
2544 PyErr_NoMemory();
2545 return NULL;
2548 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2550 if (py_attrs == Py_None) {
2551 attrs = NULL;
2552 } else {
2553 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2554 if (attrs == NULL) {
2555 Py_DECREF(py_iter);
2556 PyErr_NoMemory();
2557 return NULL;
2561 if (py_base == Py_None) {
2562 base = ldb_get_default_basedn(ldb_ctx);
2563 } else {
2564 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2565 Py_DECREF(py_iter);
2566 PyErr_NoMemory();
2567 return NULL;
2571 if (py_controls == Py_None) {
2572 parsed_controls = NULL;
2573 } else {
2574 const char **controls = NULL;
2576 controls = PyList_AsStrList(py_iter->mem_ctx,
2577 py_controls, "controls");
2578 if (controls == NULL) {
2579 Py_DECREF(py_iter);
2580 PyErr_NoMemory();
2581 return NULL;
2584 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2585 py_iter->mem_ctx,
2586 controls);
2587 if (controls[0] != NULL && parsed_controls == NULL) {
2588 Py_DECREF(py_iter);
2589 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, ldb_ctx);
2590 return NULL;
2592 talloc_free(controls);
2595 ret = ldb_build_search_req(&py_iter->state.req,
2596 ldb_ctx,
2597 py_iter->mem_ctx,
2598 base,
2599 scope,
2600 expr,
2601 attrs,
2602 parsed_controls,
2603 py_iter,
2604 py_ldb_search_iterator_callback,
2605 NULL);
2606 if (ret != LDB_SUCCESS) {
2607 Py_DECREF(py_iter);
2608 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2609 return NULL;
2612 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2614 ret = ldb_request(ldb_ctx, py_iter->state.req);
2615 if (ret != LDB_SUCCESS) {
2616 Py_DECREF(py_iter);
2617 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2618 return NULL;
2621 return (PyObject *)py_iter;
2624 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2626 char *name;
2627 void *data;
2629 if (!PyArg_ParseTuple(args, "s", &name))
2630 return NULL;
2632 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2634 if (data == NULL)
2635 Py_RETURN_NONE;
2637 if (data == (void *)1) {
2639 * This value is sometimes used to indicate that a opaque is
2640 * set.
2642 Py_RETURN_TRUE;
2647 * Let’s hope the opaque data is actually a talloc pointer,
2648 * otherwise calling this would be Very Bad.
2650 const bool *opaque = talloc_get_type(data, bool);
2651 if (opaque != NULL) {
2652 return PyBool_FromLong(*opaque);
2657 const unsigned long long *opaque = talloc_get_type(
2658 data, unsigned long long);
2659 if (opaque != NULL) {
2660 return PyLong_FromUnsignedLongLong(*opaque);
2665 const char *opaque = talloc_get_type(data, char);
2666 if (opaque != NULL) {
2667 return PyUnicode_FromString(opaque);
2671 PyErr_SetString(PyExc_ValueError, "Unsupported type for opaque");
2672 return NULL;
2675 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2677 char *name;
2678 PyObject *data;
2679 void *value = NULL;
2680 int ret;
2682 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2683 return NULL;
2685 if (data == Py_None) {
2686 value = NULL;
2687 } else if (PyBool_Check(data)) {
2688 bool *opaque = NULL;
2689 bool b;
2691 const int is_true = PyObject_IsTrue(data);
2692 if (is_true == -1) {
2693 return NULL;
2695 b = is_true;
2698 opaque = talloc(self->ldb_ctx, bool);
2699 if (opaque == NULL) {
2700 return PyErr_NoMemory();
2702 *opaque = b;
2703 value = opaque;
2704 } else if (PyLong_Check(data)) {
2705 unsigned long long *opaque = NULL;
2706 const unsigned long long n = PyLong_AsUnsignedLongLong(data);
2707 if (n == -1 && PyErr_Occurred()) {
2708 return NULL;
2711 opaque = talloc(self->ldb_ctx, unsigned long long);
2712 if (opaque == NULL) {
2713 return PyErr_NoMemory();
2715 *opaque = n;
2716 value = opaque;
2717 } else if (PyUnicode_Check(data)) {
2718 char *opaque = NULL;
2719 const char *s = PyUnicode_AsUTF8(data);
2720 if (s == NULL) {
2721 return NULL;
2724 opaque = talloc_strdup(self->ldb_ctx, s);
2725 if (opaque == NULL) {
2726 return PyErr_NoMemory();
2730 * Assign the right type to the talloc pointer, so that
2731 * py_ldb_get_opaque() can recognize it.
2733 talloc_set_name_const(opaque, "char");
2735 value = opaque;
2736 } else {
2737 PyErr_SetString(PyExc_ValueError,
2738 "Unsupported type for opaque");
2739 return NULL;
2742 ret = ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, value);
2743 if (ret) {
2744 PyErr_SetLdbError(PyExc_LdbError,
2745 ret,
2746 pyldb_Ldb_AS_LDBCONTEXT(self));
2747 return NULL;
2750 Py_RETURN_NONE;
2753 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2755 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2756 int type, ret;
2757 uint64_t value;
2759 if (!PyArg_ParseTuple(args, "i", &type))
2760 return NULL;
2762 /* FIXME: More interpretation */
2764 ret = ldb_sequence_number(ldb, type, &value);
2766 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2768 return PyLong_FromLongLong(value);
2771 static PyObject *py_ldb_whoami(PyLdbObject *self, PyObject *args)
2773 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2774 struct ldb_result *res = NULL;
2775 struct ldb_extended *ext_res = NULL;
2776 size_t len = 0;
2777 int ret;
2779 ret = ldb_extended(ldb, LDB_EXTENDED_WHOAMI_OID, NULL, &res);
2780 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2782 ext_res = res->extended;
2783 if (ext_res == NULL) {
2784 PyErr_SetString(PyExc_TypeError, "Got no exop reply");
2785 return NULL;
2788 if (strcmp(ext_res->oid, LDB_EXTENDED_WHOAMI_OID) != 0) {
2789 PyErr_SetString(PyExc_TypeError, "Got wrong reply OID");
2790 return NULL;
2793 len = talloc_get_size(ext_res->data);
2794 if (len == 0) {
2795 Py_RETURN_NONE;
2798 return PyUnicode_FromStringAndSize(ext_res->data, len);
2801 static PyObject *py_ldb_disconnect(PyLdbObject *self, PyObject *args)
2803 size_t ref_count;
2804 void *parent = NULL;
2805 TALLOC_CTX *mem_ctx = NULL;
2806 struct ldb_context *ldb = NULL;
2808 if (self->ldb_ctx == NULL) {
2809 /* It is hard to see how we'd get here. */
2810 PyErr_SetLdbError(PyExc_LdbError, LDB_ERR_OPERATIONS_ERROR, NULL);
2811 return NULL;
2814 ref_count = talloc_reference_count(self->ldb_ctx);
2816 if (ref_count != 0) {
2817 PyErr_SetString(PyExc_RuntimeError,
2818 "ldb.disconnect() not possible as "
2819 "object still has C (or second "
2820 "python object) references");
2821 return NULL;
2824 parent = talloc_parent(self->ldb_ctx);
2826 if (parent != self->mem_ctx) {
2827 PyErr_SetString(PyExc_RuntimeError,
2828 "ldb.disconnect() not possible as "
2829 "object is not talloc owned by this "
2830 "python object!");
2831 return NULL;
2835 * This recapitulates py_ldb_new(), cleaning out all the
2836 * connections and state, but leaving the python object in a
2837 * workable condition.
2839 mem_ctx = talloc_new(NULL);
2840 if (mem_ctx == NULL) {
2841 return PyErr_NoMemory();
2844 ldb = ldb_init(mem_ctx, NULL);
2845 if (ldb == NULL) {
2846 talloc_free(mem_ctx);
2847 PyErr_NoMemory();
2848 return NULL;
2852 * Notice we allocate the new mem_ctx and ldb before freeing
2853 * the old one. This has two purposes: 1, the python object
2854 * will still be consistent if an exception happens, and 2, it
2855 * ensures the new ldb can't have the same memory address as
2856 * the old one, and ldb address equality is a guard we use in
2857 * Python DNs and such. Repeated calls to disconnect() *can* make
2858 * this happen, so we don't advise doing that.
2860 TALLOC_FREE(self->mem_ctx);
2862 self->mem_ctx = mem_ctx;
2863 self->ldb_ctx = ldb;
2865 Py_RETURN_NONE;
2869 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2870 .name = "TEST",
2871 .read_fn = ldb_handler_copy,
2872 .write_clear_fn = ldb_handler_copy,
2873 .write_hex_fn = ldb_handler_copy,
2876 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2877 PyObject *Py_UNUSED(ignored))
2879 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2880 int ret;
2882 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2884 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2886 Py_RETURN_NONE;
2890 static PyMethodDef py_ldb_methods[] = {
2891 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2892 "S.set_debug(callback) -> None\n"
2893 "Set callback for LDB debug messages.\n"
2894 "The callback should accept a debug level and debug text." },
2895 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2896 "S.set_create_perms(mode) -> None\n"
2897 "Set mode to use when creating new LDB files." },
2898 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2899 "S.set_modules_dir(path) -> None\n"
2900 "Set path LDB should search for modules" },
2901 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2902 "S.transaction_start() -> None\n"
2903 "Start a new transaction." },
2904 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2905 "S.transaction_prepare_commit() -> None\n"
2906 "prepare to commit a new transaction (2-stage commit)." },
2907 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2908 "S.transaction_commit() -> None\n"
2909 "commit a new transaction." },
2910 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2911 "S.transaction_cancel() -> None\n"
2912 "cancel a new transaction." },
2913 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2914 NULL },
2915 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2916 NULL },
2917 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2918 NULL },
2919 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2920 NULL },
2921 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2922 NULL },
2923 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2924 METH_VARARGS|METH_KEYWORDS,
2925 "S.connect(url, flags=0, options=None) -> None\n"
2926 "Connect to a LDB URL." },
2927 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2928 METH_VARARGS|METH_KEYWORDS,
2929 "S.modify(message, controls=None, validate=False) -> None\n"
2930 "Modify an entry." },
2931 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2932 METH_VARARGS|METH_KEYWORDS,
2933 "S.add(message, controls=None) -> None\n"
2934 "Add an entry." },
2935 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2936 METH_VARARGS|METH_KEYWORDS,
2937 "S.delete(dn, controls=None) -> None\n"
2938 "Remove an entry." },
2939 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2940 METH_VARARGS|METH_KEYWORDS,
2941 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2942 "Rename an entry." },
2943 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2944 METH_VARARGS|METH_KEYWORDS,
2945 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2946 "Search in a database.\n"
2947 "\n"
2948 ":param base: Optional base DN to search\n"
2949 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2950 ":param expression: Optional search expression\n"
2951 ":param attrs: Attributes to return (defaults to all)\n"
2952 ":param controls: Optional list of controls\n"
2953 ":return: ldb.Result object\n"
2955 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2956 py_ldb_search_iterator),
2957 METH_VARARGS|METH_KEYWORDS,
2958 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2959 "Search in a database.\n"
2960 "\n"
2961 ":param base: Optional base DN to search\n"
2962 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2963 ":param expression: Optional search expression\n"
2964 ":param attrs: Attributes to return (defaults to all)\n"
2965 ":param controls: Optional list of controls\n"
2966 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2967 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2969 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2970 NULL },
2971 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2972 NULL },
2973 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2974 NULL },
2975 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2976 "S.parse_ldif(ldif) -> iter(messages)\n"
2977 "Parse a string formatted using LDIF." },
2978 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2979 "S.write_ldif(message, changetype) -> ldif\n"
2980 "Print the message as a string formatted using LDIF." },
2981 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2982 "S.msg_diff(Message) -> Message\n"
2983 "Return an LDB Message of the difference between two Message objects." },
2984 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2985 "S.get_opaque(name) -> value\n"
2986 "Get an opaque value set on this LDB connection. \n"
2987 ":note: The returned value may not be useful in Python."
2989 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2990 "S.set_opaque(name, value) -> None\n"
2991 "Set an opaque value on this LDB connection. \n"
2992 ":note: Passing incorrect values may cause crashes." },
2993 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2994 "S.sequence_number(type) -> value\n"
2995 "Return the value of the sequence according to the requested type" },
2996 { "whoami",
2997 (PyCFunction)py_ldb_whoami,
2998 METH_NOARGS,
2999 "S.whoami() -> value\n"
3000 "Return the RFC4532 whoami string",
3002 { "disconnect",
3003 (PyCFunction)py_ldb_disconnect,
3004 METH_NOARGS,
3005 "S.disconnect() -> None\n"
3006 "Make this Ldb object unusable, disconnect and free the "
3007 "underlying LDB, releasing any file handles and sockets.",
3009 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
3010 "S._register_test_extensions() -> None\n"
3011 "Register internal extensions used in testing" },
3012 {0},
3015 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
3017 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
3018 struct ldb_dn *dn;
3019 struct ldb_result *result;
3020 unsigned int count;
3021 int ret;
3023 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
3024 return -1;
3027 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
3028 NULL);
3029 if (ret != LDB_SUCCESS) {
3030 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
3031 return -1;
3034 count = result->count;
3036 talloc_free(result);
3038 if (count > 1) {
3039 PyErr_Format(PyExc_RuntimeError,
3040 "Searching for [%s] dn gave %u results!",
3041 ldb_dn_get_linearized(dn),
3042 count);
3043 return -1;
3046 return count;
3049 static PySequenceMethods py_ldb_seq = {
3050 .sq_contains = (objobjproc)py_ldb_contains,
3053 static void py_ldb_dealloc(PyLdbObject *self)
3055 talloc_free(self->mem_ctx);
3056 Py_TYPE(self)->tp_free(self);
3059 static PyTypeObject PyLdb = {
3060 .tp_name = "ldb.Ldb",
3061 .tp_methods = py_ldb_methods,
3062 .tp_repr = (reprfunc)py_ldb_repr,
3063 .tp_new = py_ldb_new,
3064 .tp_init = (initproc)py_ldb_init,
3065 .tp_dealloc = (destructor)py_ldb_dealloc,
3066 .tp_getattro = PyObject_GenericGetAttr,
3067 .tp_basicsize = sizeof(PyLdbObject),
3068 .tp_doc = "Connection to a LDB database.",
3069 .tp_as_sequence = &py_ldb_seq,
3070 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3073 static void py_ldb_result_dealloc(PyLdbResultObject *self)
3075 talloc_free(self->mem_ctx);
3076 Py_CLEAR(self->msgs);
3077 Py_CLEAR(self->referals);
3078 Py_CLEAR(self->controls);
3079 Py_DECREF(self->pyldb);
3080 Py_TYPE(self)->tp_free(self);
3083 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
3085 Py_INCREF(self->msgs);
3086 return self->msgs;
3089 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
3091 Py_INCREF(self->controls);
3092 return self->controls;
3095 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
3097 Py_INCREF(self->referals);
3098 return self->referals;
3101 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
3103 Py_ssize_t size;
3104 if (self->msgs == NULL) {
3105 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
3106 return NULL;
3108 size = PyList_Size(self->msgs);
3109 return PyLong_FromLong(size);
3112 static PyGetSetDef py_ldb_result_getset[] = {
3114 .name = discard_const_p(char, "controls"),
3115 .get = (getter)py_ldb_result_get_controls,
3118 .name = discard_const_p(char, "msgs"),
3119 .get = (getter)py_ldb_result_get_msgs,
3122 .name = discard_const_p(char, "referals"),
3123 .get = (getter)py_ldb_result_get_referals,
3126 .name = discard_const_p(char, "count"),
3127 .get = (getter)py_ldb_result_get_count,
3129 { .name = NULL },
3132 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
3134 return PyObject_GetIter(self->msgs);
3137 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
3139 return PySequence_Size(self->msgs);
3142 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
3144 return PySequence_GetItem(self->msgs, idx);
3147 static PySequenceMethods py_ldb_result_seq = {
3148 .sq_length = (lenfunc)py_ldb_result_len,
3149 .sq_item = (ssizeargfunc)py_ldb_result_find,
3152 static PyObject *py_ldb_result_repr(PyLdbObject *self)
3154 return PyUnicode_FromString("<ldb result>");
3158 static PyTypeObject PyLdbResult = {
3159 .tp_name = "ldb.Result",
3160 .tp_repr = (reprfunc)py_ldb_result_repr,
3161 .tp_dealloc = (destructor)py_ldb_result_dealloc,
3162 .tp_iter = (getiterfunc)py_ldb_result_iter,
3163 .tp_getset = py_ldb_result_getset,
3164 .tp_getattro = PyObject_GenericGetAttr,
3165 .tp_basicsize = sizeof(PyLdbResultObject),
3166 .tp_as_sequence = &py_ldb_result_seq,
3167 .tp_doc = "LDB result.",
3168 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3171 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
3173 Py_CLEAR(self->state.exception);
3174 TALLOC_FREE(self->mem_ctx);
3175 ZERO_STRUCT(self->state);
3176 Py_CLEAR(self->ldb);
3177 Py_TYPE(self)->tp_free(self);
3180 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
3182 PyObject *py_ret = NULL;
3184 if (self->state.req == NULL) {
3185 PyErr_SetString(PyExc_RuntimeError,
3186 "ldb.SearchIterator request already finished");
3187 return NULL;
3191 * TODO: do we want a non-blocking mode?
3192 * In future we may add an optional 'nonblocking'
3193 * argument to search_iterator().
3195 * For now we keep it simple and wait for at
3196 * least one reply.
3199 while (self->state.next == NULL) {
3200 int ret;
3202 if (self->state.result != NULL) {
3204 * We (already) got a final result from the server.
3206 * We stop the iteration and let
3207 * py_ldb_search_iterator_result() will deliver
3208 * the result details.
3210 TALLOC_FREE(self->state.req);
3211 PyErr_SetNone(PyExc_StopIteration);
3212 return NULL;
3215 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
3216 if (ret != LDB_SUCCESS) {
3217 struct ldb_context *ldb_ctx;
3218 TALLOC_FREE(self->state.req);
3219 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
3221 * We stop the iteration and let
3222 * py_ldb_search_iterator_result() will deliver
3223 * the exception.
3225 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
3226 ret, ldb_errstring(ldb_ctx));
3227 PyErr_SetNone(PyExc_StopIteration);
3228 return NULL;
3232 py_ret = self->state.next->obj;
3233 self->state.next->obj = NULL;
3234 /* no TALLOC_FREE() as self->state.next is a list */
3235 talloc_free(self->state.next);
3236 return py_ret;
3239 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
3240 PyObject *Py_UNUSED(ignored))
3242 PyObject *py_ret = NULL;
3244 if (self->state.req != NULL) {
3245 PyErr_SetString(PyExc_RuntimeError,
3246 "ldb.SearchIterator request running");
3247 return NULL;
3250 if (self->state.next != NULL) {
3251 PyErr_SetString(PyExc_RuntimeError,
3252 "ldb.SearchIterator not fully consumed.");
3253 return NULL;
3256 if (self->state.exception != NULL) {
3257 PyErr_SetObject(PyExc_LdbError, self->state.exception);
3258 Py_DECREF(self->state.exception);
3259 self->state.exception = NULL;
3260 return NULL;
3263 if (self->state.result == NULL) {
3264 PyErr_SetString(PyExc_RuntimeError,
3265 "ldb.SearchIterator result already consumed");
3266 return NULL;
3269 py_ret = self->state.result->obj;
3270 self->state.result->obj = NULL;
3271 TALLOC_FREE(self->state.result);
3272 return py_ret;
3275 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
3276 PyObject *Py_UNUSED(ignored))
3278 if (self->state.req == NULL) {
3279 PyErr_SetString(PyExc_RuntimeError,
3280 "ldb.SearchIterator request already finished");
3281 return NULL;
3284 Py_CLEAR(self->state.exception);
3285 TALLOC_FREE(self->mem_ctx);
3286 ZERO_STRUCT(self->state);
3287 Py_RETURN_NONE;
3290 static PyMethodDef py_ldb_search_iterator_methods[] = {
3291 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
3292 "S.result() -> ldb.Result (without msgs and referrals)\n" },
3293 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
3294 "S.abandon()\n" },
3298 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
3300 return PyUnicode_FromString("<ldb search iterator>");
3303 static PyTypeObject PyLdbSearchIterator = {
3304 .tp_name = "ldb.SearchIterator",
3305 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
3306 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
3307 .tp_iter = PyObject_SelfIter,
3308 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
3309 .tp_methods = py_ldb_search_iterator_methods,
3310 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
3311 .tp_doc = "LDB search_iterator.",
3312 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
3316 * Create a ldb_message_element from a Python object.
3318 * This will accept any sequence objects that contains strings, or
3319 * a string object.
3321 * A reference to set_obj might be borrowed.
3323 * @param mem_ctx Memory context
3324 * @param set_obj Python object to convert
3325 * @param flags ldb_message_element flags to set, if a new element is returned
3326 * @param attr_name Name of the attribute to set, if a new element is returned
3327 * @return New ldb_message_element, allocated as child of mem_ctx
3329 static struct ldb_message_element *PyObject_AsMessageElement(
3330 TALLOC_CTX *mem_ctx,
3331 PyObject *set_obj,
3332 unsigned int flags,
3333 const char *attr_name)
3335 struct ldb_message_element *me;
3336 const char *msg = NULL;
3337 Py_ssize_t size;
3338 int result;
3340 if (pyldb_MessageElement_Check(set_obj)) {
3341 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
3342 /* We have to talloc_reference() the memory context, not the pointer
3343 * which may not actually be it's own context */
3344 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
3345 return pyldb_MessageElement_AsMessageElement(set_obj);
3347 return NULL;
3350 me = talloc(mem_ctx, struct ldb_message_element);
3351 if (me == NULL) {
3352 PyErr_NoMemory();
3353 return NULL;
3356 me->name = talloc_strdup(me, attr_name);
3357 if (me->name == NULL) {
3358 PyErr_NoMemory();
3359 talloc_free(me);
3360 return NULL;
3362 me->flags = flags;
3363 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
3364 me->num_values = 1;
3365 me->values = talloc_array(me, struct ldb_val, me->num_values);
3366 if (PyBytes_Check(set_obj)) {
3367 char *_msg = NULL;
3368 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
3369 if (result != 0) {
3370 talloc_free(me);
3371 return NULL;
3373 msg = _msg;
3374 } else {
3375 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3376 if (msg == NULL) {
3377 talloc_free(me);
3378 return NULL;
3381 me->values[0].data = talloc_memdup(me,
3382 (const uint8_t *)msg,
3383 size+1);
3384 me->values[0].length = size;
3385 } else if (PySequence_Check(set_obj)) {
3386 Py_ssize_t i;
3387 me->num_values = PySequence_Size(set_obj);
3388 me->values = talloc_array(me, struct ldb_val, me->num_values);
3389 for (i = 0; i < me->num_values; i++) {
3390 PyObject *obj = PySequence_GetItem(set_obj, i);
3391 if (PyBytes_Check(obj)) {
3392 char *_msg = NULL;
3393 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3394 if (result != 0) {
3395 talloc_free(me);
3396 return NULL;
3398 msg = _msg;
3399 } else if (PyUnicode_Check(obj)) {
3400 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3401 if (msg == NULL) {
3402 talloc_free(me);
3403 return NULL;
3405 } else {
3406 PyErr_Format(PyExc_TypeError,
3407 "Expected string as element %zd in list", i);
3408 talloc_free(me);
3409 return NULL;
3411 me->values[i].data = talloc_memdup(me,
3412 (const uint8_t *)msg,
3413 size+1);
3414 me->values[i].length = size;
3416 } else {
3417 PyErr_Format(PyExc_TypeError,
3418 "String or List type expected for '%s' attribute", attr_name);
3419 talloc_free(me);
3420 me = NULL;
3423 return me;
3427 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3428 struct ldb_message_element *me)
3430 Py_ssize_t i;
3431 PyObject *result;
3433 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3434 result = PyList_New(me->num_values);
3435 if (result == NULL) {
3436 return NULL;
3439 for (i = 0; i < me->num_values; i++) {
3440 PyObject *obj = NULL;
3441 int ret;
3443 obj = PyObject_FromLdbValue(&me->values[i]);
3444 if (obj == NULL) {
3445 Py_DECREF(result);
3446 return NULL;
3449 ret = PyList_SetItem(result, i, obj);
3450 if (ret) {
3451 Py_DECREF(obj);
3452 Py_DECREF(result);
3453 return NULL;
3457 return result;
3460 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3462 unsigned int i;
3463 if (!PyArg_ParseTuple(args, "I", &i))
3464 return NULL;
3465 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3466 Py_RETURN_NONE;
3468 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3471 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3473 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3474 return PyLong_FromLong(el->flags);
3477 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3479 unsigned int flags;
3480 struct ldb_message_element *el;
3481 if (!PyArg_ParseTuple(args, "I", &flags))
3482 return NULL;
3484 el = pyldb_MessageElement_AsMessageElement(self);
3485 el->flags = flags;
3486 Py_RETURN_NONE;
3489 static PyMethodDef py_ldb_msg_element_methods[] = {
3490 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3491 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3492 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3493 {0},
3496 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3498 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3501 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3503 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3504 if (idx < 0 || idx >= el->num_values) {
3505 PyErr_SetString(PyExc_IndexError, "Out of range");
3506 return NULL;
3508 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3511 static PySequenceMethods py_ldb_msg_element_seq = {
3512 .sq_length = (lenfunc)py_ldb_msg_element_len,
3513 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3516 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3518 int ret;
3519 if (!pyldb_MessageElement_Check(other)) {
3520 Py_INCREF(Py_NotImplemented);
3521 return Py_NotImplemented;
3523 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3524 pyldb_MessageElement_AsMessageElement(other));
3525 return richcmp(ret, op);
3528 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3530 PyObject *el = ldb_msg_element_to_set(NULL,
3531 pyldb_MessageElement_AsMessageElement(self));
3532 PyObject *ret = PyObject_GetIter(el);
3533 Py_DECREF(el);
3534 return ret;
3537 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3539 TALLOC_CTX *ret_mem_ctx = NULL;
3540 PyLdbMessageElementObject *ret;
3542 ret_mem_ctx = talloc_new(NULL);
3543 if (ret_mem_ctx == NULL) {
3544 return PyErr_NoMemory();
3547 if (talloc_reference(ret_mem_ctx, mem_ctx) == NULL) {
3548 talloc_free(ret_mem_ctx);
3549 PyErr_NoMemory();
3550 return NULL;
3553 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3554 if (ret == NULL) {
3555 talloc_free(ret_mem_ctx);
3556 PyErr_NoMemory();
3557 return NULL;
3559 ret->mem_ctx = ret_mem_ctx;
3560 ret->el = el;
3561 return (PyObject *)ret;
3564 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3566 PyObject *py_elements = NULL;
3567 struct ldb_message_element *el;
3568 unsigned int flags = 0;
3569 char *name = NULL;
3570 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3571 PyLdbMessageElementObject *ret;
3572 TALLOC_CTX *mem_ctx;
3573 const char *msg = NULL;
3574 Py_ssize_t size;
3575 int result;
3577 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3578 discard_const_p(char *, kwnames),
3579 &py_elements, &flags, &name))
3580 return NULL;
3582 mem_ctx = talloc_new(NULL);
3583 if (mem_ctx == NULL) {
3584 PyErr_NoMemory();
3585 return NULL;
3588 el = talloc_zero(mem_ctx, struct ldb_message_element);
3589 if (el == NULL) {
3590 PyErr_NoMemory();
3591 talloc_free(mem_ctx);
3592 return NULL;
3595 if (py_elements != NULL) {
3596 Py_ssize_t i;
3597 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3598 char *_msg = NULL;
3599 el->num_values = 1;
3600 el->values = talloc_array(el, struct ldb_val, 1);
3601 if (el->values == NULL) {
3602 talloc_free(mem_ctx);
3603 PyErr_NoMemory();
3604 return NULL;
3606 if (PyBytes_Check(py_elements)) {
3607 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3608 msg = _msg;
3609 } else {
3610 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3611 result = (msg == NULL) ? -1 : 0;
3613 if (result != 0) {
3614 talloc_free(mem_ctx);
3615 return NULL;
3617 el->values[0].data = talloc_memdup(el->values,
3618 (const uint8_t *)msg, size + 1);
3619 el->values[0].length = size;
3620 } else if (PySequence_Check(py_elements)) {
3621 el->num_values = PySequence_Size(py_elements);
3622 el->values = talloc_array(el, struct ldb_val, el->num_values);
3623 if (el->values == NULL) {
3624 talloc_free(mem_ctx);
3625 PyErr_NoMemory();
3626 return NULL;
3628 for (i = 0; i < el->num_values; i++) {
3629 PyObject *item = PySequence_GetItem(py_elements, i);
3630 if (item == NULL) {
3631 talloc_free(mem_ctx);
3632 return NULL;
3634 if (PyBytes_Check(item)) {
3635 char *_msg = NULL;
3636 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3637 msg = _msg;
3638 } else if (PyUnicode_Check(item)) {
3639 msg = PyUnicode_AsUTF8AndSize(item, &size);
3640 result = (msg == NULL) ? -1 : 0;
3641 } else {
3642 PyErr_Format(PyExc_TypeError,
3643 "Expected string as element %zd in list", i);
3644 result = -1;
3646 if (result != 0) {
3647 talloc_free(mem_ctx);
3648 return NULL;
3650 el->values[i].data = talloc_memdup(el,
3651 (const uint8_t *)msg, size+1);
3652 el->values[i].length = size;
3654 } else {
3655 PyErr_SetString(PyExc_TypeError,
3656 "Expected string or list");
3657 talloc_free(mem_ctx);
3658 return NULL;
3662 el->flags = flags;
3663 if (name != NULL) {
3664 el->name = talloc_strdup(el, name);
3665 if (el->name == NULL) {
3666 talloc_free(mem_ctx);
3667 return PyErr_NoMemory();
3671 ret = PyObject_New(PyLdbMessageElementObject, type);
3672 if (ret == NULL) {
3673 talloc_free(mem_ctx);
3674 return NULL;
3677 ret->mem_ctx = mem_ctx;
3678 ret->el = el;
3679 return (PyObject *)ret;
3682 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3684 char *element_str = NULL;
3685 Py_ssize_t i;
3686 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3687 PyObject *ret, *repr;
3689 for (i = 0; i < el->num_values; i++) {
3690 PyObject *o = py_ldb_msg_element_find(self, i);
3691 repr = PyObject_Repr(o);
3692 if (element_str == NULL)
3693 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3694 else
3695 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3696 Py_DECREF(repr);
3698 if (element_str == NULL) {
3699 return PyErr_NoMemory();
3703 if (element_str != NULL) {
3704 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3705 talloc_free(element_str);
3706 } else {
3707 ret = PyUnicode_FromString("MessageElement([])");
3710 return ret;
3713 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3715 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3717 if (el->num_values == 1)
3718 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3719 else
3720 Py_RETURN_NONE;
3723 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3725 talloc_free(self->mem_ctx);
3726 PyObject_Del(self);
3729 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3731 return wrap_text("MessageElementTextWrapper", self);
3734 static PyGetSetDef py_ldb_msg_element_getset[] = {
3736 .name = discard_const_p(char, "text"),
3737 .get = (getter)py_ldb_msg_element_get_text,
3739 { .name = NULL }
3742 static PyTypeObject PyLdbMessageElement = {
3743 .tp_name = "ldb.MessageElement",
3744 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3745 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3746 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3747 .tp_str = (reprfunc)py_ldb_msg_element_str,
3748 .tp_methods = py_ldb_msg_element_methods,
3749 .tp_getset = py_ldb_msg_element_getset,
3750 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3751 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3752 .tp_as_sequence = &py_ldb_msg_element_seq,
3753 .tp_new = py_ldb_msg_element_new,
3754 .tp_flags = Py_TPFLAGS_DEFAULT,
3755 .tp_doc = "An element of a Message",
3759 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3761 PyObject *py_ldb;
3762 PyObject *py_dict;
3763 PyObject *py_ret;
3764 struct ldb_message *msg;
3765 struct ldb_context *ldb_ctx;
3766 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3768 if (!PyArg_ParseTuple(args, "O!O!|I",
3769 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3770 &mod_flags)) {
3771 return NULL;
3774 /* mask only flags we are going to use */
3775 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3776 if (!mod_flags) {
3777 PyErr_SetString(PyExc_ValueError,
3778 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3779 " expected as mod_flag value");
3780 return NULL;
3783 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3785 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3786 if (!msg) {
3787 return NULL;
3790 py_ret = PyLdbMessage_FromMessage(msg, (PyLdbObject *)py_ldb);
3792 talloc_unlink(ldb_ctx, msg);
3794 return py_ret;
3798 #define pyldb_Message_as_message(pyobj) ((PyLdbMessageObject *)pyobj)->msg
3800 #define pyldb_Message_get_pyldb(pyobj) ((PyLdbMessageObject *)pyobj)->pyldb
3803 * PyErr_LDB_MESSAGE_OR_RAISE does 3 things:
3804 * 1. checks that a PyObject is really a PyLdbMessageObject.
3805 * 2. checks that the ldb that the PyLdbMessageObject knows is the ldb that
3806 * its dn knows -- but only if the underlying message has a DN.
3807 * 3. sets message to the relevant struct ldb_message *.
3809 * We need to do all this to ensure the message belongs to the right
3810 * ldb, lest it be freed before we are ready.
3812 #define PyErr_LDB_MESSAGE_OR_RAISE(_py_obj, message) do { \
3813 PyLdbMessageObject *_py_message = NULL; \
3814 struct ldb_dn *_dn = NULL; \
3815 if (_py_obj == NULL || !pyldb_Message_Check(_py_obj)) { \
3816 PyErr_SetString(PyExc_TypeError, \
3817 "ldb Message object required"); \
3818 return NULL; \
3820 _py_message = (PyLdbMessageObject *)_py_obj; \
3821 message = pyldb_Message_as_message(_py_message); \
3822 _dn = message->dn; \
3823 if (_dn != NULL && \
3824 (_py_message->pyldb->ldb_ctx != ldb_dn_get_ldb_context(_dn))) { \
3825 PyErr_SetString(PyExc_RuntimeError, \
3826 "Message has a stale LDB connection"); \
3827 return NULL; \
3829 } while(0)
3832 static PyObject *py_ldb_msg_remove_attr(PyObject *self, PyObject *args)
3834 char *name;
3835 struct ldb_message *msg = NULL;
3836 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3838 if (!PyArg_ParseTuple(args, "s", &name)) {
3839 return NULL;
3842 ldb_msg_remove_attr(msg, name);
3844 Py_RETURN_NONE;
3847 static PyObject *py_ldb_msg_keys(PyObject *self,
3848 PyObject *Py_UNUSED(ignored))
3850 struct ldb_message *msg = NULL;
3851 Py_ssize_t i, j = 0;
3852 PyObject *obj = NULL;
3854 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3856 obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3857 if (obj == NULL) {
3858 return NULL;
3861 if (msg->dn != NULL) {
3862 PyObject *py_dn = NULL;
3863 int ret;
3865 py_dn = PyUnicode_FromString("dn");
3866 if (py_dn == NULL) {
3867 Py_DECREF(obj);
3868 return NULL;
3871 ret = PyList_SetItem(obj, j, py_dn);
3872 if (ret) {
3873 Py_DECREF(py_dn);
3874 Py_DECREF(obj);
3875 return NULL;
3878 j++;
3880 for (i = 0; i < msg->num_elements; i++) {
3881 PyObject *py_name = NULL;
3882 int ret;
3884 py_name = PyUnicode_FromString(msg->elements[i].name);
3885 if (py_name == NULL) {
3886 Py_DECREF(obj);
3887 return NULL;
3890 ret = PyList_SetItem(obj, j, py_name);
3891 if (ret) {
3892 Py_DECREF(py_name);
3893 Py_DECREF(obj);
3894 return NULL;
3897 j++;
3899 return obj;
3902 static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name)
3904 struct ldb_message_element *el = NULL;
3905 const char *name = NULL;
3906 struct ldb_message *msg = pyldb_Message_as_message(self);
3907 struct ldb_dn *dn = msg->dn;
3909 if (dn != NULL && (self->pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn))) {
3910 return -1;
3913 name = PyUnicode_AsUTF8(py_name);
3914 if (name == NULL) {
3915 return -1;
3917 if (!ldb_attr_cmp(name, "dn")) {
3918 return 1;
3920 el = ldb_msg_find_element(msg, name);
3921 return el != NULL ? 1 : 0;
3924 static PyObject *py_ldb_msg_getitem(PyObject *self, PyObject *py_name)
3926 struct ldb_message_element *el = NULL;
3927 const char *name = NULL;
3928 struct ldb_message *msg = NULL;
3929 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3931 name = PyUnicode_AsUTF8(py_name);
3932 if (name == NULL) {
3933 return NULL;
3935 if (!ldb_attr_cmp(name, "dn")) {
3936 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
3938 el = ldb_msg_find_element(msg, name);
3939 if (el == NULL) {
3940 PyErr_SetString(PyExc_KeyError, "No such element");
3941 return NULL;
3944 return PyLdbMessageElement_FromMessageElement(el, msg->elements);
3947 static PyObject *py_ldb_msg_get(PyObject *self, PyObject *args, PyObject *kwargs)
3949 PyObject *def = NULL;
3950 const char *kwnames[] = { "name", "default", "idx", NULL };
3951 const char *name = NULL;
3952 int idx = -1;
3953 struct ldb_message_element *el;
3954 struct ldb_message *msg = NULL;
3955 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3957 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3958 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3959 return NULL;
3962 if (strcasecmp(name, "dn") == 0) {
3963 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
3966 el = ldb_msg_find_element(msg, name);
3968 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3969 if (def != NULL) {
3970 Py_INCREF(def);
3971 return def;
3973 Py_RETURN_NONE;
3976 if (idx == -1) {
3977 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3980 return PyObject_FromLdbValue(&el->values[idx]);
3983 static PyObject *py_ldb_msg_items(PyObject *self,
3984 PyObject *Py_UNUSED(ignored))
3986 struct ldb_message *msg = NULL;
3987 Py_ssize_t i, j = 0;
3988 PyObject *l = NULL;
3990 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
3992 l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3993 if (l == NULL) {
3994 return PyErr_NoMemory();
3996 if (msg->dn != NULL) {
3997 PyObject *value = NULL;
3998 int res = 0;
3999 PyObject *obj = pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
4000 if (obj == NULL) {
4001 Py_CLEAR(l);
4002 return NULL;
4004 value = Py_BuildValue("(sO)", "dn", obj);
4005 Py_CLEAR(obj);
4006 if (value == NULL) {
4007 Py_CLEAR(l);
4008 return NULL;
4010 res = PyList_SetItem(l, 0, value);
4011 if (res == -1) {
4012 Py_CLEAR(l);
4013 return NULL;
4015 j++;
4017 for (i = 0; i < msg->num_elements; i++, j++) {
4018 PyObject *value = NULL;
4019 int res = 0;
4020 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i],
4021 msg->elements);
4022 if (py_el == NULL) {
4023 Py_CLEAR(l);
4024 return NULL;
4026 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
4027 Py_CLEAR(py_el);
4028 if (value == NULL ) {
4029 Py_CLEAR(l);
4030 return NULL;
4032 res = PyList_SetItem(l, j, value);
4033 if (res == -1) {
4034 Py_CLEAR(l);
4035 return NULL;
4038 return l;
4041 static PyObject *py_ldb_msg_elements(PyObject *self,
4042 PyObject *Py_UNUSED(ignored))
4044 Py_ssize_t i = 0;
4045 PyObject *l = NULL;
4046 struct ldb_message *msg = NULL;
4047 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4049 l = PyList_New(msg->num_elements);
4050 if (l == NULL) {
4051 return NULL;
4053 for (i = 0; i < msg->num_elements; i++) {
4054 PyObject *msg_el = NULL;
4055 int ret;
4057 msg_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
4058 if (msg_el == NULL) {
4059 Py_DECREF(l);
4060 return NULL;
4063 ret = PyList_SetItem(l, i, msg_el);
4064 if (ret) {
4065 Py_DECREF(msg_el);
4066 Py_DECREF(l);
4067 return NULL;
4070 return l;
4073 static PyObject *py_ldb_msg_add(PyObject *self, PyObject *args)
4075 PyLdbMessageElementObject *py_element;
4076 int i, ret;
4077 struct ldb_message_element *el;
4078 struct ldb_message_element *el_new;
4079 struct ldb_message *msg = NULL;
4080 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4082 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element)) {
4083 return NULL;
4086 el = py_element->el;
4087 if (el == NULL) {
4088 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
4089 return NULL;
4091 if (el->name == NULL) {
4092 PyErr_SetString(PyExc_ValueError,
4093 "The element has no name");
4094 return NULL;
4096 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
4097 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4099 /* now deep copy all attribute values */
4100 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
4101 if (el_new->values == NULL) {
4102 PyErr_NoMemory();
4103 return NULL;
4105 el_new->num_values = el->num_values;
4107 for (i = 0; i < el->num_values; i++) {
4108 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
4109 if (el_new->values[i].data == NULL
4110 && el->values[i].length != 0) {
4111 PyErr_NoMemory();
4112 return NULL;
4116 Py_RETURN_NONE;
4119 static PyMethodDef py_ldb_msg_methods[] = {
4120 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
4121 "Message.from_dict(ldb, dict, mod_flag) -> ldb.Message\n"
4122 "Class method to create ldb.Message object from Dictionary.\n"
4123 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
4124 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
4125 "S.keys() -> list\n\n"
4126 "Return sequence of all attribute names." },
4127 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
4128 "S.remove(name)\n\n"
4129 "Remove all entries for attributes with the specified name."},
4130 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
4131 METH_VARARGS | METH_KEYWORDS,
4132 "msg.get(name,default=None,idx=None) -> string\n"
4133 "idx is the index into the values array\n"
4134 "if idx is None, then a list is returned\n"
4135 "if idx is not None, then the element with that index is returned\n"
4136 "if you pass the special name 'dn' then the DN object is returned\n"},
4137 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
4138 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
4139 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
4140 "S.add(element)\n\n"
4141 "Add an element to this message." },
4142 {0},
4145 static PyObject *py_ldb_msg_iter(PyObject *self)
4147 PyObject *list, *iter;
4149 list = py_ldb_msg_keys(self, NULL);
4150 if (list == NULL) {
4151 return NULL;
4153 iter = PyObject_GetIter(list);
4154 Py_DECREF(list);
4155 return iter;
4158 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
4160 const char *attr_name;
4162 attr_name = PyUnicode_AsUTF8(name);
4163 if (attr_name == NULL) {
4164 PyErr_SetNone(PyExc_TypeError);
4165 return -1;
4168 if (value == NULL) {
4169 /* delitem */
4170 ldb_msg_remove_attr(self->msg, attr_name);
4171 } else {
4172 int ret;
4173 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
4174 value, 0, attr_name);
4175 if (el == NULL) {
4176 return -1;
4178 if (el->name == NULL) {
4180 * If ‘value’ is a MessageElement,
4181 * PyObject_AsMessageElement() will have returned a
4182 * reference to it without setting the name. We don’t
4183 * want to modify the original object to set the name
4184 * ourselves, but making a copy would result in
4185 * different behaviour for a caller relying on a
4186 * reference being kept. Rather than continue with a
4187 * NULL name (and probably fail later on), let’s catch
4188 * this potential mistake early.
4190 PyErr_SetString(PyExc_ValueError, "MessageElement has no name set");
4191 talloc_unlink(self->msg, el);
4192 return -1;
4194 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
4195 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
4196 if (ret != LDB_SUCCESS) {
4197 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
4198 talloc_unlink(self->msg, el);
4199 return -1;
4202 return 0;
4205 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
4207 return pyldb_Message_AsMessage(self)->num_elements;
4210 static PySequenceMethods py_ldb_msg_sequence = {
4211 .sq_contains = (objobjproc)py_ldb_msg_contains,
4214 static PyMappingMethods py_ldb_msg_mapping = {
4215 .mp_length = (lenfunc)py_ldb_msg_length,
4216 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
4217 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
4220 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
4222 const char * const kwnames[] = { "dn", NULL };
4223 struct ldb_message *ret;
4224 TALLOC_CTX *mem_ctx;
4225 PyObject *pydn = NULL;
4226 PyLdbMessageObject *py_ret;
4228 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
4229 discard_const_p(char *, kwnames),
4230 &pydn))
4231 return NULL;
4233 mem_ctx = talloc_new(NULL);
4234 if (mem_ctx == NULL) {
4235 PyErr_NoMemory();
4236 return NULL;
4239 ret = ldb_msg_new(mem_ctx);
4240 if (ret == NULL) {
4241 talloc_free(mem_ctx);
4242 PyErr_NoMemory();
4243 return NULL;
4246 if (pydn != NULL) {
4247 struct ldb_dn *dn;
4248 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
4249 talloc_free(mem_ctx);
4250 return NULL;
4252 ret->dn = talloc_reference(ret, dn);
4253 if (ret->dn == NULL) {
4254 talloc_free(mem_ctx);
4255 return PyErr_NoMemory();
4259 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
4260 if (py_ret == NULL) {
4261 PyErr_NoMemory();
4262 talloc_free(mem_ctx);
4263 return NULL;
4266 py_ret->mem_ctx = mem_ctx;
4267 py_ret->msg = ret;
4268 if (pydn != NULL) {
4269 py_ret->pyldb = ((PyLdbDnObject *)pydn)->pyldb;
4270 Py_INCREF(py_ret->pyldb);
4272 return (PyObject *)py_ret;
4275 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg, PyLdbObject *pyldb)
4277 TALLOC_CTX *mem_ctx = NULL;
4278 struct ldb_message *msg_ref = NULL;
4279 PyLdbMessageObject *ret;
4281 mem_ctx = talloc_new(NULL);
4282 if (mem_ctx == NULL) {
4283 return PyErr_NoMemory();
4286 msg_ref = talloc_reference(mem_ctx, msg);
4287 if (msg_ref == NULL) {
4288 talloc_free(mem_ctx);
4289 return PyErr_NoMemory();
4292 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
4293 if (ret == NULL) {
4294 talloc_free(mem_ctx);
4295 PyErr_NoMemory();
4296 return NULL;
4298 ret->mem_ctx = mem_ctx;
4299 ret->msg = msg_ref;
4301 ret->pyldb = pyldb;
4302 Py_INCREF(ret->pyldb);
4304 return (PyObject *)ret;
4307 static PyObject *py_ldb_msg_get_dn(PyObject *self, void *closure)
4309 struct ldb_message *msg = NULL;
4310 PyErr_LDB_MESSAGE_OR_RAISE(self, msg);
4311 return pyldb_Dn_FromDn(msg->dn, pyldb_Message_get_pyldb(self));
4314 static int py_ldb_msg_set_dn(PyObject *self, PyObject *value, void *closure)
4317 * no PyErr_LDB_MESSAGE_OR_RAISE here, because this returns int.
4319 * Also, since this is trying to replace the dn, we don't need to
4320 * check the old one.
4322 struct ldb_message *msg = pyldb_Message_as_message(self);
4323 struct ldb_dn *dn = NULL;
4324 PyLdbObject *pyldb = pyldb_Message_get_pyldb(self);
4325 PyLdbMessageObject *self_as_msg = (PyLdbMessageObject *)self;
4327 if (value == NULL) {
4328 PyErr_SetString(PyExc_AttributeError, "cannot delete dn");
4329 return -1;
4331 if (!pyldb_Dn_Check(value)) {
4332 PyErr_SetString(PyExc_TypeError, "expected dn");
4333 return -1;
4336 dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
4337 if (dn == NULL) {
4338 PyErr_NoMemory();
4339 return -1;
4342 if (pyldb != NULL) {
4343 if (pyldb->ldb_ctx != ldb_dn_get_ldb_context(dn)) {
4344 PyErr_SetString(PyExc_RuntimeError,
4345 "DN is from the wrong LDB");
4346 return -1;
4348 Py_DECREF(pyldb);
4351 msg->dn = dn;
4353 self_as_msg->pyldb = ((PyLdbDnObject *)value)->pyldb;
4354 Py_INCREF(self_as_msg->pyldb);
4356 return 0;
4359 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
4361 return wrap_text("MessageTextWrapper", self);
4366 static PyObject *py_ldb_msg_get_ldb(PyLdbMessageObject *self, void *closure)
4368 if (self->pyldb == NULL) {
4369 Py_RETURN_NONE;
4371 Py_INCREF(self->pyldb);
4372 return (PyObject *)self->pyldb;
4376 static PyGetSetDef py_ldb_msg_getset[] = {
4378 .name = discard_const_p(char, "dn"),
4379 .get = (getter)py_ldb_msg_get_dn,
4380 .set = (setter)py_ldb_msg_set_dn,
4383 .name = discard_const_p(char, "text"),
4384 .get = (getter)py_ldb_msg_get_text,
4387 .name = discard_const_p(char, "ldb"),
4388 .get = (getter)py_ldb_msg_get_ldb,
4389 .doc = discard_const_p(
4390 char, "returns the associated ldb object (or None)")
4392 { .name = NULL },
4395 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
4397 PyObject *dict = PyDict_New(), *ret, *repr;
4398 const char *repr_str = NULL;
4399 if (dict == NULL) {
4400 return NULL;
4402 if (PyDict_Update(dict, (PyObject *)self) != 0) {
4403 Py_DECREF(dict);
4404 return NULL;
4406 repr = PyObject_Repr(dict);
4407 if (repr == NULL) {
4408 Py_DECREF(dict);
4409 return NULL;
4411 repr_str = PyUnicode_AsUTF8(repr);
4412 if (repr_str == NULL) {
4413 Py_DECREF(repr);
4414 Py_DECREF(dict);
4415 return NULL;
4417 ret = PyUnicode_FromFormat("Message(%s)", repr_str);
4418 Py_DECREF(repr);
4419 Py_DECREF(dict);
4420 return ret;
4423 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
4425 talloc_free(self->mem_ctx);
4426 /* The pyldb element will only be present if a DN is assigned */
4427 if (self->pyldb) {
4428 Py_DECREF(self->pyldb);
4430 PyObject_Del(self);
4433 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
4434 PyLdbMessageObject *py_msg2, int op)
4436 struct ldb_message *msg1, *msg2;
4437 unsigned int i;
4438 int ret;
4440 if (!pyldb_Message_Check(py_msg2)) {
4441 Py_INCREF(Py_NotImplemented);
4442 return Py_NotImplemented;
4445 PyErr_LDB_MESSAGE_OR_RAISE(py_msg1, msg1);
4446 PyErr_LDB_MESSAGE_OR_RAISE(py_msg2, msg2);
4448 * FIXME: this can be a non-transitive compare, unsuitable for
4449 * sorting.
4451 * supposing msg1, msg2, and msg3 have 1, 2, and 3 elements
4452 * each. msg2 has a NULL DN, while msg1 has a DN that compares
4453 * higher than msg3. Then:
4455 * msg1 < msg2, due to num_elements.
4456 * msg2 < msg3, due to num_elements.
4457 * msg1 > msg3, due to DNs.
4459 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
4460 ret = ldb_dn_compare(msg1->dn, msg2->dn);
4461 if (ret != 0) {
4462 return richcmp(ret, op);
4466 if (msg1->num_elements > msg2->num_elements) {
4467 return richcmp(1, op);
4469 if (msg1->num_elements < msg2->num_elements) {
4470 return richcmp(-1, op);
4473 for (i = 0; i < msg1->num_elements; i++) {
4474 ret = ldb_msg_element_compare_name(&msg1->elements[i],
4475 &msg2->elements[i]);
4476 if (ret != 0) {
4477 return richcmp(ret, op);
4480 ret = ldb_msg_element_compare(&msg1->elements[i],
4481 &msg2->elements[i]);
4482 if (ret != 0) {
4483 return richcmp(ret, op);
4487 return richcmp(0, op);
4490 static PyTypeObject PyLdbMessage = {
4491 .tp_name = "ldb.Message",
4492 .tp_methods = py_ldb_msg_methods,
4493 .tp_getset = py_ldb_msg_getset,
4494 .tp_as_sequence = &py_ldb_msg_sequence,
4495 .tp_as_mapping = &py_ldb_msg_mapping,
4496 .tp_basicsize = sizeof(PyLdbMessageObject),
4497 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
4498 .tp_new = py_ldb_msg_new,
4499 .tp_repr = (reprfunc)py_ldb_msg_repr,
4500 .tp_flags = Py_TPFLAGS_DEFAULT,
4501 .tp_iter = (getiterfunc)py_ldb_msg_iter,
4502 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
4503 .tp_doc = "A LDB Message",
4506 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
4508 talloc_free(self->mem_ctx);
4509 PyObject_Del(self);
4512 static PyTypeObject PyLdbTree = {
4513 .tp_name = "ldb.Tree",
4514 .tp_basicsize = sizeof(PyLdbTreeObject),
4515 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
4516 .tp_flags = Py_TPFLAGS_DEFAULT,
4517 .tp_doc = "A search tree",
4520 static PyObject *py_timestring(PyObject *module, PyObject *args)
4522 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4523 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4524 long int t_val;
4525 char *tresult;
4526 PyObject *ret;
4527 if (!PyArg_ParseTuple(args, "l", &t_val))
4528 return NULL;
4529 tresult = ldb_timestring(NULL, (time_t) t_val);
4530 if (tresult == NULL) {
4532 * Most likely EOVERFLOW from gmtime()
4534 PyErr_SetFromErrno(PyExc_OSError);
4535 return NULL;
4537 ret = PyUnicode_FromString(tresult);
4538 talloc_free(tresult);
4539 return ret;
4542 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4544 char *str;
4545 time_t t;
4546 if (!PyArg_ParseTuple(args, "s", &str)) {
4547 return NULL;
4549 t = ldb_string_to_time(str);
4551 if (t == 0 && errno != 0) {
4552 PyErr_SetFromErrno(PyExc_ValueError);
4553 return NULL;
4555 return PyLong_FromLong(t);
4558 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4560 char *name;
4561 if (!PyArg_ParseTuple(args, "s", &name))
4562 return NULL;
4563 return PyBool_FromLong(ldb_valid_attr_name(name));
4567 encode a string using RFC2254 rules
4569 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4571 char *str, *encoded;
4572 Py_ssize_t size = 0;
4573 struct ldb_val val;
4574 PyObject *ret;
4576 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4577 return NULL;
4578 val.data = (uint8_t *)str;
4579 val.length = size;
4581 encoded = ldb_binary_encode(NULL, val);
4582 if (encoded == NULL) {
4583 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4584 return NULL;
4586 ret = PyUnicode_FromString(encoded);
4587 talloc_free(encoded);
4588 return ret;
4592 decode a string using RFC2254 rules
4594 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4596 char *str;
4597 struct ldb_val val;
4598 PyObject *ret;
4600 if (!PyArg_ParseTuple(args, "s", &str))
4601 return NULL;
4603 val = ldb_binary_decode(NULL, str);
4604 if (val.data == NULL) {
4605 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4606 return NULL;
4608 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4609 talloc_free(val.data);
4610 return ret;
4613 static PyMethodDef py_ldb_global_methods[] = {
4614 { "timestring", py_timestring, METH_VARARGS,
4615 "S.timestring(int) -> string\n\n"
4616 "Generate a LDAP time string from a UNIX timestamp" },
4617 { "string_to_time", py_string_to_time, METH_VARARGS,
4618 "S.string_to_time(string) -> int\n\n"
4619 "Parse a LDAP time string into a UNIX timestamp." },
4620 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4621 "S.valid_attr_name(name) -> bool\n\n"
4622 "Check whether the supplied name is a valid attribute name." },
4623 { "binary_encode", py_binary_encode, METH_VARARGS,
4624 "S.binary_encode(string) -> string\n\n"
4625 "Perform a RFC2254 binary encoding on a string" },
4626 { "binary_decode", py_binary_decode, METH_VARARGS,
4627 "S.binary_decode(string) -> string\n\n"
4628 "Perform a RFC2254 binary decode on a string" },
4632 #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."
4634 static struct PyModuleDef moduledef = {
4635 PyModuleDef_HEAD_INIT,
4636 .m_name = "ldb",
4637 .m_doc = MODULE_DOC,
4638 .m_size = -1,
4639 .m_methods = py_ldb_global_methods,
4642 static PyObject* module_init(void)
4644 PyObject *m;
4646 PyLdbBytesType.tp_base = &PyBytes_Type;
4647 if (PyType_Ready(&PyLdbBytesType) < 0) {
4648 return NULL;
4651 if (PyType_Ready(&PyLdbDn) < 0)
4652 return NULL;
4654 if (PyType_Ready(&PyLdbMessage) < 0)
4655 return NULL;
4657 if (PyType_Ready(&PyLdbMessageElement) < 0)
4658 return NULL;
4660 if (PyType_Ready(&PyLdb) < 0)
4661 return NULL;
4663 if (PyType_Ready(&PyLdbTree) < 0)
4664 return NULL;
4666 if (PyType_Ready(&PyLdbResult) < 0)
4667 return NULL;
4669 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4670 return NULL;
4672 if (PyType_Ready(&PyLdbControl) < 0)
4673 return NULL;
4675 m = PyModule_Create(&moduledef);
4676 if (m == NULL)
4677 return NULL;
4679 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4681 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4682 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4683 ADD_LDB_INT(SEQ_NEXT);
4684 ADD_LDB_INT(SCOPE_DEFAULT);
4685 ADD_LDB_INT(SCOPE_BASE);
4686 ADD_LDB_INT(SCOPE_ONELEVEL);
4687 ADD_LDB_INT(SCOPE_SUBTREE);
4689 ADD_LDB_INT(CHANGETYPE_NONE);
4690 ADD_LDB_INT(CHANGETYPE_ADD);
4691 ADD_LDB_INT(CHANGETYPE_DELETE);
4692 ADD_LDB_INT(CHANGETYPE_MODIFY);
4693 ADD_LDB_INT(CHANGETYPE_MODRDN);
4695 ADD_LDB_INT(FLAG_MOD_ADD);
4696 ADD_LDB_INT(FLAG_MOD_REPLACE);
4697 ADD_LDB_INT(FLAG_MOD_DELETE);
4698 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4700 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4701 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4702 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4703 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4705 ADD_LDB_INT(SUCCESS);
4706 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4707 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4708 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4709 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4710 ADD_LDB_INT(ERR_COMPARE_FALSE);
4711 ADD_LDB_INT(ERR_COMPARE_TRUE);
4712 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4713 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4714 ADD_LDB_INT(ERR_REFERRAL);
4715 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4716 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4717 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4718 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4719 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4720 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4721 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4722 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4723 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4724 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4725 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4726 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4727 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4728 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4729 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4730 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4731 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4732 ADD_LDB_INT(ERR_BUSY);
4733 ADD_LDB_INT(ERR_UNAVAILABLE);
4734 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4735 ADD_LDB_INT(ERR_LOOP_DETECT);
4736 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4737 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4738 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4739 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4740 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4741 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4742 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4743 ADD_LDB_INT(ERR_OTHER);
4745 ADD_LDB_INT(FLG_RDONLY);
4746 ADD_LDB_INT(FLG_NOSYNC);
4747 ADD_LDB_INT(FLG_RECONNECT);
4748 ADD_LDB_INT(FLG_NOMMAP);
4749 ADD_LDB_INT(FLG_SHOW_BINARY);
4750 ADD_LDB_INT(FLG_ENABLE_TRACING);
4751 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4753 ADD_LDB_INT(PACKING_FORMAT);
4754 ADD_LDB_INT(PACKING_FORMAT_V2);
4756 /* Historical misspelling */
4757 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4759 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4761 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4762 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4764 Py_INCREF(&PyLdb);
4765 Py_INCREF(&PyLdbDn);
4766 Py_INCREF(&PyLdbMessage);
4767 Py_INCREF(&PyLdbMessageElement);
4768 Py_INCREF(&PyLdbTree);
4769 Py_INCREF(&PyLdbResult);
4770 Py_INCREF(&PyLdbControl);
4772 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4773 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4774 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4775 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4776 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4777 PyModule_AddObject(m, "Result", (PyObject *)&PyLdbResult);
4778 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4780 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4782 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4784 ADD_LDB_STRING(SYNTAX_DN);
4785 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4786 ADD_LDB_STRING(SYNTAX_INTEGER);
4787 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4788 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4789 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4790 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4791 ADD_LDB_STRING(OID_COMPARATOR_AND);
4792 ADD_LDB_STRING(OID_COMPARATOR_OR);
4794 return m;
4797 PyMODINIT_FUNC PyInit_ldb(void);
4798 PyMODINIT_FUNC PyInit_ldb(void)
4800 return module_init();