pyldb: Fix deleting an ldb.Message dn
[Samba.git] / lib / ldb / pyldb.c
blobe31d2d083bd1cfca02ad97fa4a4418bb429cae07
1 /*
2 Unix SMB/CIFS implementation.
4 Python interface to ldb.
6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
7 Copyright (C) 2006 Simo Sorce <idra@samba.org>
8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org>
9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer
10 Copyright (C) 2009-2011 Andrew Tridgell
11 Copyright (C) 2009-2011 Andrew Bartlett
13 ** NOTE! The following LGPL license applies to the ldb
14 ** library. This does NOT imply that all of Samba is released
15 ** under the LGPL
17 This library is free software; you can redistribute it and/or
18 modify it under the terms of the GNU Lesser General Public
19 License as published by the Free Software Foundation; either
20 version 3 of the License, or (at your option) any later version.
22 This library is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25 Lesser General Public License for more details.
27 You should have received a copy of the GNU Lesser General Public
28 License along with this library; if not, see <http://www.gnu.org/licenses/>.
31 #include <Python.h>
32 #include "ldb_private.h"
33 #include "ldb_handlers.h"
34 #include "pyldb.h"
35 #include "dlinklist.h"
37 /* discard signature of 'func' in favour of 'target_sig' */
38 #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
40 struct py_ldb_search_iterator_reply;
42 typedef struct {
43 PyObject_HEAD
44 TALLOC_CTX *mem_ctx;
45 PyLdbObject *ldb;
46 struct {
47 struct ldb_request *req;
48 struct py_ldb_search_iterator_reply *next;
49 struct py_ldb_search_iterator_reply *result;
50 PyObject *exception;
51 } state;
52 } PyLdbSearchIteratorObject;
54 struct py_ldb_search_iterator_reply {
55 struct py_ldb_search_iterator_reply *prev, *next;
56 PyLdbSearchIteratorObject *py_iter;
57 PyObject *obj;
60 void initldb(void);
61 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
62 static PyObject *PyExc_LdbError;
64 static PyTypeObject PyLdbControl;
65 static PyTypeObject PyLdbResult;
66 static PyTypeObject PyLdbSearchIterator;
67 static PyTypeObject PyLdbMessage;
68 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
69 static PyTypeObject PyLdbModule;
70 static PyTypeObject PyLdbDn;
71 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
72 static PyTypeObject PyLdb;
73 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
74 static PyTypeObject PyLdbMessageElement;
75 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
77 static PyTypeObject PyLdbTree;
78 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
79 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
80 static struct ldb_message_element *PyObject_AsMessageElement(
81 TALLOC_CTX *mem_ctx,
82 PyObject *set_obj,
83 unsigned int flags,
84 const char *attr_name);
85 static PyTypeObject PyLdbBytesType;
87 #if PY_MAJOR_VERSION >= 3
89 #define PYARG_STR_UNI "es"
91 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
93 PyObject* result = NULL;
94 PyObject* args = NULL;
95 args = Py_BuildValue("(y#)", msg, size);
96 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
97 Py_DECREF(args);
98 return result;
100 #else
101 #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
103 #define PYARG_STR_UNI "et"
105 #endif
107 static PyObject *richcmp(int cmp_val, int op)
109 int ret;
110 switch (op) {
111 case Py_LT: ret = cmp_val < 0; break;
112 case Py_LE: ret = cmp_val <= 0; break;
113 case Py_EQ: ret = cmp_val == 0; break;
114 case Py_NE: ret = cmp_val != 0; break;
115 case Py_GT: ret = cmp_val > 0; break;
116 case Py_GE: ret = cmp_val >= 0; break;
117 default:
118 Py_INCREF(Py_NotImplemented);
119 return Py_NotImplemented;
121 return PyBool_FromLong(ret);
125 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
127 if (self->data != NULL) {
128 char* control = ldb_control_to_string(self->mem_ctx, self->data);
129 if (control == NULL) {
130 PyErr_NoMemory();
131 return NULL;
133 return PyUnicode_FromString(control);
134 } else {
135 return PyUnicode_FromString("ldb control");
139 static void py_ldb_control_dealloc(PyLdbControlObject *self)
141 if (self->mem_ctx != NULL) {
142 talloc_free(self->mem_ctx);
144 self->data = NULL;
145 Py_TYPE(self)->tp_free(self);
148 /* Create a text (rather than bytes) interface for a LDB result object */
149 static PyObject *wrap_text(const char *type, PyObject *wrapped)
151 PyObject *mod, *cls, *constructor, *inst;
152 mod = PyImport_ImportModule("_ldb_text");
153 if (mod == NULL)
154 return NULL;
155 cls = PyObject_GetAttrString(mod, type);
156 Py_DECREF(mod);
157 if (cls == NULL) {
158 Py_DECREF(mod);
159 return NULL;
161 constructor = PyObject_GetAttrString(cls, "_wrap");
162 Py_DECREF(cls);
163 if (constructor == NULL) {
164 return NULL;
166 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
167 Py_DECREF(constructor);
168 return inst;
171 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
172 PyObject *Py_UNUSED(ignored))
174 return PyUnicode_FromString(self->data->oid);
177 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
178 PyObject *Py_UNUSED(ignored))
180 return PyBool_FromLong(self->data->critical);
183 static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
185 if (PyObject_IsTrue(value)) {
186 self->data->critical = true;
187 } else {
188 self->data->critical = false;
190 return 0;
193 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
195 char *data = NULL;
196 const char * const kwnames[] = { "ldb", "data", NULL };
197 struct ldb_control *parsed_controls;
198 PyLdbControlObject *ret;
199 PyObject *py_ldb;
200 TALLOC_CTX *mem_ctx;
201 struct ldb_context *ldb_ctx;
203 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
204 discard_const_p(char *, kwnames),
205 &PyLdb, &py_ldb, &data))
206 return NULL;
208 mem_ctx = talloc_new(NULL);
209 if (mem_ctx == NULL) {
210 PyErr_NoMemory();
211 return NULL;
214 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
215 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
217 if (!parsed_controls) {
218 talloc_free(mem_ctx);
219 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
220 return NULL;
223 ret = PyObject_New(PyLdbControlObject, type);
224 if (ret == NULL) {
225 PyErr_NoMemory();
226 talloc_free(mem_ctx);
227 return NULL;
230 ret->mem_ctx = mem_ctx;
232 ret->data = talloc_move(mem_ctx, &parsed_controls);
233 if (ret->data == NULL) {
234 Py_DECREF(ret);
235 PyErr_NoMemory();
236 talloc_free(mem_ctx);
237 return NULL;
240 return (PyObject *)ret;
243 static PyGetSetDef py_ldb_control_getset[] = {
245 .name = discard_const_p(char, "oid"),
246 .get = (getter)py_ldb_control_get_oid,
249 .name = discard_const_p(char, "critical"),
250 .get = (getter)py_ldb_control_get_critical,
251 .set = (setter)py_ldb_control_set_critical,
253 { .name = NULL },
256 static PyTypeObject PyLdbControl = {
257 .tp_name = "ldb.control",
258 .tp_dealloc = (destructor)py_ldb_control_dealloc,
259 .tp_getattro = PyObject_GenericGetAttr,
260 .tp_basicsize = sizeof(PyLdbControlObject),
261 .tp_getset = py_ldb_control_getset,
262 .tp_doc = "LDB control.",
263 .tp_str = (reprfunc)py_ldb_control_str,
264 .tp_new = py_ldb_control_new,
265 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
268 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
270 if (ret == LDB_ERR_PYTHON_EXCEPTION)
271 return; /* Python exception should already be set, just keep that */
273 PyErr_SetObject(error,
274 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
275 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
277 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
279 char *msg = NULL;
280 Py_ssize_t size;
281 int result = 0;
282 if (!PyBytes_Check(self)) {
283 PyErr_Format(PyExc_TypeError,"Unexpected type");
284 return NULL;
286 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
287 if (result != 0) {
288 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
289 return NULL;
291 return PyUnicode_FromStringAndSize(msg, size);
294 static PyTypeObject PyLdbBytesType = {
295 PyVarObject_HEAD_INIT(NULL, 0)
296 .tp_name = "ldb.bytes",
297 .tp_doc = "str/bytes (with custom str)",
298 .tp_str = (reprfunc)py_ldb_bytes_str,
299 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
302 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
304 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
307 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
309 return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
313 * Create a Python object from a ldb_result.
315 * @param result LDB result to convert
316 * @return Python object with converted result (a list object)
318 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
320 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
321 PyLdbControlObject *ctrl;
322 if (ctl_ctx == NULL) {
323 PyErr_NoMemory();
324 return NULL;
327 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
328 if (ctrl == NULL) {
329 talloc_free(ctl_ctx);
330 PyErr_NoMemory();
331 return NULL;
333 ctrl->mem_ctx = ctl_ctx;
334 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
335 if (ctrl->data == NULL) {
336 Py_DECREF(ctrl);
337 PyErr_NoMemory();
338 return NULL;
340 return (PyObject*) ctrl;
344 * Create a Python object from a ldb_result.
346 * @param result LDB result to convert
347 * @return Python object with converted result (a list object)
349 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
351 PyLdbResultObject *ret;
352 PyObject *list, *controls, *referals;
353 Py_ssize_t i;
355 if (result == NULL) {
356 Py_RETURN_NONE;
359 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
360 if (ret == NULL) {
361 PyErr_NoMemory();
362 return NULL;
365 list = PyList_New(result->count);
366 if (list == NULL) {
367 PyErr_NoMemory();
368 Py_DECREF(ret);
369 return NULL;
372 for (i = 0; i < result->count; i++) {
373 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
376 ret->mem_ctx = talloc_new(NULL);
377 if (ret->mem_ctx == NULL) {
378 Py_DECREF(list);
379 Py_DECREF(ret);
380 PyErr_NoMemory();
381 return NULL;
384 ret->msgs = list;
386 if (result->controls) {
387 i = 0;
388 while (result->controls[i]) {
389 i++;
391 controls = PyList_New(i);
392 if (controls == NULL) {
393 Py_DECREF(ret);
394 PyErr_NoMemory();
395 return NULL;
397 for (i=0; result->controls[i]; i++) {
398 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
399 if (ctrl == NULL) {
400 Py_DECREF(ret);
401 Py_DECREF(controls);
402 PyErr_NoMemory();
403 return NULL;
405 PyList_SetItem(controls, i, ctrl);
407 } else {
409 * No controls so we keep an empty list
411 controls = PyList_New(0);
412 if (controls == NULL) {
413 Py_DECREF(ret);
414 PyErr_NoMemory();
415 return NULL;
419 ret->controls = controls;
421 i = 0;
423 while (result->refs && result->refs[i]) {
424 i++;
427 referals = PyList_New(i);
428 if (referals == NULL) {
429 Py_DECREF(ret);
430 PyErr_NoMemory();
431 return NULL;
434 for (i = 0;result->refs && result->refs[i]; i++) {
435 PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
437 ret->referals = referals;
438 return (PyObject *)ret;
442 * Create a LDB Result from a Python object.
443 * If conversion fails, NULL will be returned and a Python exception set.
445 * Note: the result object only includes the messages at the moment; extended
446 * result, controls and referrals are ignored.
448 * @param mem_ctx Memory context in which to allocate the LDB Result
449 * @param obj Python object to convert
450 * @return a ldb_result, or NULL if the conversion failed
452 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
453 PyObject *obj)
455 struct ldb_result *res;
456 Py_ssize_t i;
458 if (obj == Py_None)
459 return NULL;
461 res = talloc_zero(mem_ctx, struct ldb_result);
462 res->count = PyList_Size(obj);
463 res->msgs = talloc_array(res, struct ldb_message *, res->count);
464 for (i = 0; i < res->count; i++) {
465 PyObject *item = PyList_GetItem(obj, i);
466 res->msgs[i] = pyldb_Message_AsMessage(item);
468 return res;
471 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self,
472 PyObject *Py_UNUSED(ignored))
474 return PyBool_FromLong(ldb_dn_validate(self->dn));
477 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
478 PyObject *Py_UNUSED(ignored))
480 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
483 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
484 PyObject *Py_UNUSED(ignored))
486 return PyBool_FromLong(ldb_dn_is_special(self->dn));
489 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self,
490 PyObject *Py_UNUSED(ignored))
492 return PyBool_FromLong(ldb_dn_is_null(self->dn));
495 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self,
496 PyObject *Py_UNUSED(ignored))
498 return PyUnicode_FromString(ldb_dn_get_casefold(self->dn));
501 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
503 return PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
506 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self,
507 PyObject *Py_UNUSED(ignored))
509 return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn));
512 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self,
513 PyObject *Py_UNUSED(ignored))
515 return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
518 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
520 const char * const kwnames[] = { "mode", NULL };
521 int mode = 1;
522 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
523 discard_const_p(char *, kwnames),
524 &mode))
525 return NULL;
526 return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
529 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
531 char *name;
532 const struct ldb_val *val;
534 if (!PyArg_ParseTuple(args, "s", &name))
535 return NULL;
536 val = ldb_dn_get_extended_component(self->dn, name);
537 if (val == NULL) {
538 Py_RETURN_NONE;
541 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
544 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
546 char *name;
547 int err;
548 uint8_t *value = NULL;
549 Py_ssize_t size = 0;
551 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
552 return NULL;
554 if (value == NULL) {
555 err = ldb_dn_set_extended_component(self->dn, name, NULL);
556 } else {
557 struct ldb_val val;
558 val.data = (uint8_t *)value;
559 val.length = size;
560 err = ldb_dn_set_extended_component(self->dn, name, &val);
563 if (err != LDB_SUCCESS) {
564 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
565 return NULL;
568 Py_RETURN_NONE;
571 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
573 PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
574 PyObject *repr, *result;
575 if (str == NULL)
576 return NULL;
577 repr = PyObject_Repr(str);
578 if (repr == NULL) {
579 Py_DECREF(str);
580 return NULL;
582 result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
583 Py_DECREF(str);
584 Py_DECREF(repr);
585 return result;
588 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
590 char *name;
592 if (!PyArg_ParseTuple(args, "s", &name))
593 return NULL;
595 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
598 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
600 int ret;
601 if (!pyldb_Dn_Check(dn2)) {
602 Py_INCREF(Py_NotImplemented);
603 return Py_NotImplemented;
605 ret = ldb_dn_compare(pyldb_Dn_AS_DN(dn1), pyldb_Dn_AS_DN(dn2));
606 return richcmp(ret, op);
609 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self,
610 PyObject *Py_UNUSED(ignored))
612 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self);
613 struct ldb_dn *parent;
614 PyLdbDnObject *py_ret;
615 TALLOC_CTX *mem_ctx = talloc_new(NULL);
617 parent = ldb_dn_get_parent(mem_ctx, dn);
618 if (parent == NULL) {
619 talloc_free(mem_ctx);
620 Py_RETURN_NONE;
623 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
624 if (py_ret == NULL) {
625 PyErr_NoMemory();
626 talloc_free(mem_ctx);
627 return NULL;
629 py_ret->mem_ctx = mem_ctx;
630 py_ret->dn = parent;
631 return (PyObject *)py_ret;
634 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
636 PyObject *py_other;
637 struct ldb_dn *dn, *other;
638 if (!PyArg_ParseTuple(args, "O", &py_other))
639 return NULL;
641 dn = pyldb_Dn_AS_DN((PyObject *)self);
643 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
644 return NULL;
646 return PyBool_FromLong(ldb_dn_add_child(dn, other));
649 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
651 PyObject *py_other;
652 struct ldb_dn *other, *dn;
653 if (!PyArg_ParseTuple(args, "O", &py_other))
654 return NULL;
656 dn = pyldb_Dn_AS_DN((PyObject *)self);
658 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
659 return NULL;
661 return PyBool_FromLong(ldb_dn_add_base(dn, other));
664 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
666 struct ldb_dn *dn;
667 int i;
668 if (!PyArg_ParseTuple(args, "i", &i))
669 return NULL;
671 dn = pyldb_Dn_AS_DN((PyObject *)self);
673 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
676 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
678 PyObject *py_base;
679 struct ldb_dn *dn, *base;
680 if (!PyArg_ParseTuple(args, "O", &py_base))
681 return NULL;
683 dn = pyldb_Dn_AS_DN((PyObject *)self);
685 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
686 return NULL;
688 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
691 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
693 struct ldb_dn *dn;
694 const char *name;
695 unsigned int num = 0;
697 if (!PyArg_ParseTuple(args, "I", &num))
698 return NULL;
700 dn = pyldb_Dn_AS_DN((PyObject *)self);
702 name = ldb_dn_get_component_name(dn, num);
703 if (name == NULL) {
704 Py_RETURN_NONE;
707 return PyUnicode_FromString(name);
710 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
712 struct ldb_dn *dn;
713 const struct ldb_val *val;
714 unsigned int num = 0;
716 if (!PyArg_ParseTuple(args, "I", &num))
717 return NULL;
719 dn = pyldb_Dn_AS_DN((PyObject *)self);
721 val = ldb_dn_get_component_val(dn, num);
722 if (val == NULL) {
723 Py_RETURN_NONE;
726 return PyStr_FromLdbValue(val);
729 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
731 unsigned int num = 0;
732 char *name = NULL, *value = NULL;
733 struct ldb_val val = { 0 };
734 int err;
735 Py_ssize_t size = 0;
737 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
738 return NULL;
740 val.data = (unsigned char*) value;
741 val.length = size;
743 err = ldb_dn_set_component(self->dn, num, name, val);
744 if (err != LDB_SUCCESS) {
745 PyErr_SetString(PyExc_TypeError, "Failed to set component");
746 return NULL;
749 Py_RETURN_NONE;
752 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self,
753 PyObject *Py_UNUSED(ignored))
755 struct ldb_dn *dn;
756 const char *name;
758 dn = pyldb_Dn_AS_DN((PyObject *)self);
760 name = ldb_dn_get_rdn_name(dn);
761 if (name == NULL) {
762 Py_RETURN_NONE;
765 return PyUnicode_FromString(name);
768 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self,
769 PyObject *Py_UNUSED(ignored))
771 struct ldb_dn *dn;
772 const struct ldb_val *val;
774 dn = pyldb_Dn_AS_DN((PyObject *)self);
776 val = ldb_dn_get_rdn_val(dn);
777 if (val == NULL) {
778 Py_RETURN_NONE;
781 return PyStr_FromLdbValue(val);
784 static PyMethodDef py_ldb_dn_methods[] = {
785 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
786 "S.validate() -> bool\n"
787 "Validate DN is correct." },
788 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
789 "S.is_valid() -> bool\n" },
790 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
791 "S.is_special() -> bool\n"
792 "Check whether this is a special LDB DN." },
793 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
794 "Check whether this is a null DN." },
795 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
796 NULL },
797 { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
798 py_ldb_dn_get_linearized),
799 METH_NOARGS,
800 NULL },
801 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
802 "S.canonical_str() -> string\n"
803 "Canonical version of this DN (like a posix path)." },
804 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
805 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
806 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
807 "S.canonical_ex_str() -> string\n"
808 "Canonical version of this DN (like a posix path, with terminating newline)." },
809 { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
810 py_ldb_dn_extended_str),
811 METH_VARARGS | METH_KEYWORDS,
812 "S.extended_str(mode=1) -> string\n"
813 "Extended version of this DN" },
814 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
815 "S.parent() -> dn\n"
816 "Get the parent for this DN." },
817 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
818 "S.add_child(dn) -> None\n"
819 "Add a child DN to this DN." },
820 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
821 "S.add_base(dn) -> None\n"
822 "Add a base DN to this DN." },
823 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
824 "S.remove_base_components(int) -> bool\n"
825 "Remove a number of DN components from the base of this DN." },
826 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
827 "S.check_special(name) -> bool\n\n"
828 "Check if name is a special DN name"},
829 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
830 "S.get_extended_component(name) -> string\n\n"
831 "returns a DN extended component as a binary string"},
832 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
833 "S.set_extended_component(name, value) -> None\n\n"
834 "set a DN extended component as a binary string"},
835 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
836 "S.get_component_name(num) -> string\n"
837 "get the attribute name of the specified component" },
838 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
839 "S.get_component_value(num) -> string\n"
840 "get the attribute value of the specified component as a binary string" },
841 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
842 "S.set_component(num, name, value) -> None\n"
843 "set the attribute name and value of the specified component" },
844 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
845 "S.get_rdn_name() -> string\n"
846 "get the RDN attribute name" },
847 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
848 "S.get_rdn_value() -> string\n"
849 "get the RDN attribute value as a binary string" },
853 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
855 return ldb_dn_get_comp_num(pyldb_Dn_AS_DN((PyObject *)self));
859 copy a DN as a python object
861 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
863 PyLdbDnObject *py_ret;
865 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
866 if (py_ret == NULL) {
867 PyErr_NoMemory();
868 return NULL;
870 py_ret->mem_ctx = talloc_new(NULL);
871 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
872 return (PyObject *)py_ret;
875 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
877 struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self),
878 *other;
879 PyLdbDnObject *py_ret;
881 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
882 return NULL;
884 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
885 if (py_ret == NULL) {
886 PyErr_NoMemory();
887 return NULL;
889 py_ret->mem_ctx = talloc_new(NULL);
890 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
891 ldb_dn_add_base(py_ret->dn, other);
892 return (PyObject *)py_ret;
895 static PySequenceMethods py_ldb_dn_seq = {
896 .sq_length = (lenfunc)py_ldb_dn_len,
897 .sq_concat = (binaryfunc)py_ldb_dn_concat,
900 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
902 struct ldb_dn *ret = NULL;
903 char *str = NULL;
904 PyObject *py_ldb = NULL;
905 struct ldb_context *ldb_ctx = NULL;
906 TALLOC_CTX *mem_ctx = NULL;
907 PyLdbDnObject *py_ret = NULL;
908 const char * const kwnames[] = { "ldb", "dn", NULL };
910 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
911 discard_const_p(char *, kwnames),
912 &py_ldb, "utf8", &str))
913 goto out;
915 if (!PyLdb_Check(py_ldb)) {
916 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
917 goto out;
919 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
921 mem_ctx = talloc_new(NULL);
922 if (mem_ctx == NULL) {
923 PyErr_NoMemory();
924 goto out;
927 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
928 if (!ldb_dn_validate(ret)) {
929 talloc_free(mem_ctx);
930 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
931 goto out;
934 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
935 if (py_ret == NULL) {
936 talloc_free(mem_ctx);
937 PyErr_NoMemory();
938 goto out;
940 py_ret->mem_ctx = mem_ctx;
941 py_ret->dn = ret;
942 out:
943 if (str != NULL) {
944 PyMem_Free(discard_const_p(char, str));
946 return (PyObject *)py_ret;
949 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
951 talloc_free(self->mem_ctx);
952 PyObject_Del(self);
955 static PyTypeObject PyLdbDn = {
956 .tp_name = "ldb.Dn",
957 .tp_methods = py_ldb_dn_methods,
958 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
959 .tp_repr = (reprfunc)py_ldb_dn_repr,
960 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
961 .tp_as_sequence = &py_ldb_dn_seq,
962 .tp_doc = "A LDB distinguished name.",
963 .tp_new = py_ldb_dn_new,
964 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
965 .tp_basicsize = sizeof(PyLdbDnObject),
966 .tp_flags = Py_TPFLAGS_DEFAULT,
969 /* Debug */
970 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
971 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
973 PyObject *fn = (PyObject *)context;
974 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
977 static PyObject *py_ldb_debug_func;
979 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
981 PyObject *cb;
982 struct ldb_context *ldb_ctx;
984 if (!PyArg_ParseTuple(args, "O", &cb))
985 return NULL;
987 if (py_ldb_debug_func != NULL) {
988 Py_DECREF(py_ldb_debug_func);
991 Py_INCREF(cb);
992 /* FIXME: DECREF cb when exiting program */
993 py_ldb_debug_func = cb;
994 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
995 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
996 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
997 ldb_ctx);
999 Py_RETURN_NONE;
1002 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1004 unsigned int perms;
1005 if (!PyArg_ParseTuple(args, "I", &perms))
1006 return NULL;
1008 ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
1010 Py_RETURN_NONE;
1013 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1015 char *modules_dir;
1016 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1017 return NULL;
1019 ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
1021 Py_RETURN_NONE;
1024 static PyObject *py_ldb_transaction_start(PyLdbObject *self,
1025 PyObject *Py_UNUSED(ignored))
1027 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1028 int ldb_err;
1029 ldb_err = ldb_transaction_start(ldb_ctx);
1030 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1031 Py_RETURN_NONE;
1034 static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
1035 PyObject *Py_UNUSED(ignored))
1037 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1038 int ldb_err;
1039 ldb_err = ldb_transaction_commit(ldb_ctx);
1040 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1041 Py_RETURN_NONE;
1044 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
1045 PyObject *Py_UNUSED(ignored))
1047 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1048 int ldb_err;
1049 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1050 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1051 Py_RETURN_NONE;
1054 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
1055 PyObject *Py_UNUSED(ignored))
1057 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1058 int ldb_err;
1059 ldb_err = ldb_transaction_cancel(ldb_ctx);
1060 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1061 Py_RETURN_NONE;
1064 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
1065 PyObject *Py_UNUSED(ignored))
1067 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1068 int ldb_err;
1069 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1070 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1071 Py_RETURN_NONE;
1074 static PyObject *py_ldb_repr(PyLdbObject *self)
1076 return PyUnicode_FromString("<ldb connection>");
1079 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
1080 PyObject *Py_UNUSED(ignored))
1082 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1083 if (dn == NULL)
1084 Py_RETURN_NONE;
1085 return py_ldb_dn_copy(dn);
1089 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
1090 PyObject *Py_UNUSED(ignored))
1092 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1093 if (dn == NULL)
1094 Py_RETURN_NONE;
1095 return py_ldb_dn_copy(dn);
1098 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
1099 PyObject *Py_UNUSED(ignored))
1101 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1102 if (dn == NULL)
1103 Py_RETURN_NONE;
1104 return py_ldb_dn_copy(dn);
1107 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
1108 PyObject *Py_UNUSED(ignored))
1110 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
1111 if (dn == NULL)
1112 Py_RETURN_NONE;
1113 return py_ldb_dn_copy(dn);
1116 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1117 const char *paramname)
1119 const char **ret;
1120 Py_ssize_t i;
1121 if (!PyList_Check(list)) {
1122 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1123 return NULL;
1125 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1126 if (ret == NULL) {
1127 PyErr_NoMemory();
1128 return NULL;
1131 for (i = 0; i < PyList_Size(list); i++) {
1132 const char *str = NULL;
1133 Py_ssize_t size;
1134 PyObject *item = PyList_GetItem(list, i);
1135 if (!PyUnicode_Check(item)) {
1136 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1137 talloc_free(ret);
1138 return NULL;
1140 str = PyUnicode_AsUTF8AndSize(item, &size);
1141 if (str == NULL) {
1142 talloc_free(ret);
1143 return NULL;
1145 ret[i] = talloc_strndup(ret, str, size);
1147 ret[i] = NULL;
1148 return ret;
1151 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1153 const char * const kwnames[] = { "url", "flags", "options", NULL };
1154 char *url = NULL;
1155 PyObject *py_options = Py_None;
1156 const char **options;
1157 unsigned int flags = 0;
1158 int ret;
1159 struct ldb_context *ldb;
1161 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1162 discard_const_p(char *, kwnames),
1163 &url, &flags, &py_options))
1164 return -1;
1166 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1168 if (py_options == Py_None) {
1169 options = NULL;
1170 } else {
1171 options = PyList_AsStrList(ldb, py_options, "options");
1172 if (options == NULL)
1173 return -1;
1176 if (url != NULL) {
1177 ret = ldb_connect(ldb, url, flags, options);
1178 if (ret != LDB_SUCCESS) {
1179 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1180 return -1;
1182 } else {
1183 ldb_set_flags(ldb, flags);
1186 talloc_free(options);
1187 return 0;
1190 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1192 PyLdbObject *ret;
1193 struct ldb_context *ldb;
1194 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1195 if (ret == NULL) {
1196 PyErr_NoMemory();
1197 return NULL;
1199 ret->mem_ctx = talloc_new(NULL);
1200 ldb = ldb_init(ret->mem_ctx, NULL);
1202 if (ldb == NULL) {
1203 PyErr_NoMemory();
1204 return NULL;
1207 ret->ldb_ctx = ldb;
1208 return (PyObject *)ret;
1211 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1213 char *url = NULL;
1214 unsigned int flags = 0;
1215 PyObject *py_options = Py_None;
1216 int ret;
1217 const char **options;
1218 const char * const kwnames[] = { "url", "flags", "options", NULL };
1219 struct ldb_context *ldb_ctx;
1221 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1222 discard_const_p(char *, kwnames),
1223 &url, &flags, &py_options))
1224 return NULL;
1226 if (py_options == Py_None) {
1227 options = NULL;
1228 } else {
1229 options = PyList_AsStrList(NULL, py_options, "options");
1230 if (options == NULL)
1231 return NULL;
1234 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1235 ret = ldb_connect(ldb_ctx, url, flags, options);
1236 talloc_free(options);
1238 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1240 Py_RETURN_NONE;
1243 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1245 PyObject *py_msg;
1246 PyObject *py_controls = Py_None;
1247 struct ldb_context *ldb_ctx;
1248 struct ldb_request *req;
1249 struct ldb_control **parsed_controls;
1250 struct ldb_message *msg;
1251 int ret;
1252 TALLOC_CTX *mem_ctx;
1253 bool validate=true;
1254 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1256 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1257 discard_const_p(char *, kwnames),
1258 &py_msg, &py_controls, &validate))
1259 return NULL;
1261 mem_ctx = talloc_new(NULL);
1262 if (mem_ctx == NULL) {
1263 PyErr_NoMemory();
1264 return NULL;
1266 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1268 if (py_controls == Py_None) {
1269 parsed_controls = NULL;
1270 } else {
1271 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1272 if (controls == NULL) {
1273 talloc_free(mem_ctx);
1274 return NULL;
1276 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1277 talloc_free(controls);
1280 if (!PyLdbMessage_Check(py_msg)) {
1281 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1282 talloc_free(mem_ctx);
1283 return NULL;
1285 msg = pyldb_Message_AsMessage(py_msg);
1287 if (validate) {
1288 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1289 if (ret != LDB_SUCCESS) {
1290 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1291 talloc_free(mem_ctx);
1292 return NULL;
1296 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1297 NULL, ldb_op_default_callback, NULL);
1298 if (ret != LDB_SUCCESS) {
1299 PyErr_SetString(PyExc_TypeError, "failed to build request");
1300 talloc_free(mem_ctx);
1301 return NULL;
1304 /* do request and autostart a transaction */
1305 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1307 ret = ldb_transaction_start(ldb_ctx);
1308 if (ret != LDB_SUCCESS) {
1309 talloc_free(mem_ctx);
1310 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1311 return NULL;
1314 ret = ldb_request(ldb_ctx, req);
1315 if (ret == LDB_SUCCESS) {
1316 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1319 if (ret == LDB_SUCCESS) {
1320 ret = ldb_transaction_commit(ldb_ctx);
1321 } else {
1322 ldb_transaction_cancel(ldb_ctx);
1325 talloc_free(mem_ctx);
1326 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1328 Py_RETURN_NONE;
1333 * Obtain a ldb message from a Python Dictionary object.
1335 * @param mem_ctx Memory context
1336 * @param py_obj Python Dictionary object
1337 * @param ldb_ctx LDB context
1338 * @param mod_flags Flags to be set on every message element
1339 * @return ldb_message on success or NULL on failure
1341 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1342 PyObject *py_obj,
1343 struct ldb_context *ldb_ctx,
1344 unsigned int mod_flags)
1346 struct ldb_message *msg;
1347 unsigned int msg_pos = 0;
1348 Py_ssize_t dict_pos = 0;
1349 PyObject *key, *value;
1350 struct ldb_message_element *msg_el;
1351 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1353 msg = ldb_msg_new(mem_ctx);
1354 if (msg == NULL) {
1355 PyErr_NoMemory();
1356 return NULL;
1358 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1360 if (dn_value) {
1361 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1362 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1363 return NULL;
1365 if (msg->dn == NULL) {
1366 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1367 return NULL;
1369 } else {
1370 PyErr_SetString(PyExc_TypeError, "no dn set");
1371 return NULL;
1374 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1375 const char *key_str = PyUnicode_AsUTF8(key);
1376 if (ldb_attr_cmp(key_str, "dn") != 0) {
1377 msg_el = PyObject_AsMessageElement(msg->elements, value,
1378 mod_flags, key_str);
1379 if (msg_el == NULL) {
1380 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1381 return NULL;
1383 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1384 msg_pos++;
1388 msg->num_elements = msg_pos;
1390 return msg;
1393 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1395 PyObject *py_obj;
1396 int ret;
1397 struct ldb_context *ldb_ctx;
1398 struct ldb_request *req;
1399 struct ldb_message *msg = NULL;
1400 PyObject *py_controls = Py_None;
1401 TALLOC_CTX *mem_ctx;
1402 struct ldb_control **parsed_controls;
1403 const char * const kwnames[] = { "message", "controls", NULL };
1405 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1406 discard_const_p(char *, kwnames),
1407 &py_obj, &py_controls))
1408 return NULL;
1410 mem_ctx = talloc_new(NULL);
1411 if (mem_ctx == NULL) {
1412 PyErr_NoMemory();
1413 return NULL;
1415 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1417 if (py_controls == Py_None) {
1418 parsed_controls = NULL;
1419 } else {
1420 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1421 if (controls == NULL) {
1422 talloc_free(mem_ctx);
1423 return NULL;
1425 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1426 talloc_free(controls);
1429 if (PyLdbMessage_Check(py_obj)) {
1430 msg = pyldb_Message_AsMessage(py_obj);
1431 } else if (PyDict_Check(py_obj)) {
1432 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1433 } else {
1434 PyErr_SetString(PyExc_TypeError,
1435 "Dictionary or LdbMessage object expected!");
1438 if (!msg) {
1439 /* we should have a PyErr already set */
1440 talloc_free(mem_ctx);
1441 return NULL;
1444 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1445 if (ret != LDB_SUCCESS) {
1446 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1447 talloc_free(mem_ctx);
1448 return NULL;
1451 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1452 NULL, ldb_op_default_callback, NULL);
1453 if (ret != LDB_SUCCESS) {
1454 PyErr_SetString(PyExc_TypeError, "failed to build request");
1455 talloc_free(mem_ctx);
1456 return NULL;
1459 /* do request and autostart a transaction */
1460 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1462 ret = ldb_transaction_start(ldb_ctx);
1463 if (ret != LDB_SUCCESS) {
1464 talloc_free(mem_ctx);
1465 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1466 return NULL;
1469 ret = ldb_request(ldb_ctx, req);
1470 if (ret == LDB_SUCCESS) {
1471 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1474 if (ret == LDB_SUCCESS) {
1475 ret = ldb_transaction_commit(ldb_ctx);
1476 } else {
1477 ldb_transaction_cancel(ldb_ctx);
1480 talloc_free(mem_ctx);
1481 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1483 Py_RETURN_NONE;
1486 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1488 PyObject *py_dn;
1489 struct ldb_dn *dn;
1490 int ret;
1491 struct ldb_context *ldb_ctx;
1492 struct ldb_request *req;
1493 PyObject *py_controls = Py_None;
1494 TALLOC_CTX *mem_ctx;
1495 struct ldb_control **parsed_controls;
1496 const char * const kwnames[] = { "dn", "controls", NULL };
1498 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1499 discard_const_p(char *, kwnames),
1500 &py_dn, &py_controls))
1501 return NULL;
1503 mem_ctx = talloc_new(NULL);
1504 if (mem_ctx == NULL) {
1505 PyErr_NoMemory();
1506 return NULL;
1508 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1510 if (py_controls == Py_None) {
1511 parsed_controls = NULL;
1512 } else {
1513 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1514 if (controls == NULL) {
1515 talloc_free(mem_ctx);
1516 return NULL;
1518 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1519 talloc_free(controls);
1522 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1523 talloc_free(mem_ctx);
1524 return NULL;
1527 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1528 NULL, ldb_op_default_callback, NULL);
1529 if (ret != LDB_SUCCESS) {
1530 PyErr_SetString(PyExc_TypeError, "failed to build request");
1531 talloc_free(mem_ctx);
1532 return NULL;
1535 /* do request and autostart a transaction */
1536 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1538 ret = ldb_transaction_start(ldb_ctx);
1539 if (ret != LDB_SUCCESS) {
1540 talloc_free(mem_ctx);
1541 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1542 return NULL;
1545 ret = ldb_request(ldb_ctx, req);
1546 if (ret == LDB_SUCCESS) {
1547 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1550 if (ret == LDB_SUCCESS) {
1551 ret = ldb_transaction_commit(ldb_ctx);
1552 } else {
1553 ldb_transaction_cancel(ldb_ctx);
1556 talloc_free(mem_ctx);
1557 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1559 Py_RETURN_NONE;
1562 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1564 PyObject *py_dn1, *py_dn2;
1565 struct ldb_dn *dn1, *dn2;
1566 int ret;
1567 TALLOC_CTX *mem_ctx;
1568 PyObject *py_controls = Py_None;
1569 struct ldb_control **parsed_controls;
1570 struct ldb_context *ldb_ctx;
1571 struct ldb_request *req;
1572 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1574 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1576 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1577 discard_const_p(char *, kwnames),
1578 &py_dn1, &py_dn2, &py_controls))
1579 return NULL;
1582 mem_ctx = talloc_new(NULL);
1583 if (mem_ctx == NULL) {
1584 PyErr_NoMemory();
1585 return NULL;
1588 if (py_controls == Py_None) {
1589 parsed_controls = NULL;
1590 } else {
1591 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1592 if (controls == NULL) {
1593 talloc_free(mem_ctx);
1594 return NULL;
1596 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1597 talloc_free(controls);
1601 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1602 talloc_free(mem_ctx);
1603 return NULL;
1606 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1607 talloc_free(mem_ctx);
1608 return NULL;
1611 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1612 NULL, ldb_op_default_callback, NULL);
1613 if (ret != LDB_SUCCESS) {
1614 PyErr_SetString(PyExc_TypeError, "failed to build request");
1615 talloc_free(mem_ctx);
1616 return NULL;
1619 /* do request and autostart a transaction */
1620 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1622 ret = ldb_transaction_start(ldb_ctx);
1623 if (ret != LDB_SUCCESS) {
1624 talloc_free(mem_ctx);
1625 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1626 return NULL;
1629 ret = ldb_request(ldb_ctx, req);
1630 if (ret == LDB_SUCCESS) {
1631 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1634 if (ret == LDB_SUCCESS) {
1635 ret = ldb_transaction_commit(ldb_ctx);
1636 } else {
1637 ldb_transaction_cancel(ldb_ctx);
1640 talloc_free(mem_ctx);
1641 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1643 Py_RETURN_NONE;
1646 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1648 char *name;
1649 if (!PyArg_ParseTuple(args, "s", &name))
1650 return NULL;
1652 ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
1654 Py_RETURN_NONE;
1657 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1659 char *attribute, *syntax;
1660 unsigned int flags;
1661 int ret;
1662 struct ldb_context *ldb_ctx;
1664 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1665 return NULL;
1667 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1668 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1670 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1672 Py_RETURN_NONE;
1675 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1677 if (ldif == NULL) {
1678 Py_RETURN_NONE;
1679 } else {
1680 /* We don't want this attached to the 'ldb' any more */
1681 PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
1682 PyObject *result =
1683 Py_BuildValue(discard_const_p(char, "(iO)"),
1684 ldif->changetype,
1685 obj);
1686 Py_CLEAR(obj);
1687 return result;
1692 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1694 int changetype;
1695 PyObject *py_msg;
1696 struct ldb_ldif ldif;
1697 PyObject *ret;
1698 char *string;
1699 TALLOC_CTX *mem_ctx;
1701 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1702 return NULL;
1704 if (!PyLdbMessage_Check(py_msg)) {
1705 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1706 return NULL;
1709 ldif.msg = pyldb_Message_AsMessage(py_msg);
1710 ldif.changetype = changetype;
1712 mem_ctx = talloc_new(NULL);
1714 string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
1715 if (!string) {
1716 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1717 return NULL;
1720 ret = PyUnicode_FromString(string);
1722 talloc_free(mem_ctx);
1724 return ret;
1727 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1729 PyObject *list, *ret;
1730 struct ldb_ldif *ldif;
1731 const char *s;
1732 struct ldb_dn *last_dn = NULL;
1734 TALLOC_CTX *mem_ctx;
1736 if (!PyArg_ParseTuple(args, "s", &s))
1737 return NULL;
1739 mem_ctx = talloc_new(NULL);
1740 if (!mem_ctx) {
1741 Py_RETURN_NONE;
1744 list = PyList_New(0);
1745 while (s && *s != '\0') {
1746 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1747 talloc_steal(mem_ctx, ldif);
1748 if (ldif) {
1749 int res = 0;
1750 PyObject *py_ldif = ldb_ldif_to_pyobject(ldif);
1751 if (py_ldif == NULL) {
1752 Py_CLEAR(list);
1753 PyErr_BadArgument();
1754 talloc_free(mem_ctx);
1755 return NULL;
1757 res = PyList_Append(list, py_ldif);
1758 Py_CLEAR(py_ldif);
1759 if (res == -1) {
1760 Py_CLEAR(list);
1761 talloc_free(mem_ctx);
1762 return NULL;
1764 last_dn = ldif->msg->dn;
1765 } else {
1766 const char *last_dn_str = NULL;
1767 const char *err_string = NULL;
1768 if (last_dn == NULL) {
1769 PyErr_SetString(PyExc_ValueError,
1770 "unable to parse LDIF "
1771 "string at first chunk");
1772 Py_CLEAR(list);
1773 talloc_free(mem_ctx);
1774 return NULL;
1777 last_dn_str
1778 = ldb_dn_get_linearized(last_dn);
1780 err_string
1781 = talloc_asprintf(mem_ctx,
1782 "unable to parse ldif "
1783 "string AFTER %s",
1784 last_dn_str);
1786 PyErr_SetString(PyExc_ValueError,
1787 err_string);
1788 talloc_free(mem_ctx);
1789 Py_CLEAR(list);
1790 return NULL;
1793 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1794 ret = PyObject_GetIter(list);
1795 Py_DECREF(list);
1796 return ret;
1799 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1801 int ldb_ret;
1802 PyObject *py_msg_old;
1803 PyObject *py_msg_new;
1804 struct ldb_message *diff;
1805 struct ldb_context *ldb;
1806 PyObject *py_ret;
1807 TALLOC_CTX *mem_ctx = NULL;
1809 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1810 return NULL;
1812 if (!PyLdbMessage_Check(py_msg_old)) {
1813 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1814 return NULL;
1817 if (!PyLdbMessage_Check(py_msg_new)) {
1818 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1819 return NULL;
1822 mem_ctx = talloc_new(NULL);
1823 if (mem_ctx == NULL) {
1824 PyErr_NoMemory();
1825 return NULL;
1828 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1829 ldb_ret = ldb_msg_difference(ldb, mem_ctx,
1830 pyldb_Message_AsMessage(py_msg_old),
1831 pyldb_Message_AsMessage(py_msg_new),
1832 &diff);
1833 if (ldb_ret != LDB_SUCCESS) {
1834 talloc_free(mem_ctx);
1835 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1836 return NULL;
1839 diff = ldb_msg_copy(mem_ctx, diff);
1840 if (diff == NULL) {
1841 PyErr_NoMemory();
1842 return NULL;
1845 py_ret = PyLdbMessage_FromMessage(diff);
1847 talloc_free(mem_ctx);
1849 return py_ret;
1852 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1854 const struct ldb_schema_attribute *a;
1855 struct ldb_val old_val;
1856 struct ldb_val new_val;
1857 TALLOC_CTX *mem_ctx;
1858 PyObject *ret;
1859 char *element_name;
1860 PyObject *val;
1861 Py_ssize_t size;
1862 int result;
1864 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1865 return NULL;
1867 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1868 old_val.length = size;
1870 if (result != 0) {
1871 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1872 return NULL;
1875 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
1877 if (a == NULL) {
1878 Py_RETURN_NONE;
1881 mem_ctx = talloc_new(NULL);
1882 if (mem_ctx == NULL) {
1883 PyErr_NoMemory();
1884 return NULL;
1887 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
1888 talloc_free(mem_ctx);
1889 Py_RETURN_NONE;
1892 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1894 talloc_free(mem_ctx);
1896 return ret;
1899 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1901 PyObject *py_base = Py_None;
1902 int scope = LDB_SCOPE_DEFAULT;
1903 char *expr = NULL;
1904 PyObject *py_attrs = Py_None;
1905 PyObject *py_controls = Py_None;
1906 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1907 int ret;
1908 struct ldb_result *res;
1909 struct ldb_request *req;
1910 const char **attrs;
1911 struct ldb_context *ldb_ctx;
1912 struct ldb_control **parsed_controls;
1913 struct ldb_dn *base;
1914 PyObject *py_ret;
1915 TALLOC_CTX *mem_ctx;
1917 /* type "int" rather than "enum" for "scope" is intentional */
1918 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1919 discard_const_p(char *, kwnames),
1920 &py_base, &scope, &expr, &py_attrs, &py_controls))
1921 return NULL;
1924 mem_ctx = talloc_new(NULL);
1925 if (mem_ctx == NULL) {
1926 PyErr_NoMemory();
1927 return NULL;
1929 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1931 if (py_attrs == Py_None) {
1932 attrs = NULL;
1933 } else {
1934 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1935 if (attrs == NULL) {
1936 talloc_free(mem_ctx);
1937 return NULL;
1941 if (py_base == Py_None) {
1942 base = ldb_get_default_basedn(ldb_ctx);
1943 } else {
1944 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1945 talloc_free(mem_ctx);
1946 return NULL;
1950 if (py_controls == Py_None) {
1951 parsed_controls = NULL;
1952 } else {
1953 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1954 if (controls == NULL) {
1955 talloc_free(mem_ctx);
1956 return NULL;
1958 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1959 talloc_free(controls);
1962 res = talloc_zero(mem_ctx, struct ldb_result);
1963 if (res == NULL) {
1964 PyErr_NoMemory();
1965 talloc_free(mem_ctx);
1966 return NULL;
1969 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1970 base,
1971 scope,
1972 expr,
1973 attrs,
1974 parsed_controls,
1975 res,
1976 ldb_search_default_callback,
1977 NULL);
1979 if (ret != LDB_SUCCESS) {
1980 talloc_free(mem_ctx);
1981 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1982 return NULL;
1985 talloc_steal(req, attrs);
1987 ret = ldb_request(ldb_ctx, req);
1989 if (ret == LDB_SUCCESS) {
1990 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1993 if (ret != LDB_SUCCESS) {
1994 talloc_free(mem_ctx);
1995 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1996 return NULL;
1999 py_ret = PyLdbResult_FromResult(res);
2001 talloc_free(mem_ctx);
2003 return py_ret;
2006 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
2008 if (reply->py_iter != NULL) {
2009 DLIST_REMOVE(reply->py_iter->state.next, reply);
2010 if (reply->py_iter->state.result == reply) {
2011 reply->py_iter->state.result = NULL;
2013 reply->py_iter = NULL;
2016 if (reply->obj != NULL) {
2017 Py_DECREF(reply->obj);
2018 reply->obj = NULL;
2021 return 0;
2024 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2025 struct ldb_reply *ares)
2027 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2028 struct ldb_result result = { .msgs = NULL };
2029 struct py_ldb_search_iterator_reply *reply = NULL;
2031 if (ares == NULL) {
2032 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2035 if (ares->error != LDB_SUCCESS) {
2036 int ret = ares->error;
2037 TALLOC_FREE(ares);
2038 return ldb_request_done(req, ret);
2041 reply = talloc_zero(py_iter->mem_ctx,
2042 struct py_ldb_search_iterator_reply);
2043 if (reply == NULL) {
2044 TALLOC_FREE(ares);
2045 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2047 reply->py_iter = py_iter;
2048 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2050 switch (ares->type) {
2051 case LDB_REPLY_ENTRY:
2052 reply->obj = PyLdbMessage_FromMessage(ares->message);
2053 if (reply->obj == NULL) {
2054 TALLOC_FREE(ares);
2055 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2057 DLIST_ADD_END(py_iter->state.next, reply);
2058 TALLOC_FREE(ares);
2059 return LDB_SUCCESS;
2061 case LDB_REPLY_REFERRAL:
2062 reply->obj = PyUnicode_FromString(ares->referral);
2063 if (reply->obj == NULL) {
2064 TALLOC_FREE(ares);
2065 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2067 DLIST_ADD_END(py_iter->state.next, reply);
2068 TALLOC_FREE(ares);
2069 return LDB_SUCCESS;
2071 case LDB_REPLY_DONE:
2072 result = (struct ldb_result) { .controls = ares->controls };
2073 reply->obj = PyLdbResult_FromResult(&result);
2074 if (reply->obj == NULL) {
2075 TALLOC_FREE(ares);
2076 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2078 py_iter->state.result = reply;
2079 TALLOC_FREE(ares);
2080 return ldb_request_done(req, LDB_SUCCESS);
2083 TALLOC_FREE(ares);
2084 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2087 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2089 PyObject *py_base = Py_None;
2090 int scope = LDB_SCOPE_DEFAULT;
2091 int timeout = 0;
2092 char *expr = NULL;
2093 PyObject *py_attrs = Py_None;
2094 PyObject *py_controls = Py_None;
2095 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2096 int ret;
2097 const char **attrs;
2098 struct ldb_context *ldb_ctx;
2099 struct ldb_control **parsed_controls;
2100 struct ldb_dn *base;
2101 PyLdbSearchIteratorObject *py_iter;
2103 /* type "int" rather than "enum" for "scope" is intentional */
2104 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2105 discard_const_p(char *, kwnames),
2106 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2107 return NULL;
2109 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2110 if (py_iter == NULL) {
2111 PyErr_NoMemory();
2112 return NULL;
2114 py_iter->ldb = self;
2115 Py_INCREF(self);
2116 ZERO_STRUCT(py_iter->state);
2117 py_iter->mem_ctx = talloc_new(NULL);
2118 if (py_iter->mem_ctx == NULL) {
2119 Py_DECREF(py_iter);
2120 PyErr_NoMemory();
2121 return NULL;
2124 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2126 if (py_attrs == Py_None) {
2127 attrs = NULL;
2128 } else {
2129 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2130 if (attrs == NULL) {
2131 Py_DECREF(py_iter);
2132 PyErr_NoMemory();
2133 return NULL;
2137 if (py_base == Py_None) {
2138 base = ldb_get_default_basedn(ldb_ctx);
2139 } else {
2140 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2141 Py_DECREF(py_iter);
2142 PyErr_NoMemory();
2143 return NULL;
2147 if (py_controls == Py_None) {
2148 parsed_controls = NULL;
2149 } else {
2150 const char **controls = NULL;
2152 controls = PyList_AsStrList(py_iter->mem_ctx,
2153 py_controls, "controls");
2154 if (controls == NULL) {
2155 Py_DECREF(py_iter);
2156 PyErr_NoMemory();
2157 return NULL;
2160 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2161 py_iter->mem_ctx,
2162 controls);
2163 if (controls[0] != NULL && parsed_controls == NULL) {
2164 Py_DECREF(py_iter);
2165 PyErr_NoMemory();
2166 return NULL;
2168 talloc_free(controls);
2171 ret = ldb_build_search_req(&py_iter->state.req,
2172 ldb_ctx,
2173 py_iter->mem_ctx,
2174 base,
2175 scope,
2176 expr,
2177 attrs,
2178 parsed_controls,
2179 py_iter,
2180 py_ldb_search_iterator_callback,
2181 NULL);
2182 if (ret != LDB_SUCCESS) {
2183 Py_DECREF(py_iter);
2184 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2185 return NULL;
2188 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2190 ret = ldb_request(ldb_ctx, py_iter->state.req);
2191 if (ret != LDB_SUCCESS) {
2192 Py_DECREF(py_iter);
2193 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2194 return NULL;
2197 return (PyObject *)py_iter;
2200 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2202 char *name;
2203 void *data;
2205 if (!PyArg_ParseTuple(args, "s", &name))
2206 return NULL;
2208 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2210 if (data == NULL)
2211 Py_RETURN_NONE;
2213 /* FIXME: More interpretation */
2215 Py_RETURN_TRUE;
2218 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2220 char *name;
2221 PyObject *data;
2223 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2224 return NULL;
2226 /* FIXME: More interpretation */
2228 ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
2230 Py_RETURN_NONE;
2233 static PyObject *py_ldb_modules(PyLdbObject *self,
2234 PyObject *Py_UNUSED(ignored))
2236 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2237 PyObject *ret = PyList_New(0);
2238 struct ldb_module *mod;
2240 if (ret == NULL) {
2241 return PyErr_NoMemory();
2243 for (mod = ldb->modules; mod; mod = mod->next) {
2244 PyObject *item = PyLdbModule_FromModule(mod);
2245 int res = 0;
2246 if (item == NULL) {
2247 PyErr_SetString(PyExc_RuntimeError,
2248 "Failed to load LdbModule");
2249 Py_CLEAR(ret);
2250 return NULL;
2252 res = PyList_Append(ret, item);
2253 Py_CLEAR(item);
2254 if (res == -1) {
2255 Py_CLEAR(ret);
2256 return NULL;
2260 return ret;
2263 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2265 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2266 int type, ret;
2267 uint64_t value;
2269 if (!PyArg_ParseTuple(args, "i", &type))
2270 return NULL;
2272 /* FIXME: More interpretation */
2274 ret = ldb_sequence_number(ldb, type, &value);
2276 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2278 return PyLong_FromLongLong(value);
2282 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2283 .name = "TEST",
2284 .read_fn = ldb_handler_copy,
2285 .write_clear_fn = ldb_handler_copy,
2286 .write_hex_fn = ldb_handler_copy,
2289 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2290 PyObject *Py_UNUSED(ignored))
2292 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2293 int ret;
2295 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2297 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2299 Py_RETURN_NONE;
2303 static PyMethodDef py_ldb_methods[] = {
2304 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2305 "S.set_debug(callback) -> None\n"
2306 "Set callback for LDB debug messages.\n"
2307 "The callback should accept a debug level and debug text." },
2308 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2309 "S.set_create_perms(mode) -> None\n"
2310 "Set mode to use when creating new LDB files." },
2311 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2312 "S.set_modules_dir(path) -> None\n"
2313 "Set path LDB should search for modules" },
2314 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2315 "S.transaction_start() -> None\n"
2316 "Start a new transaction." },
2317 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2318 "S.transaction_prepare_commit() -> None\n"
2319 "prepare to commit a new transaction (2-stage commit)." },
2320 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2321 "S.transaction_commit() -> None\n"
2322 "commit a new transaction." },
2323 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2324 "S.transaction_cancel() -> None\n"
2325 "cancel a new transaction." },
2326 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2327 NULL },
2328 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2329 NULL },
2330 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2331 NULL },
2332 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2333 NULL },
2334 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2335 NULL },
2336 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2337 METH_VARARGS|METH_KEYWORDS,
2338 "S.connect(url, flags=0, options=None) -> None\n"
2339 "Connect to a LDB URL." },
2340 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2341 METH_VARARGS|METH_KEYWORDS,
2342 "S.modify(message, controls=None, validate=False) -> None\n"
2343 "Modify an entry." },
2344 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2345 METH_VARARGS|METH_KEYWORDS,
2346 "S.add(message, controls=None) -> None\n"
2347 "Add an entry." },
2348 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2349 METH_VARARGS|METH_KEYWORDS,
2350 "S.delete(dn, controls=None) -> None\n"
2351 "Remove an entry." },
2352 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2353 METH_VARARGS|METH_KEYWORDS,
2354 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2355 "Rename an entry." },
2356 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2357 METH_VARARGS|METH_KEYWORDS,
2358 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2359 "Search in a database.\n"
2360 "\n"
2361 ":param base: Optional base DN to search\n"
2362 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2363 ":param expression: Optional search expression\n"
2364 ":param attrs: Attributes to return (defaults to all)\n"
2365 ":param controls: Optional list of controls\n"
2366 ":return: ldb.Result object\n"
2368 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2369 py_ldb_search_iterator),
2370 METH_VARARGS|METH_KEYWORDS,
2371 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2372 "Search in a database.\n"
2373 "\n"
2374 ":param base: Optional base DN to search\n"
2375 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2376 ":param expression: Optional search expression\n"
2377 ":param attrs: Attributes to return (defaults to all)\n"
2378 ":param controls: Optional list of controls\n"
2379 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2380 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2382 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2383 NULL },
2384 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2385 NULL },
2386 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2387 NULL },
2388 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2389 "S.parse_ldif(ldif) -> iter(messages)\n"
2390 "Parse a string formatted using LDIF." },
2391 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2392 "S.write_ldif(message, changetype) -> ldif\n"
2393 "Print the message as a string formatted using LDIF." },
2394 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2395 "S.msg_diff(Message) -> Message\n"
2396 "Return an LDB Message of the difference between two Message objects." },
2397 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2398 "S.get_opaque(name) -> value\n"
2399 "Get an opaque value set on this LDB connection. \n"
2400 ":note: The returned value may not be useful in Python."
2402 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2403 "S.set_opaque(name, value) -> None\n"
2404 "Set an opaque value on this LDB connection. \n"
2405 ":note: Passing incorrect values may cause crashes." },
2406 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2407 "S.modules() -> list\n"
2408 "Return the list of modules on this LDB connection " },
2409 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2410 "S.sequence_number(type) -> value\n"
2411 "Return the value of the sequence according to the requested type" },
2412 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2413 "S._register_test_extensions() -> None\n"
2414 "Register internal extensions used in testing" },
2415 {0},
2418 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2420 PyLdbModuleObject *ret;
2422 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2423 if (ret == NULL) {
2424 PyErr_NoMemory();
2425 return NULL;
2427 ret->mem_ctx = talloc_new(NULL);
2428 ret->mod = talloc_reference(ret->mem_ctx, mod);
2429 return (PyObject *)ret;
2432 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2434 struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
2435 if (mod == NULL) {
2436 Py_RETURN_NONE;
2438 return PyLdbModule_FromModule(mod);
2441 static PyGetSetDef py_ldb_getset[] = {
2443 .name = discard_const_p(char, "firstmodule"),
2444 .get = (getter)py_ldb_get_firstmodule,
2446 { .name = NULL },
2449 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2451 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2452 struct ldb_dn *dn;
2453 struct ldb_result *result;
2454 unsigned int count;
2455 int ret;
2457 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2458 return -1;
2461 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2462 NULL);
2463 if (ret != LDB_SUCCESS) {
2464 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2465 return -1;
2468 count = result->count;
2470 talloc_free(result);
2472 if (count > 1) {
2473 PyErr_Format(PyExc_RuntimeError,
2474 "Searching for [%s] dn gave %u results!",
2475 ldb_dn_get_linearized(dn),
2476 count);
2477 return -1;
2480 return count;
2483 static PySequenceMethods py_ldb_seq = {
2484 .sq_contains = (objobjproc)py_ldb_contains,
2487 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2489 PyLdbObject *ret;
2491 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2492 if (ret == NULL) {
2493 PyErr_NoMemory();
2494 return NULL;
2496 ret->mem_ctx = talloc_new(NULL);
2497 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2498 return (PyObject *)ret;
2501 static void py_ldb_dealloc(PyLdbObject *self)
2503 talloc_free(self->mem_ctx);
2504 Py_TYPE(self)->tp_free(self);
2507 static PyTypeObject PyLdb = {
2508 .tp_name = "ldb.Ldb",
2509 .tp_methods = py_ldb_methods,
2510 .tp_repr = (reprfunc)py_ldb_repr,
2511 .tp_new = py_ldb_new,
2512 .tp_init = (initproc)py_ldb_init,
2513 .tp_dealloc = (destructor)py_ldb_dealloc,
2514 .tp_getset = py_ldb_getset,
2515 .tp_getattro = PyObject_GenericGetAttr,
2516 .tp_basicsize = sizeof(PyLdbObject),
2517 .tp_doc = "Connection to a LDB database.",
2518 .tp_as_sequence = &py_ldb_seq,
2519 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2522 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2524 talloc_free(self->mem_ctx);
2525 Py_DECREF(self->msgs);
2526 Py_DECREF(self->referals);
2527 Py_DECREF(self->controls);
2528 Py_TYPE(self)->tp_free(self);
2531 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2533 Py_INCREF(self->msgs);
2534 return self->msgs;
2537 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2539 Py_INCREF(self->controls);
2540 return self->controls;
2543 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2545 Py_INCREF(self->referals);
2546 return self->referals;
2549 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2551 Py_ssize_t size;
2552 if (self->msgs == NULL) {
2553 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2554 return NULL;
2556 size = PyList_Size(self->msgs);
2557 return PyLong_FromLong(size);
2560 static PyGetSetDef py_ldb_result_getset[] = {
2562 .name = discard_const_p(char, "controls"),
2563 .get = (getter)py_ldb_result_get_controls,
2566 .name = discard_const_p(char, "msgs"),
2567 .get = (getter)py_ldb_result_get_msgs,
2570 .name = discard_const_p(char, "referals"),
2571 .get = (getter)py_ldb_result_get_referals,
2574 .name = discard_const_p(char, "count"),
2575 .get = (getter)py_ldb_result_get_count,
2577 { .name = NULL },
2580 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2582 return PyObject_GetIter(self->msgs);
2585 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2587 return PySequence_Size(self->msgs);
2590 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2592 return PySequence_GetItem(self->msgs, idx);
2595 static PySequenceMethods py_ldb_result_seq = {
2596 .sq_length = (lenfunc)py_ldb_result_len,
2597 .sq_item = (ssizeargfunc)py_ldb_result_find,
2600 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2602 return PyUnicode_FromString("<ldb result>");
2606 static PyTypeObject PyLdbResult = {
2607 .tp_name = "ldb.Result",
2608 .tp_repr = (reprfunc)py_ldb_result_repr,
2609 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2610 .tp_iter = (getiterfunc)py_ldb_result_iter,
2611 .tp_getset = py_ldb_result_getset,
2612 .tp_getattro = PyObject_GenericGetAttr,
2613 .tp_basicsize = sizeof(PyLdbResultObject),
2614 .tp_as_sequence = &py_ldb_result_seq,
2615 .tp_doc = "LDB result.",
2616 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2619 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2621 Py_XDECREF(self->state.exception);
2622 TALLOC_FREE(self->mem_ctx);
2623 ZERO_STRUCT(self->state);
2624 Py_DECREF(self->ldb);
2625 Py_TYPE(self)->tp_free(self);
2628 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2630 PyObject *py_ret = NULL;
2632 if (self->state.req == NULL) {
2633 PyErr_SetString(PyExc_RuntimeError,
2634 "ldb.SearchIterator request already finished");
2635 return NULL;
2639 * TODO: do we want a non-blocking mode?
2640 * In future we may add an optional 'nonblocking'
2641 * argument to search_iterator().
2643 * For now we keep it simple and wait for at
2644 * least one reply.
2647 while (self->state.next == NULL) {
2648 int ret;
2650 if (self->state.result != NULL) {
2652 * We (already) got a final result from the server.
2654 * We stop the iteration and let
2655 * py_ldb_search_iterator_result() will deliver
2656 * the result details.
2658 TALLOC_FREE(self->state.req);
2659 PyErr_SetNone(PyExc_StopIteration);
2660 return NULL;
2663 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2664 if (ret != LDB_SUCCESS) {
2665 struct ldb_context *ldb_ctx;
2666 TALLOC_FREE(self->state.req);
2667 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
2669 * We stop the iteration and let
2670 * py_ldb_search_iterator_result() will deliver
2671 * the exception.
2673 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2674 ret, ldb_errstring(ldb_ctx));
2675 PyErr_SetNone(PyExc_StopIteration);
2676 return NULL;
2680 py_ret = self->state.next->obj;
2681 self->state.next->obj = NULL;
2682 /* no TALLOC_FREE() as self->state.next is a list */
2683 talloc_free(self->state.next);
2684 return py_ret;
2687 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
2688 PyObject *Py_UNUSED(ignored))
2690 PyObject *py_ret = NULL;
2692 if (self->state.req != NULL) {
2693 PyErr_SetString(PyExc_RuntimeError,
2694 "ldb.SearchIterator request running");
2695 return NULL;
2698 if (self->state.next != NULL) {
2699 PyErr_SetString(PyExc_RuntimeError,
2700 "ldb.SearchIterator not fully consumed.");
2701 return NULL;
2704 if (self->state.exception != NULL) {
2705 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2706 self->state.exception = NULL;
2707 return NULL;
2710 if (self->state.result == NULL) {
2711 PyErr_SetString(PyExc_RuntimeError,
2712 "ldb.SearchIterator result already consumed");
2713 return NULL;
2716 py_ret = self->state.result->obj;
2717 self->state.result->obj = NULL;
2718 TALLOC_FREE(self->state.result);
2719 return py_ret;
2722 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
2723 PyObject *Py_UNUSED(ignored))
2725 if (self->state.req == NULL) {
2726 PyErr_SetString(PyExc_RuntimeError,
2727 "ldb.SearchIterator request already finished");
2728 return NULL;
2731 Py_XDECREF(self->state.exception);
2732 TALLOC_FREE(self->mem_ctx);
2733 ZERO_STRUCT(self->state);
2734 Py_RETURN_NONE;
2737 static PyMethodDef py_ldb_search_iterator_methods[] = {
2738 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2739 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2740 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2741 "S.abandon()\n" },
2745 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2747 return PyUnicode_FromString("<ldb search iterator>");
2750 static PyTypeObject PyLdbSearchIterator = {
2751 .tp_name = "ldb.SearchIterator",
2752 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2753 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2754 .tp_iter = PyObject_SelfIter,
2755 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2756 .tp_methods = py_ldb_search_iterator_methods,
2757 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2758 .tp_doc = "LDB search_iterator.",
2759 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2762 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2764 return PyUnicode_FromFormat("<ldb module '%s'>",
2765 pyldb_Module_AsModule(self)->ops->name);
2768 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2770 return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
2773 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
2774 PyObject *Py_UNUSED(ignored))
2776 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2777 Py_RETURN_NONE;
2780 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
2781 PyObject *Py_UNUSED(ignored))
2783 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2784 Py_RETURN_NONE;
2787 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
2788 PyObject *Py_UNUSED(ignored))
2790 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2791 Py_RETURN_NONE;
2794 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2796 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2797 int ret, scope;
2798 struct ldb_request *req;
2799 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2800 struct ldb_module *mod;
2801 const char * const*attrs;
2803 /* type "int" rather than "enum" for "scope" is intentional */
2804 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2805 discard_const_p(char *, kwnames),
2806 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2807 return NULL;
2809 mod = self->mod;
2811 if (py_attrs == Py_None) {
2812 attrs = NULL;
2813 } else {
2814 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2815 if (attrs == NULL)
2816 return NULL;
2819 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
2820 scope, NULL /* expr */, attrs,
2821 NULL /* controls */, NULL, NULL, NULL);
2823 talloc_steal(req, attrs);
2825 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2827 req->op.search.res = NULL;
2829 ret = mod->ops->search(mod, req);
2831 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2833 py_ret = PyLdbResult_FromResult(req->op.search.res);
2835 talloc_free(req);
2837 return py_ret;
2841 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2843 struct ldb_request *req;
2844 PyObject *py_message;
2845 int ret;
2846 struct ldb_module *mod;
2848 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2849 return NULL;
2851 req = talloc_zero(NULL, struct ldb_request);
2852 req->operation = LDB_ADD;
2853 req->op.add.message = pyldb_Message_AsMessage(py_message);
2855 mod = pyldb_Module_AsModule(self);
2856 ret = mod->ops->add(mod, req);
2858 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2860 Py_RETURN_NONE;
2863 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2865 int ret;
2866 struct ldb_request *req;
2867 PyObject *py_message;
2868 struct ldb_module *mod;
2870 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2871 return NULL;
2873 req = talloc_zero(NULL, struct ldb_request);
2874 req->operation = LDB_MODIFY;
2875 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2877 mod = pyldb_Module_AsModule(self);
2878 ret = mod->ops->modify(mod, req);
2880 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2882 Py_RETURN_NONE;
2885 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2887 int ret;
2888 struct ldb_request *req;
2889 PyObject *py_dn;
2891 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2892 return NULL;
2894 req = talloc_zero(NULL, struct ldb_request);
2895 req->operation = LDB_DELETE;
2896 req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
2898 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2900 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2902 Py_RETURN_NONE;
2905 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2907 int ret;
2908 struct ldb_request *req;
2909 PyObject *py_dn1, *py_dn2;
2911 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2912 return NULL;
2914 req = talloc_zero(NULL, struct ldb_request);
2916 req->operation = LDB_RENAME;
2917 req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
2918 req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
2920 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2922 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2924 Py_RETURN_NONE;
2927 static PyMethodDef py_ldb_module_methods[] = {
2928 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
2929 METH_VARARGS|METH_KEYWORDS, NULL },
2930 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2931 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2932 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2933 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2934 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2935 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2936 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2937 {0},
2940 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2942 talloc_free(self->mem_ctx);
2943 PyObject_Del(self);
2946 static PyTypeObject PyLdbModule = {
2947 .tp_name = "ldb.LdbModule",
2948 .tp_methods = py_ldb_module_methods,
2949 .tp_repr = (reprfunc)py_ldb_module_repr,
2950 .tp_str = (reprfunc)py_ldb_module_str,
2951 .tp_basicsize = sizeof(PyLdbModuleObject),
2952 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2953 .tp_flags = Py_TPFLAGS_DEFAULT,
2954 .tp_doc = "LDB module (extension)",
2959 * Create a ldb_message_element from a Python object.
2961 * This will accept any sequence objects that contains strings, or
2962 * a string object.
2964 * A reference to set_obj will be borrowed.
2966 * @param mem_ctx Memory context
2967 * @param set_obj Python object to convert
2968 * @param flags ldb_message_element flags to set
2969 * @param attr_name Name of the attribute
2970 * @return New ldb_message_element, allocated as child of mem_ctx
2972 static struct ldb_message_element *PyObject_AsMessageElement(
2973 TALLOC_CTX *mem_ctx,
2974 PyObject *set_obj,
2975 unsigned int flags,
2976 const char *attr_name)
2978 struct ldb_message_element *me;
2979 const char *msg = NULL;
2980 Py_ssize_t size;
2981 int result;
2983 if (pyldb_MessageElement_Check(set_obj)) {
2984 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2985 /* We have to talloc_reference() the memory context, not the pointer
2986 * which may not actually be it's own context */
2987 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2988 return pyldb_MessageElement_AsMessageElement(set_obj);
2990 return NULL;
2993 me = talloc(mem_ctx, struct ldb_message_element);
2994 if (me == NULL) {
2995 PyErr_NoMemory();
2996 return NULL;
2999 me->name = talloc_strdup(me, attr_name);
3000 me->flags = flags;
3001 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
3002 me->num_values = 1;
3003 me->values = talloc_array(me, struct ldb_val, me->num_values);
3004 if (PyBytes_Check(set_obj)) {
3005 char *_msg = NULL;
3006 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
3007 if (result != 0) {
3008 talloc_free(me);
3009 return NULL;
3011 msg = _msg;
3012 } else {
3013 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3014 if (msg == NULL) {
3015 talloc_free(me);
3016 return NULL;
3019 me->values[0].data = talloc_memdup(me,
3020 (const uint8_t *)msg,
3021 size+1);
3022 me->values[0].length = size;
3023 } else if (PySequence_Check(set_obj)) {
3024 Py_ssize_t i;
3025 me->num_values = PySequence_Size(set_obj);
3026 me->values = talloc_array(me, struct ldb_val, me->num_values);
3027 for (i = 0; i < me->num_values; i++) {
3028 PyObject *obj = PySequence_GetItem(set_obj, i);
3029 if (PyBytes_Check(obj)) {
3030 char *_msg = NULL;
3031 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3032 if (result != 0) {
3033 talloc_free(me);
3034 return NULL;
3036 msg = _msg;
3037 } else if (PyUnicode_Check(obj)) {
3038 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3039 if (msg == NULL) {
3040 talloc_free(me);
3041 return NULL;
3043 } else {
3044 PyErr_Format(PyExc_TypeError,
3045 "Expected string as element %zd in list", i);
3046 talloc_free(me);
3047 return NULL;
3049 me->values[i].data = talloc_memdup(me,
3050 (const uint8_t *)msg,
3051 size+1);
3052 me->values[i].length = size;
3054 } else {
3055 PyErr_Format(PyExc_TypeError,
3056 "String or List type expected for '%s' attribute", attr_name);
3057 talloc_free(me);
3058 me = NULL;
3061 return me;
3065 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3066 struct ldb_message_element *me)
3068 Py_ssize_t i;
3069 PyObject *result;
3071 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3072 result = PyList_New(me->num_values);
3074 for (i = 0; i < me->num_values; i++) {
3075 PyList_SetItem(result, i,
3076 PyObject_FromLdbValue(&me->values[i]));
3079 return result;
3082 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3084 unsigned int i;
3085 if (!PyArg_ParseTuple(args, "I", &i))
3086 return NULL;
3087 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3088 Py_RETURN_NONE;
3090 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3093 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3095 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3096 return PyLong_FromLong(el->flags);
3099 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3101 unsigned int flags;
3102 struct ldb_message_element *el;
3103 if (!PyArg_ParseTuple(args, "I", &flags))
3104 return NULL;
3106 el = pyldb_MessageElement_AsMessageElement(self);
3107 el->flags = flags;
3108 Py_RETURN_NONE;
3111 static PyMethodDef py_ldb_msg_element_methods[] = {
3112 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3113 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3114 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3115 {0},
3118 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3120 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3123 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3125 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3126 if (idx < 0 || idx >= el->num_values) {
3127 PyErr_SetString(PyExc_IndexError, "Out of range");
3128 return NULL;
3130 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3133 static PySequenceMethods py_ldb_msg_element_seq = {
3134 .sq_length = (lenfunc)py_ldb_msg_element_len,
3135 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3138 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3140 int ret;
3141 if (!pyldb_MessageElement_Check(other)) {
3142 Py_INCREF(Py_NotImplemented);
3143 return Py_NotImplemented;
3145 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3146 pyldb_MessageElement_AsMessageElement(other));
3147 return richcmp(ret, op);
3150 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3152 PyObject *el = ldb_msg_element_to_set(NULL,
3153 pyldb_MessageElement_AsMessageElement(self));
3154 PyObject *ret = PyObject_GetIter(el);
3155 Py_DECREF(el);
3156 return ret;
3159 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3161 PyLdbMessageElementObject *ret;
3162 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3163 if (ret == NULL) {
3164 PyErr_NoMemory();
3165 return NULL;
3167 ret->mem_ctx = talloc_new(NULL);
3168 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3169 PyErr_NoMemory();
3170 return NULL;
3172 ret->el = el;
3173 return (PyObject *)ret;
3176 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3178 PyObject *py_elements = NULL;
3179 struct ldb_message_element *el;
3180 unsigned int flags = 0;
3181 char *name = NULL;
3182 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3183 PyLdbMessageElementObject *ret;
3184 TALLOC_CTX *mem_ctx;
3185 const char *msg = NULL;
3186 Py_ssize_t size;
3187 int result;
3189 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3190 discard_const_p(char *, kwnames),
3191 &py_elements, &flags, &name))
3192 return NULL;
3194 mem_ctx = talloc_new(NULL);
3195 if (mem_ctx == NULL) {
3196 PyErr_NoMemory();
3197 return NULL;
3200 el = talloc_zero(mem_ctx, struct ldb_message_element);
3201 if (el == NULL) {
3202 PyErr_NoMemory();
3203 talloc_free(mem_ctx);
3204 return NULL;
3207 if (py_elements != NULL) {
3208 Py_ssize_t i;
3209 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3210 char *_msg = NULL;
3211 el->num_values = 1;
3212 el->values = talloc_array(el, struct ldb_val, 1);
3213 if (el->values == NULL) {
3214 talloc_free(mem_ctx);
3215 PyErr_NoMemory();
3216 return NULL;
3218 if (PyBytes_Check(py_elements)) {
3219 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3220 msg = _msg;
3221 } else {
3222 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3223 result = (msg == NULL) ? -1 : 0;
3225 if (result != 0) {
3226 talloc_free(mem_ctx);
3227 return NULL;
3229 el->values[0].data = talloc_memdup(el->values,
3230 (const uint8_t *)msg, size + 1);
3231 el->values[0].length = size;
3232 } else if (PySequence_Check(py_elements)) {
3233 el->num_values = PySequence_Size(py_elements);
3234 el->values = talloc_array(el, struct ldb_val, el->num_values);
3235 if (el->values == NULL) {
3236 talloc_free(mem_ctx);
3237 PyErr_NoMemory();
3238 return NULL;
3240 for (i = 0; i < el->num_values; i++) {
3241 PyObject *item = PySequence_GetItem(py_elements, i);
3242 if (item == NULL) {
3243 talloc_free(mem_ctx);
3244 return NULL;
3246 if (PyBytes_Check(item)) {
3247 char *_msg = NULL;
3248 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3249 msg = _msg;
3250 } else if (PyUnicode_Check(item)) {
3251 msg = PyUnicode_AsUTF8AndSize(item, &size);
3252 result = (msg == NULL) ? -1 : 0;
3253 } else {
3254 PyErr_Format(PyExc_TypeError,
3255 "Expected string as element %zd in list", i);
3256 result = -1;
3258 if (result != 0) {
3259 talloc_free(mem_ctx);
3260 return NULL;
3262 el->values[i].data = talloc_memdup(el,
3263 (const uint8_t *)msg, size+1);
3264 el->values[i].length = size;
3266 } else {
3267 PyErr_SetString(PyExc_TypeError,
3268 "Expected string or list");
3269 talloc_free(mem_ctx);
3270 return NULL;
3274 el->flags = flags;
3275 el->name = talloc_strdup(el, name);
3277 ret = PyObject_New(PyLdbMessageElementObject, type);
3278 if (ret == NULL) {
3279 talloc_free(mem_ctx);
3280 return NULL;
3283 ret->mem_ctx = mem_ctx;
3284 ret->el = el;
3285 return (PyObject *)ret;
3288 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3290 char *element_str = NULL;
3291 Py_ssize_t i;
3292 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3293 PyObject *ret, *repr;
3295 for (i = 0; i < el->num_values; i++) {
3296 PyObject *o = py_ldb_msg_element_find(self, i);
3297 repr = PyObject_Repr(o);
3298 if (element_str == NULL)
3299 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3300 else
3301 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3302 Py_DECREF(repr);
3305 if (element_str != NULL) {
3306 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3307 talloc_free(element_str);
3308 } else {
3309 ret = PyUnicode_FromString("MessageElement([])");
3312 return ret;
3315 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3317 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3319 if (el->num_values == 1)
3320 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3321 else
3322 Py_RETURN_NONE;
3325 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3327 talloc_free(self->mem_ctx);
3328 PyObject_Del(self);
3331 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3333 return wrap_text("MessageElementTextWrapper", self);
3336 static PyGetSetDef py_ldb_msg_element_getset[] = {
3338 .name = discard_const_p(char, "text"),
3339 .get = (getter)py_ldb_msg_element_get_text,
3341 { .name = NULL }
3344 static PyTypeObject PyLdbMessageElement = {
3345 .tp_name = "ldb.MessageElement",
3346 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3347 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3348 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3349 .tp_str = (reprfunc)py_ldb_msg_element_str,
3350 .tp_methods = py_ldb_msg_element_methods,
3351 .tp_getset = py_ldb_msg_element_getset,
3352 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3353 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3354 .tp_as_sequence = &py_ldb_msg_element_seq,
3355 .tp_new = py_ldb_msg_element_new,
3356 .tp_flags = Py_TPFLAGS_DEFAULT,
3357 .tp_doc = "An element of a Message",
3361 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3363 PyObject *py_ldb;
3364 PyObject *py_dict;
3365 PyObject *py_ret;
3366 struct ldb_message *msg;
3367 struct ldb_context *ldb_ctx;
3368 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3370 if (!PyArg_ParseTuple(args, "O!O!|I",
3371 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3372 &mod_flags)) {
3373 return NULL;
3376 if (!PyLdb_Check(py_ldb)) {
3377 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3378 return NULL;
3381 /* mask only flags we are going to use */
3382 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3383 if (!mod_flags) {
3384 PyErr_SetString(PyExc_ValueError,
3385 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3386 " expected as mod_flag value");
3387 return NULL;
3390 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3392 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3393 if (!msg) {
3394 return NULL;
3397 py_ret = PyLdbMessage_FromMessage(msg);
3399 talloc_unlink(ldb_ctx, msg);
3401 return py_ret;
3404 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3406 char *name;
3407 if (!PyArg_ParseTuple(args, "s", &name))
3408 return NULL;
3410 ldb_msg_remove_attr(self->msg, name);
3412 Py_RETURN_NONE;
3415 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
3416 PyObject *Py_UNUSED(ignored))
3418 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3419 Py_ssize_t i, j = 0;
3420 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3421 if (msg->dn != NULL) {
3422 PyList_SetItem(obj, j, PyUnicode_FromString("dn"));
3423 j++;
3425 for (i = 0; i < msg->num_elements; i++) {
3426 PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name));
3427 j++;
3429 return obj;
3432 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3434 struct ldb_message_element *el;
3435 const char *name;
3436 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3437 name = PyUnicode_AsUTF8(py_name);
3438 if (name == NULL) {
3439 PyErr_SetNone(PyExc_TypeError);
3440 return NULL;
3442 if (!ldb_attr_cmp(name, "dn"))
3443 return pyldb_Dn_FromDn(msg->dn);
3444 el = ldb_msg_find_element(msg, name);
3445 if (el == NULL) {
3446 return NULL;
3448 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3451 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3453 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3454 if (ret == NULL) {
3455 PyErr_SetString(PyExc_KeyError, "No such element");
3456 return NULL;
3458 return ret;
3461 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3463 PyObject *def = NULL;
3464 const char *kwnames[] = { "name", "default", "idx", NULL };
3465 const char *name = NULL;
3466 int idx = -1;
3467 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3468 struct ldb_message_element *el;
3470 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3471 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3472 return NULL;
3475 if (strcasecmp(name, "dn") == 0) {
3476 return pyldb_Dn_FromDn(msg->dn);
3479 el = ldb_msg_find_element(msg, name);
3481 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3482 if (def != NULL) {
3483 Py_INCREF(def);
3484 return def;
3486 Py_RETURN_NONE;
3489 if (idx == -1) {
3490 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3493 return PyObject_FromLdbValue(&el->values[idx]);
3496 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
3497 PyObject *Py_UNUSED(ignored))
3499 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3500 Py_ssize_t i, j = 0;
3501 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3502 if (l == NULL) {
3503 return PyErr_NoMemory();
3505 if (msg->dn != NULL) {
3506 PyObject *value = NULL;
3507 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3508 int res = 0;
3509 value = Py_BuildValue("(sO)", "dn", obj);
3510 Py_CLEAR(obj);
3511 if (value == NULL) {
3512 Py_CLEAR(l);
3513 return NULL;
3515 res = PyList_SetItem(l, 0, value);
3516 if (res == -1) {
3517 Py_CLEAR(l);
3518 return NULL;
3520 j++;
3522 for (i = 0; i < msg->num_elements; i++, j++) {
3523 PyObject *value = NULL;
3524 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3525 int res = 0;
3526 Py_CLEAR(py_el);
3527 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3528 if (value == NULL ) {
3529 Py_CLEAR(l);
3530 return NULL;
3532 res = PyList_SetItem(l, 0, value);
3533 if (res == -1) {
3534 Py_CLEAR(l);
3535 return NULL;
3538 return l;
3541 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
3542 PyObject *Py_UNUSED(ignored))
3544 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3545 Py_ssize_t i = 0;
3546 PyObject *l = PyList_New(msg->num_elements);
3547 for (i = 0; i < msg->num_elements; i++) {
3548 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3550 return l;
3553 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3555 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3556 PyLdbMessageElementObject *py_element;
3557 int i, ret;
3558 struct ldb_message_element *el;
3559 struct ldb_message_element *el_new;
3561 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3562 return NULL;
3564 el = py_element->el;
3565 if (el == NULL) {
3566 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3567 return NULL;
3569 if (el->name == NULL) {
3570 PyErr_SetString(PyExc_ValueError,
3571 "The element has no name");
3572 return NULL;
3574 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3575 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3577 /* now deep copy all attribute values */
3578 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3579 if (el_new->values == NULL) {
3580 PyErr_NoMemory();
3581 return NULL;
3583 el_new->num_values = el->num_values;
3585 for (i = 0; i < el->num_values; i++) {
3586 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3587 if (el_new->values[i].data == NULL
3588 && el->values[i].length != 0) {
3589 PyErr_NoMemory();
3590 return NULL;
3594 Py_RETURN_NONE;
3597 static PyMethodDef py_ldb_msg_methods[] = {
3598 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3599 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3600 "Class method to create ldb.Message object from Dictionary.\n"
3601 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3602 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3603 "S.keys() -> list\n\n"
3604 "Return sequence of all attribute names." },
3605 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3606 "S.remove(name)\n\n"
3607 "Remove all entries for attributes with the specified name."},
3608 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
3609 METH_VARARGS | METH_KEYWORDS,
3610 "msg.get(name,default=None,idx=None) -> string\n"
3611 "idx is the index into the values array\n"
3612 "if idx is None, then a list is returned\n"
3613 "if idx is not None, then the element with that index is returned\n"
3614 "if you pass the special name 'dn' then the DN object is returned\n"},
3615 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3616 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3617 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3618 "S.add(element)\n\n"
3619 "Add an element to this message." },
3620 {0},
3623 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3625 PyObject *list, *iter;
3627 list = py_ldb_msg_keys(self, NULL);
3628 iter = PyObject_GetIter(list);
3629 Py_DECREF(list);
3630 return iter;
3633 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3635 const char *attr_name;
3637 attr_name = PyUnicode_AsUTF8(name);
3638 if (attr_name == NULL) {
3639 PyErr_SetNone(PyExc_TypeError);
3640 return -1;
3643 if (value == NULL) {
3644 /* delitem */
3645 ldb_msg_remove_attr(self->msg, attr_name);
3646 } else {
3647 int ret;
3648 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3649 value, 0, attr_name);
3650 if (el == NULL) {
3651 return -1;
3653 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3654 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3655 if (ret != LDB_SUCCESS) {
3656 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3657 return -1;
3660 return 0;
3663 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3665 return pyldb_Message_AsMessage(self)->num_elements;
3668 static PyMappingMethods py_ldb_msg_mapping = {
3669 .mp_length = (lenfunc)py_ldb_msg_length,
3670 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3671 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3674 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3676 const char * const kwnames[] = { "dn", NULL };
3677 struct ldb_message *ret;
3678 TALLOC_CTX *mem_ctx;
3679 PyObject *pydn = NULL;
3680 PyLdbMessageObject *py_ret;
3682 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3683 discard_const_p(char *, kwnames),
3684 &pydn))
3685 return NULL;
3687 mem_ctx = talloc_new(NULL);
3688 if (mem_ctx == NULL) {
3689 PyErr_NoMemory();
3690 return NULL;
3693 ret = ldb_msg_new(mem_ctx);
3694 if (ret == NULL) {
3695 talloc_free(mem_ctx);
3696 PyErr_NoMemory();
3697 return NULL;
3700 if (pydn != NULL) {
3701 struct ldb_dn *dn;
3702 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3703 talloc_free(mem_ctx);
3704 return NULL;
3706 ret->dn = talloc_reference(ret, dn);
3709 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3710 if (py_ret == NULL) {
3711 PyErr_NoMemory();
3712 talloc_free(mem_ctx);
3713 return NULL;
3716 py_ret->mem_ctx = mem_ctx;
3717 py_ret->msg = ret;
3718 return (PyObject *)py_ret;
3721 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3723 PyLdbMessageObject *ret;
3725 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3726 if (ret == NULL) {
3727 PyErr_NoMemory();
3728 return NULL;
3730 ret->mem_ctx = talloc_new(NULL);
3731 ret->msg = talloc_reference(ret->mem_ctx, msg);
3732 return (PyObject *)ret;
3735 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3737 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3738 return pyldb_Dn_FromDn(msg->dn);
3741 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3743 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3744 if (value == NULL) {
3745 PyErr_SetString(PyExc_AttributeError, "cannot delete dn");
3746 return -1;
3748 if (!pyldb_Dn_Check(value)) {
3749 PyErr_SetString(PyExc_TypeError, "expected dn");
3750 return -1;
3753 msg->dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
3754 return 0;
3757 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3759 return wrap_text("MessageTextWrapper", self);
3762 static PyGetSetDef py_ldb_msg_getset[] = {
3764 .name = discard_const_p(char, "dn"),
3765 .get = (getter)py_ldb_msg_get_dn,
3766 .set = (setter)py_ldb_msg_set_dn,
3769 .name = discard_const_p(char, "text"),
3770 .get = (getter)py_ldb_msg_get_text,
3772 { .name = NULL },
3775 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3777 PyObject *dict = PyDict_New(), *ret, *repr;
3778 if (PyDict_Update(dict, (PyObject *)self) != 0)
3779 return NULL;
3780 repr = PyObject_Repr(dict);
3781 if (repr == NULL) {
3782 Py_DECREF(dict);
3783 return NULL;
3785 ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr));
3786 Py_DECREF(repr);
3787 Py_DECREF(dict);
3788 return ret;
3791 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3793 talloc_free(self->mem_ctx);
3794 PyObject_Del(self);
3797 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3798 PyLdbMessageObject *py_msg2, int op)
3800 struct ldb_message *msg1, *msg2;
3801 unsigned int i;
3802 int ret;
3804 if (!PyLdbMessage_Check(py_msg2)) {
3805 Py_INCREF(Py_NotImplemented);
3806 return Py_NotImplemented;
3809 msg1 = pyldb_Message_AsMessage(py_msg1),
3810 msg2 = pyldb_Message_AsMessage(py_msg2);
3812 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3813 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3814 if (ret != 0) {
3815 return richcmp(ret, op);
3819 ret = msg1->num_elements - msg2->num_elements;
3820 if (ret != 0) {
3821 return richcmp(ret, op);
3824 for (i = 0; i < msg1->num_elements; i++) {
3825 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3826 &msg2->elements[i]);
3827 if (ret != 0) {
3828 return richcmp(ret, op);
3831 ret = ldb_msg_element_compare(&msg1->elements[i],
3832 &msg2->elements[i]);
3833 if (ret != 0) {
3834 return richcmp(ret, op);
3838 return richcmp(0, op);
3841 static PyTypeObject PyLdbMessage = {
3842 .tp_name = "ldb.Message",
3843 .tp_methods = py_ldb_msg_methods,
3844 .tp_getset = py_ldb_msg_getset,
3845 .tp_as_mapping = &py_ldb_msg_mapping,
3846 .tp_basicsize = sizeof(PyLdbMessageObject),
3847 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3848 .tp_new = py_ldb_msg_new,
3849 .tp_repr = (reprfunc)py_ldb_msg_repr,
3850 .tp_flags = Py_TPFLAGS_DEFAULT,
3851 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3852 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3853 .tp_doc = "A LDB Message",
3856 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3858 PyLdbTreeObject *ret;
3860 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3861 if (ret == NULL) {
3862 PyErr_NoMemory();
3863 return NULL;
3866 ret->mem_ctx = talloc_new(NULL);
3867 ret->tree = talloc_reference(ret->mem_ctx, tree);
3868 return (PyObject *)ret;
3871 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3873 talloc_free(self->mem_ctx);
3874 PyObject_Del(self);
3877 static PyTypeObject PyLdbTree = {
3878 .tp_name = "ldb.Tree",
3879 .tp_basicsize = sizeof(PyLdbTreeObject),
3880 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3881 .tp_flags = Py_TPFLAGS_DEFAULT,
3882 .tp_doc = "A search tree",
3885 /* Ldb_module */
3886 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3888 PyObject *py_ldb = (PyObject *)mod->private_data;
3889 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3891 py_base = pyldb_Dn_FromDn(req->op.search.base);
3893 if (py_base == NULL)
3894 return LDB_ERR_OPERATIONS_ERROR;
3896 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3898 if (py_tree == NULL)
3899 return LDB_ERR_OPERATIONS_ERROR;
3901 if (req->op.search.attrs == NULL) {
3902 py_attrs = Py_None;
3903 } else {
3904 int i, len;
3905 for (len = 0; req->op.search.attrs[len]; len++);
3906 py_attrs = PyList_New(len);
3907 for (i = 0; i < len; i++)
3908 PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i]));
3911 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3912 discard_const_p(char, "OiOO"),
3913 py_base, req->op.search.scope, py_tree, py_attrs);
3915 Py_DECREF(py_attrs);
3916 Py_DECREF(py_tree);
3917 Py_DECREF(py_base);
3919 if (py_result == NULL) {
3920 return LDB_ERR_PYTHON_EXCEPTION;
3923 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3924 if (req->op.search.res == NULL) {
3925 return LDB_ERR_PYTHON_EXCEPTION;
3928 Py_DECREF(py_result);
3930 return LDB_SUCCESS;
3933 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3935 PyObject *py_ldb = (PyObject *)mod->private_data;
3936 PyObject *py_result, *py_msg;
3938 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3940 if (py_msg == NULL) {
3941 return LDB_ERR_OPERATIONS_ERROR;
3944 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3945 discard_const_p(char, "O"),
3946 py_msg);
3948 Py_DECREF(py_msg);
3950 if (py_result == NULL) {
3951 return LDB_ERR_PYTHON_EXCEPTION;
3954 Py_DECREF(py_result);
3956 return LDB_SUCCESS;
3959 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3961 PyObject *py_ldb = (PyObject *)mod->private_data;
3962 PyObject *py_result, *py_msg;
3964 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3966 if (py_msg == NULL) {
3967 return LDB_ERR_OPERATIONS_ERROR;
3970 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3971 discard_const_p(char, "O"),
3972 py_msg);
3974 Py_DECREF(py_msg);
3976 if (py_result == NULL) {
3977 return LDB_ERR_PYTHON_EXCEPTION;
3980 Py_DECREF(py_result);
3982 return LDB_SUCCESS;
3985 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3987 PyObject *py_ldb = (PyObject *)mod->private_data;
3988 PyObject *py_result, *py_dn;
3990 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3992 if (py_dn == NULL)
3993 return LDB_ERR_OPERATIONS_ERROR;
3995 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3996 discard_const_p(char, "O"),
3997 py_dn);
3999 if (py_result == NULL) {
4000 return LDB_ERR_PYTHON_EXCEPTION;
4003 Py_DECREF(py_result);
4005 return LDB_SUCCESS;
4008 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
4010 PyObject *py_ldb = (PyObject *)mod->private_data;
4011 PyObject *py_result, *py_olddn, *py_newdn;
4013 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
4015 if (py_olddn == NULL)
4016 return LDB_ERR_OPERATIONS_ERROR;
4018 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
4020 if (py_newdn == NULL)
4021 return LDB_ERR_OPERATIONS_ERROR;
4023 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
4024 discard_const_p(char, "OO"),
4025 py_olddn, py_newdn);
4027 Py_DECREF(py_olddn);
4028 Py_DECREF(py_newdn);
4030 if (py_result == NULL) {
4031 return LDB_ERR_PYTHON_EXCEPTION;
4034 Py_DECREF(py_result);
4036 return LDB_SUCCESS;
4039 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
4041 PyObject *py_ldb = (PyObject *)mod->private_data;
4042 PyObject *py_result;
4044 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
4045 discard_const_p(char, ""));
4047 Py_XDECREF(py_result);
4049 return LDB_ERR_OPERATIONS_ERROR;
4052 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4054 PyObject *py_ldb = (PyObject *)mod->private_data;
4055 PyObject *py_result;
4057 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4058 discard_const_p(char, ""));
4060 Py_XDECREF(py_result);
4062 return LDB_ERR_OPERATIONS_ERROR;
4065 static int py_module_start_transaction(struct ldb_module *mod)
4067 PyObject *py_ldb = (PyObject *)mod->private_data;
4068 PyObject *py_result;
4070 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4071 discard_const_p(char, ""));
4073 if (py_result == NULL) {
4074 return LDB_ERR_PYTHON_EXCEPTION;
4077 Py_DECREF(py_result);
4079 return LDB_SUCCESS;
4082 static int py_module_end_transaction(struct ldb_module *mod)
4084 PyObject *py_ldb = (PyObject *)mod->private_data;
4085 PyObject *py_result;
4087 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4088 discard_const_p(char, ""));
4090 if (py_result == NULL) {
4091 return LDB_ERR_PYTHON_EXCEPTION;
4094 Py_DECREF(py_result);
4096 return LDB_SUCCESS;
4099 static int py_module_del_transaction(struct ldb_module *mod)
4101 PyObject *py_ldb = (PyObject *)mod->private_data;
4102 PyObject *py_result;
4104 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4105 discard_const_p(char, ""));
4107 if (py_result == NULL) {
4108 return LDB_ERR_PYTHON_EXCEPTION;
4111 Py_DECREF(py_result);
4113 return LDB_SUCCESS;
4116 static int py_module_destructor(struct ldb_module *mod)
4118 Py_DECREF((PyObject *)mod->private_data);
4119 return 0;
4122 static int py_module_init(struct ldb_module *mod)
4124 PyObject *py_class = (PyObject *)mod->ops->private_data;
4125 PyObject *py_result, *py_next, *py_ldb;
4127 py_ldb = PyLdb_FromLdbContext(mod->ldb);
4129 if (py_ldb == NULL)
4130 return LDB_ERR_OPERATIONS_ERROR;
4132 py_next = PyLdbModule_FromModule(mod->next);
4134 if (py_next == NULL)
4135 return LDB_ERR_OPERATIONS_ERROR;
4137 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4138 py_ldb, py_next);
4140 if (py_result == NULL) {
4141 return LDB_ERR_PYTHON_EXCEPTION;
4144 mod->private_data = py_result;
4146 talloc_set_destructor(mod, py_module_destructor);
4148 return ldb_next_init(mod);
4151 static PyObject *py_register_module(PyObject *module, PyObject *args)
4153 int ret;
4154 struct ldb_module_ops *ops;
4155 PyObject *input;
4156 PyObject *tmp = NULL;
4157 const char *name = NULL;
4159 if (!PyArg_ParseTuple(args, "O", &input))
4160 return NULL;
4162 ops = talloc_zero(NULL, struct ldb_module_ops);
4163 if (ops == NULL) {
4164 PyErr_NoMemory();
4165 return NULL;
4168 tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
4169 if (tmp == NULL) {
4170 return NULL;
4172 name = PyUnicode_AsUTF8(tmp);
4173 if (name == NULL) {
4174 return NULL;
4176 Py_XDECREF(tmp);
4177 Py_INCREF(input);
4179 ops->name = talloc_strdup(ops, name);
4180 ops->private_data = input;
4181 ops->init_context = py_module_init;
4182 ops->search = py_module_search;
4183 ops->add = py_module_add;
4184 ops->modify = py_module_modify;
4185 ops->del = py_module_del;
4186 ops->rename = py_module_rename;
4187 ops->request = py_module_request;
4188 ops->extended = py_module_extended;
4189 ops->start_transaction = py_module_start_transaction;
4190 ops->end_transaction = py_module_end_transaction;
4191 ops->del_transaction = py_module_del_transaction;
4193 ret = ldb_register_module(ops);
4194 if (ret != LDB_SUCCESS) {
4195 TALLOC_FREE(ops);
4198 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4200 Py_RETURN_NONE;
4203 static PyObject *py_timestring(PyObject *module, PyObject *args)
4205 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4206 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4207 long int t_val;
4208 char *tresult;
4209 PyObject *ret;
4210 if (!PyArg_ParseTuple(args, "l", &t_val))
4211 return NULL;
4212 tresult = ldb_timestring(NULL, (time_t) t_val);
4213 ret = PyUnicode_FromString(tresult);
4214 talloc_free(tresult);
4215 return ret;
4218 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4220 char *str;
4221 if (!PyArg_ParseTuple(args, "s", &str))
4222 return NULL;
4224 return PyLong_FromLong(ldb_string_to_time(str));
4227 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4229 char *name;
4230 if (!PyArg_ParseTuple(args, "s", &name))
4231 return NULL;
4232 return PyBool_FromLong(ldb_valid_attr_name(name));
4236 encode a string using RFC2254 rules
4238 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4240 char *str, *encoded;
4241 Py_ssize_t size = 0;
4242 struct ldb_val val;
4243 PyObject *ret;
4245 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4246 return NULL;
4247 val.data = (uint8_t *)str;
4248 val.length = size;
4250 encoded = ldb_binary_encode(NULL, val);
4251 if (encoded == NULL) {
4252 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4253 return NULL;
4255 ret = PyUnicode_FromString(encoded);
4256 talloc_free(encoded);
4257 return ret;
4261 decode a string using RFC2254 rules
4263 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4265 char *str;
4266 struct ldb_val val;
4267 PyObject *ret;
4269 if (!PyArg_ParseTuple(args, "s", &str))
4270 return NULL;
4272 val = ldb_binary_decode(NULL, str);
4273 if (val.data == NULL) {
4274 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4275 return NULL;
4277 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4278 talloc_free(val.data);
4279 return ret;
4282 static PyMethodDef py_ldb_global_methods[] = {
4283 { "register_module", py_register_module, METH_VARARGS,
4284 "S.register_module(module) -> None\n\n"
4285 "Register a LDB module."},
4286 { "timestring", py_timestring, METH_VARARGS,
4287 "S.timestring(int) -> string\n\n"
4288 "Generate a LDAP time string from a UNIX timestamp" },
4289 { "string_to_time", py_string_to_time, METH_VARARGS,
4290 "S.string_to_time(string) -> int\n\n"
4291 "Parse a LDAP time string into a UNIX timestamp." },
4292 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4293 "S.valid_attr_name(name) -> bool\n\nn"
4294 "Check whether the supplied name is a valid attribute name." },
4295 { "binary_encode", py_binary_encode, METH_VARARGS,
4296 "S.binary_encode(string) -> string\n\n"
4297 "Perform a RFC2254 binary encoding on a string" },
4298 { "binary_decode", py_binary_decode, METH_VARARGS,
4299 "S.binary_decode(string) -> string\n\n"
4300 "Perform a RFC2254 binary decode on a string" },
4304 #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."
4306 #if PY_MAJOR_VERSION >= 3
4307 static struct PyModuleDef moduledef = {
4308 PyModuleDef_HEAD_INIT,
4309 .m_name = "ldb",
4310 .m_doc = MODULE_DOC,
4311 .m_size = -1,
4312 .m_methods = py_ldb_global_methods,
4314 #endif
4316 static PyObject* module_init(void)
4318 PyObject *m;
4320 PyLdbBytesType.tp_base = &PyBytes_Type;
4321 if (PyType_Ready(&PyLdbBytesType) < 0) {
4322 return NULL;
4325 if (PyType_Ready(&PyLdbDn) < 0)
4326 return NULL;
4328 if (PyType_Ready(&PyLdbMessage) < 0)
4329 return NULL;
4331 if (PyType_Ready(&PyLdbMessageElement) < 0)
4332 return NULL;
4334 if (PyType_Ready(&PyLdb) < 0)
4335 return NULL;
4337 if (PyType_Ready(&PyLdbModule) < 0)
4338 return NULL;
4340 if (PyType_Ready(&PyLdbTree) < 0)
4341 return NULL;
4343 if (PyType_Ready(&PyLdbResult) < 0)
4344 return NULL;
4346 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4347 return NULL;
4349 if (PyType_Ready(&PyLdbControl) < 0)
4350 return NULL;
4352 #if PY_MAJOR_VERSION >= 3
4353 m = PyModule_Create(&moduledef);
4354 #else
4355 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4356 #endif
4357 if (m == NULL)
4358 return NULL;
4360 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4362 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4363 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4364 ADD_LDB_INT(SEQ_NEXT);
4365 ADD_LDB_INT(SCOPE_DEFAULT);
4366 ADD_LDB_INT(SCOPE_BASE);
4367 ADD_LDB_INT(SCOPE_ONELEVEL);
4368 ADD_LDB_INT(SCOPE_SUBTREE);
4370 ADD_LDB_INT(CHANGETYPE_NONE);
4371 ADD_LDB_INT(CHANGETYPE_ADD);
4372 ADD_LDB_INT(CHANGETYPE_DELETE);
4373 ADD_LDB_INT(CHANGETYPE_MODIFY);
4375 ADD_LDB_INT(FLAG_MOD_ADD);
4376 ADD_LDB_INT(FLAG_MOD_REPLACE);
4377 ADD_LDB_INT(FLAG_MOD_DELETE);
4378 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4380 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4381 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4382 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4383 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4385 ADD_LDB_INT(SUCCESS);
4386 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4387 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4388 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4389 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4390 ADD_LDB_INT(ERR_COMPARE_FALSE);
4391 ADD_LDB_INT(ERR_COMPARE_TRUE);
4392 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4393 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4394 ADD_LDB_INT(ERR_REFERRAL);
4395 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4396 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4397 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4398 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4399 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4400 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4401 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4402 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4403 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4404 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4405 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4406 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4407 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4408 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4409 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4410 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4411 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4412 ADD_LDB_INT(ERR_BUSY);
4413 ADD_LDB_INT(ERR_UNAVAILABLE);
4414 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4415 ADD_LDB_INT(ERR_LOOP_DETECT);
4416 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4417 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4418 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4419 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4420 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4421 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4422 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4423 ADD_LDB_INT(ERR_OTHER);
4425 ADD_LDB_INT(FLG_RDONLY);
4426 ADD_LDB_INT(FLG_NOSYNC);
4427 ADD_LDB_INT(FLG_RECONNECT);
4428 ADD_LDB_INT(FLG_NOMMAP);
4429 ADD_LDB_INT(FLG_SHOW_BINARY);
4430 ADD_LDB_INT(FLG_ENABLE_TRACING);
4431 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4433 ADD_LDB_INT(PACKING_FORMAT);
4434 ADD_LDB_INT(PACKING_FORMAT_V2);
4436 /* Historical misspelling */
4437 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4439 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4441 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4442 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4444 Py_INCREF(&PyLdb);
4445 Py_INCREF(&PyLdbDn);
4446 Py_INCREF(&PyLdbModule);
4447 Py_INCREF(&PyLdbMessage);
4448 Py_INCREF(&PyLdbMessageElement);
4449 Py_INCREF(&PyLdbTree);
4450 Py_INCREF(&PyLdbResult);
4451 Py_INCREF(&PyLdbControl);
4453 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4454 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4455 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4456 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4457 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4458 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4459 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4461 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4463 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4465 ADD_LDB_STRING(SYNTAX_DN);
4466 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4467 ADD_LDB_STRING(SYNTAX_INTEGER);
4468 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4469 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4470 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4471 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4472 ADD_LDB_STRING(OID_COMPARATOR_AND);
4473 ADD_LDB_STRING(OID_COMPARATOR_OR);
4475 return m;
4478 #if PY_MAJOR_VERSION >= 3
4479 PyMODINIT_FUNC PyInit_ldb(void);
4480 PyMODINIT_FUNC PyInit_ldb(void)
4482 return module_init();
4484 #else
4485 void initldb(void);
4486 void initldb(void)
4488 module_init();
4490 #endif