vfs: restore platform specific POSIX sys_acl_set_file() functions
[Samba.git] / lib / ldb / pyldb.c
blob813cdb0870eb0f62057e1091c4a33d2e0e1d5016
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.get_component_value(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;
1808 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1809 return NULL;
1811 if (!PyLdbMessage_Check(py_msg_old)) {
1812 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1813 return NULL;
1816 if (!PyLdbMessage_Check(py_msg_new)) {
1817 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1818 return NULL;
1821 ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
1822 ldb_ret = ldb_msg_difference(ldb, ldb,
1823 pyldb_Message_AsMessage(py_msg_old),
1824 pyldb_Message_AsMessage(py_msg_new),
1825 &diff);
1826 if (ldb_ret != LDB_SUCCESS) {
1827 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1828 return NULL;
1831 py_ret = PyLdbMessage_FromMessage(diff);
1833 talloc_unlink(ldb, diff);
1835 return py_ret;
1838 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1840 const struct ldb_schema_attribute *a;
1841 struct ldb_val old_val;
1842 struct ldb_val new_val;
1843 TALLOC_CTX *mem_ctx;
1844 PyObject *ret;
1845 char *element_name;
1846 PyObject *val;
1847 Py_ssize_t size;
1848 int result;
1850 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1851 return NULL;
1853 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1854 old_val.length = size;
1856 if (result != 0) {
1857 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1858 return NULL;
1861 a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
1863 if (a == NULL) {
1864 Py_RETURN_NONE;
1867 mem_ctx = talloc_new(NULL);
1868 if (mem_ctx == NULL) {
1869 PyErr_NoMemory();
1870 return NULL;
1873 if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
1874 talloc_free(mem_ctx);
1875 Py_RETURN_NONE;
1878 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1880 talloc_free(mem_ctx);
1882 return ret;
1885 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1887 PyObject *py_base = Py_None;
1888 int scope = LDB_SCOPE_DEFAULT;
1889 char *expr = NULL;
1890 PyObject *py_attrs = Py_None;
1891 PyObject *py_controls = Py_None;
1892 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1893 int ret;
1894 struct ldb_result *res;
1895 struct ldb_request *req;
1896 const char **attrs;
1897 struct ldb_context *ldb_ctx;
1898 struct ldb_control **parsed_controls;
1899 struct ldb_dn *base;
1900 PyObject *py_ret;
1901 TALLOC_CTX *mem_ctx;
1903 /* type "int" rather than "enum" for "scope" is intentional */
1904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1905 discard_const_p(char *, kwnames),
1906 &py_base, &scope, &expr, &py_attrs, &py_controls))
1907 return NULL;
1910 mem_ctx = talloc_new(NULL);
1911 if (mem_ctx == NULL) {
1912 PyErr_NoMemory();
1913 return NULL;
1915 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
1917 if (py_attrs == Py_None) {
1918 attrs = NULL;
1919 } else {
1920 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1921 if (attrs == NULL) {
1922 talloc_free(mem_ctx);
1923 return NULL;
1927 if (py_base == Py_None) {
1928 base = ldb_get_default_basedn(ldb_ctx);
1929 } else {
1930 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1931 talloc_free(mem_ctx);
1932 return NULL;
1936 if (py_controls == Py_None) {
1937 parsed_controls = NULL;
1938 } else {
1939 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1940 if (controls == NULL) {
1941 talloc_free(mem_ctx);
1942 return NULL;
1944 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1945 talloc_free(controls);
1948 res = talloc_zero(mem_ctx, struct ldb_result);
1949 if (res == NULL) {
1950 PyErr_NoMemory();
1951 talloc_free(mem_ctx);
1952 return NULL;
1955 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1956 base,
1957 scope,
1958 expr,
1959 attrs,
1960 parsed_controls,
1961 res,
1962 ldb_search_default_callback,
1963 NULL);
1965 if (ret != LDB_SUCCESS) {
1966 talloc_free(mem_ctx);
1967 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1968 return NULL;
1971 talloc_steal(req, attrs);
1973 ret = ldb_request(ldb_ctx, req);
1975 if (ret == LDB_SUCCESS) {
1976 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1979 if (ret != LDB_SUCCESS) {
1980 talloc_free(mem_ctx);
1981 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1982 return NULL;
1985 py_ret = PyLdbResult_FromResult(res);
1987 talloc_free(mem_ctx);
1989 return py_ret;
1992 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1994 if (reply->py_iter != NULL) {
1995 DLIST_REMOVE(reply->py_iter->state.next, reply);
1996 if (reply->py_iter->state.result == reply) {
1997 reply->py_iter->state.result = NULL;
1999 reply->py_iter = NULL;
2002 if (reply->obj != NULL) {
2003 Py_DECREF(reply->obj);
2004 reply->obj = NULL;
2007 return 0;
2010 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2011 struct ldb_reply *ares)
2013 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2014 struct ldb_result result = { .msgs = NULL };
2015 struct py_ldb_search_iterator_reply *reply = NULL;
2017 if (ares == NULL) {
2018 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2021 if (ares->error != LDB_SUCCESS) {
2022 int ret = ares->error;
2023 TALLOC_FREE(ares);
2024 return ldb_request_done(req, ret);
2027 reply = talloc_zero(py_iter->mem_ctx,
2028 struct py_ldb_search_iterator_reply);
2029 if (reply == NULL) {
2030 TALLOC_FREE(ares);
2031 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2033 reply->py_iter = py_iter;
2034 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2036 switch (ares->type) {
2037 case LDB_REPLY_ENTRY:
2038 reply->obj = PyLdbMessage_FromMessage(ares->message);
2039 if (reply->obj == NULL) {
2040 TALLOC_FREE(ares);
2041 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2043 DLIST_ADD_END(py_iter->state.next, reply);
2044 TALLOC_FREE(ares);
2045 return LDB_SUCCESS;
2047 case LDB_REPLY_REFERRAL:
2048 reply->obj = PyUnicode_FromString(ares->referral);
2049 if (reply->obj == NULL) {
2050 TALLOC_FREE(ares);
2051 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2053 DLIST_ADD_END(py_iter->state.next, reply);
2054 TALLOC_FREE(ares);
2055 return LDB_SUCCESS;
2057 case LDB_REPLY_DONE:
2058 result = (struct ldb_result) { .controls = ares->controls };
2059 reply->obj = PyLdbResult_FromResult(&result);
2060 if (reply->obj == NULL) {
2061 TALLOC_FREE(ares);
2062 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2064 py_iter->state.result = reply;
2065 TALLOC_FREE(ares);
2066 return ldb_request_done(req, LDB_SUCCESS);
2069 TALLOC_FREE(ares);
2070 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2073 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2075 PyObject *py_base = Py_None;
2076 int scope = LDB_SCOPE_DEFAULT;
2077 int timeout = 0;
2078 char *expr = NULL;
2079 PyObject *py_attrs = Py_None;
2080 PyObject *py_controls = Py_None;
2081 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2082 int ret;
2083 const char **attrs;
2084 struct ldb_context *ldb_ctx;
2085 struct ldb_control **parsed_controls;
2086 struct ldb_dn *base;
2087 PyLdbSearchIteratorObject *py_iter;
2089 /* type "int" rather than "enum" for "scope" is intentional */
2090 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2091 discard_const_p(char *, kwnames),
2092 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2093 return NULL;
2095 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2096 if (py_iter == NULL) {
2097 PyErr_NoMemory();
2098 return NULL;
2100 py_iter->ldb = self;
2101 Py_INCREF(self);
2102 ZERO_STRUCT(py_iter->state);
2103 py_iter->mem_ctx = talloc_new(NULL);
2104 if (py_iter->mem_ctx == NULL) {
2105 Py_DECREF(py_iter);
2106 PyErr_NoMemory();
2107 return NULL;
2110 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2112 if (py_attrs == Py_None) {
2113 attrs = NULL;
2114 } else {
2115 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2116 if (attrs == NULL) {
2117 Py_DECREF(py_iter);
2118 PyErr_NoMemory();
2119 return NULL;
2123 if (py_base == Py_None) {
2124 base = ldb_get_default_basedn(ldb_ctx);
2125 } else {
2126 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2127 Py_DECREF(py_iter);
2128 PyErr_NoMemory();
2129 return NULL;
2133 if (py_controls == Py_None) {
2134 parsed_controls = NULL;
2135 } else {
2136 const char **controls = NULL;
2138 controls = PyList_AsStrList(py_iter->mem_ctx,
2139 py_controls, "controls");
2140 if (controls == NULL) {
2141 Py_DECREF(py_iter);
2142 PyErr_NoMemory();
2143 return NULL;
2146 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2147 py_iter->mem_ctx,
2148 controls);
2149 if (controls[0] != NULL && parsed_controls == NULL) {
2150 Py_DECREF(py_iter);
2151 PyErr_NoMemory();
2152 return NULL;
2154 talloc_free(controls);
2157 ret = ldb_build_search_req(&py_iter->state.req,
2158 ldb_ctx,
2159 py_iter->mem_ctx,
2160 base,
2161 scope,
2162 expr,
2163 attrs,
2164 parsed_controls,
2165 py_iter,
2166 py_ldb_search_iterator_callback,
2167 NULL);
2168 if (ret != LDB_SUCCESS) {
2169 Py_DECREF(py_iter);
2170 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2171 return NULL;
2174 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2176 ret = ldb_request(ldb_ctx, py_iter->state.req);
2177 if (ret != LDB_SUCCESS) {
2178 Py_DECREF(py_iter);
2179 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2180 return NULL;
2183 return (PyObject *)py_iter;
2186 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2188 char *name;
2189 void *data;
2191 if (!PyArg_ParseTuple(args, "s", &name))
2192 return NULL;
2194 data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
2196 if (data == NULL)
2197 Py_RETURN_NONE;
2199 /* FIXME: More interpretation */
2201 Py_RETURN_TRUE;
2204 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2206 char *name;
2207 PyObject *data;
2209 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2210 return NULL;
2212 /* FIXME: More interpretation */
2214 ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
2216 Py_RETURN_NONE;
2219 static PyObject *py_ldb_modules(PyLdbObject *self,
2220 PyObject *Py_UNUSED(ignored))
2222 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2223 PyObject *ret = PyList_New(0);
2224 struct ldb_module *mod;
2226 if (ret == NULL) {
2227 return PyErr_NoMemory();
2229 for (mod = ldb->modules; mod; mod = mod->next) {
2230 PyObject *item = PyLdbModule_FromModule(mod);
2231 int res = 0;
2232 if (item == NULL) {
2233 PyErr_SetString(PyExc_RuntimeError,
2234 "Failed to load LdbModule");
2235 Py_CLEAR(ret);
2236 return NULL;
2238 res = PyList_Append(ret, item);
2239 Py_CLEAR(item);
2240 if (res == -1) {
2241 Py_CLEAR(ret);
2242 return NULL;
2246 return ret;
2249 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2251 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2252 int type, ret;
2253 uint64_t value;
2255 if (!PyArg_ParseTuple(args, "i", &type))
2256 return NULL;
2258 /* FIXME: More interpretation */
2260 ret = ldb_sequence_number(ldb, type, &value);
2262 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2264 return PyLong_FromLongLong(value);
2268 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2269 .name = "TEST",
2270 .read_fn = ldb_handler_copy,
2271 .write_clear_fn = ldb_handler_copy,
2272 .write_hex_fn = ldb_handler_copy,
2275 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
2276 PyObject *Py_UNUSED(ignored))
2278 struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
2279 int ret;
2281 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2283 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2285 Py_RETURN_NONE;
2289 static PyMethodDef py_ldb_methods[] = {
2290 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2291 "S.set_debug(callback) -> None\n"
2292 "Set callback for LDB debug messages.\n"
2293 "The callback should accept a debug level and debug text." },
2294 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2295 "S.set_create_perms(mode) -> None\n"
2296 "Set mode to use when creating new LDB files." },
2297 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2298 "S.set_modules_dir(path) -> None\n"
2299 "Set path LDB should search for modules" },
2300 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2301 "S.transaction_start() -> None\n"
2302 "Start a new transaction." },
2303 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2304 "S.transaction_prepare_commit() -> None\n"
2305 "prepare to commit a new transaction (2-stage commit)." },
2306 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2307 "S.transaction_commit() -> None\n"
2308 "commit a new transaction." },
2309 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2310 "S.transaction_cancel() -> None\n"
2311 "cancel a new transaction." },
2312 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2313 NULL },
2314 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2315 NULL },
2316 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2317 NULL },
2318 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2319 NULL },
2320 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2321 NULL },
2322 { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
2323 METH_VARARGS|METH_KEYWORDS,
2324 "S.connect(url, flags=0, options=None) -> None\n"
2325 "Connect to a LDB URL." },
2326 { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
2327 METH_VARARGS|METH_KEYWORDS,
2328 "S.modify(message, controls=None, validate=False) -> None\n"
2329 "Modify an entry." },
2330 { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
2331 METH_VARARGS|METH_KEYWORDS,
2332 "S.add(message, controls=None) -> None\n"
2333 "Add an entry." },
2334 { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
2335 METH_VARARGS|METH_KEYWORDS,
2336 "S.delete(dn, controls=None) -> None\n"
2337 "Remove an entry." },
2338 { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
2339 METH_VARARGS|METH_KEYWORDS,
2340 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2341 "Rename an entry." },
2342 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
2343 METH_VARARGS|METH_KEYWORDS,
2344 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2345 "Search in a database.\n"
2346 "\n"
2347 ":param base: Optional base DN to search\n"
2348 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2349 ":param expression: Optional search expression\n"
2350 ":param attrs: Attributes to return (defaults to all)\n"
2351 ":param controls: Optional list of controls\n"
2352 ":return: ldb.Result object\n"
2354 { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
2355 py_ldb_search_iterator),
2356 METH_VARARGS|METH_KEYWORDS,
2357 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2358 "Search in a database.\n"
2359 "\n"
2360 ":param base: Optional base DN to search\n"
2361 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2362 ":param expression: Optional search expression\n"
2363 ":param attrs: Attributes to return (defaults to all)\n"
2364 ":param controls: Optional list of controls\n"
2365 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2366 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2368 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2369 NULL },
2370 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2371 NULL },
2372 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2373 NULL },
2374 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2375 "S.parse_ldif(ldif) -> iter(messages)\n"
2376 "Parse a string formatted using LDIF." },
2377 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2378 "S.write_ldif(message, changetype) -> ldif\n"
2379 "Print the message as a string formatted using LDIF." },
2380 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2381 "S.msg_diff(Message) -> Message\n"
2382 "Return an LDB Message of the difference between two Message objects." },
2383 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2384 "S.get_opaque(name) -> value\n"
2385 "Get an opaque value set on this LDB connection. \n"
2386 ":note: The returned value may not be useful in Python."
2388 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2389 "S.set_opaque(name, value) -> None\n"
2390 "Set an opaque value on this LDB connection. \n"
2391 ":note: Passing incorrect values may cause crashes." },
2392 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2393 "S.modules() -> list\n"
2394 "Return the list of modules on this LDB connection " },
2395 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2396 "S.sequence_number(type) -> value\n"
2397 "Return the value of the sequence according to the requested type" },
2398 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2399 "S._register_test_extensions() -> None\n"
2400 "Register internal extensions used in testing" },
2401 {0},
2404 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2406 PyLdbModuleObject *ret;
2408 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2409 if (ret == NULL) {
2410 PyErr_NoMemory();
2411 return NULL;
2413 ret->mem_ctx = talloc_new(NULL);
2414 ret->mod = talloc_reference(ret->mem_ctx, mod);
2415 return (PyObject *)ret;
2418 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2420 struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
2421 if (mod == NULL) {
2422 Py_RETURN_NONE;
2424 return PyLdbModule_FromModule(mod);
2427 static PyGetSetDef py_ldb_getset[] = {
2429 .name = discard_const_p(char, "firstmodule"),
2430 .get = (getter)py_ldb_get_firstmodule,
2432 { .name = NULL },
2435 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2437 struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
2438 struct ldb_dn *dn;
2439 struct ldb_result *result;
2440 unsigned int count;
2441 int ret;
2443 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2444 return -1;
2447 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2448 NULL);
2449 if (ret != LDB_SUCCESS) {
2450 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2451 return -1;
2454 count = result->count;
2456 talloc_free(result);
2458 if (count > 1) {
2459 PyErr_Format(PyExc_RuntimeError,
2460 "Searching for [%s] dn gave %u results!",
2461 ldb_dn_get_linearized(dn),
2462 count);
2463 return -1;
2466 return count;
2469 static PySequenceMethods py_ldb_seq = {
2470 .sq_contains = (objobjproc)py_ldb_contains,
2473 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2475 PyLdbObject *ret;
2477 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2478 if (ret == NULL) {
2479 PyErr_NoMemory();
2480 return NULL;
2482 ret->mem_ctx = talloc_new(NULL);
2483 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2484 return (PyObject *)ret;
2487 static void py_ldb_dealloc(PyLdbObject *self)
2489 talloc_free(self->mem_ctx);
2490 Py_TYPE(self)->tp_free(self);
2493 static PyTypeObject PyLdb = {
2494 .tp_name = "ldb.Ldb",
2495 .tp_methods = py_ldb_methods,
2496 .tp_repr = (reprfunc)py_ldb_repr,
2497 .tp_new = py_ldb_new,
2498 .tp_init = (initproc)py_ldb_init,
2499 .tp_dealloc = (destructor)py_ldb_dealloc,
2500 .tp_getset = py_ldb_getset,
2501 .tp_getattro = PyObject_GenericGetAttr,
2502 .tp_basicsize = sizeof(PyLdbObject),
2503 .tp_doc = "Connection to a LDB database.",
2504 .tp_as_sequence = &py_ldb_seq,
2505 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2508 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2510 talloc_free(self->mem_ctx);
2511 Py_DECREF(self->msgs);
2512 Py_DECREF(self->referals);
2513 Py_DECREF(self->controls);
2514 Py_TYPE(self)->tp_free(self);
2517 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2519 Py_INCREF(self->msgs);
2520 return self->msgs;
2523 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2525 Py_INCREF(self->controls);
2526 return self->controls;
2529 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2531 Py_INCREF(self->referals);
2532 return self->referals;
2535 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2537 Py_ssize_t size;
2538 if (self->msgs == NULL) {
2539 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2540 return NULL;
2542 size = PyList_Size(self->msgs);
2543 return PyLong_FromLong(size);
2546 static PyGetSetDef py_ldb_result_getset[] = {
2548 .name = discard_const_p(char, "controls"),
2549 .get = (getter)py_ldb_result_get_controls,
2552 .name = discard_const_p(char, "msgs"),
2553 .get = (getter)py_ldb_result_get_msgs,
2556 .name = discard_const_p(char, "referals"),
2557 .get = (getter)py_ldb_result_get_referals,
2560 .name = discard_const_p(char, "count"),
2561 .get = (getter)py_ldb_result_get_count,
2563 { .name = NULL },
2566 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2568 return PyObject_GetIter(self->msgs);
2571 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2573 return PySequence_Size(self->msgs);
2576 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2578 return PySequence_GetItem(self->msgs, idx);
2581 static PySequenceMethods py_ldb_result_seq = {
2582 .sq_length = (lenfunc)py_ldb_result_len,
2583 .sq_item = (ssizeargfunc)py_ldb_result_find,
2586 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2588 return PyUnicode_FromString("<ldb result>");
2592 static PyTypeObject PyLdbResult = {
2593 .tp_name = "ldb.Result",
2594 .tp_repr = (reprfunc)py_ldb_result_repr,
2595 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2596 .tp_iter = (getiterfunc)py_ldb_result_iter,
2597 .tp_getset = py_ldb_result_getset,
2598 .tp_getattro = PyObject_GenericGetAttr,
2599 .tp_basicsize = sizeof(PyLdbResultObject),
2600 .tp_as_sequence = &py_ldb_result_seq,
2601 .tp_doc = "LDB result.",
2602 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2605 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2607 Py_XDECREF(self->state.exception);
2608 TALLOC_FREE(self->mem_ctx);
2609 ZERO_STRUCT(self->state);
2610 Py_DECREF(self->ldb);
2611 Py_TYPE(self)->tp_free(self);
2614 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2616 PyObject *py_ret = NULL;
2618 if (self->state.req == NULL) {
2619 PyErr_SetString(PyExc_RuntimeError,
2620 "ldb.SearchIterator request already finished");
2621 return NULL;
2625 * TODO: do we want a non-blocking mode?
2626 * In future we may add an optional 'nonblocking'
2627 * argument to search_iterator().
2629 * For now we keep it simple and wait for at
2630 * least one reply.
2633 while (self->state.next == NULL) {
2634 int ret;
2636 if (self->state.result != NULL) {
2638 * We (already) got a final result from the server.
2640 * We stop the iteration and let
2641 * py_ldb_search_iterator_result() will deliver
2642 * the result details.
2644 TALLOC_FREE(self->state.req);
2645 PyErr_SetNone(PyExc_StopIteration);
2646 return NULL;
2649 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2650 if (ret != LDB_SUCCESS) {
2651 struct ldb_context *ldb_ctx;
2652 TALLOC_FREE(self->state.req);
2653 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
2655 * We stop the iteration and let
2656 * py_ldb_search_iterator_result() will deliver
2657 * the exception.
2659 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2660 ret, ldb_errstring(ldb_ctx));
2661 PyErr_SetNone(PyExc_StopIteration);
2662 return NULL;
2666 py_ret = self->state.next->obj;
2667 self->state.next->obj = NULL;
2668 /* no TALLOC_FREE() as self->state.next is a list */
2669 talloc_free(self->state.next);
2670 return py_ret;
2673 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
2674 PyObject *Py_UNUSED(ignored))
2676 PyObject *py_ret = NULL;
2678 if (self->state.req != NULL) {
2679 PyErr_SetString(PyExc_RuntimeError,
2680 "ldb.SearchIterator request running");
2681 return NULL;
2684 if (self->state.next != NULL) {
2685 PyErr_SetString(PyExc_RuntimeError,
2686 "ldb.SearchIterator not fully consumed.");
2687 return NULL;
2690 if (self->state.exception != NULL) {
2691 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2692 self->state.exception = NULL;
2693 return NULL;
2696 if (self->state.result == NULL) {
2697 PyErr_SetString(PyExc_RuntimeError,
2698 "ldb.SearchIterator result already consumed");
2699 return NULL;
2702 py_ret = self->state.result->obj;
2703 self->state.result->obj = NULL;
2704 TALLOC_FREE(self->state.result);
2705 return py_ret;
2708 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
2709 PyObject *Py_UNUSED(ignored))
2711 if (self->state.req == NULL) {
2712 PyErr_SetString(PyExc_RuntimeError,
2713 "ldb.SearchIterator request already finished");
2714 return NULL;
2717 Py_XDECREF(self->state.exception);
2718 TALLOC_FREE(self->mem_ctx);
2719 ZERO_STRUCT(self->state);
2720 Py_RETURN_NONE;
2723 static PyMethodDef py_ldb_search_iterator_methods[] = {
2724 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2725 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2726 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2727 "S.abandon()\n" },
2731 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2733 return PyUnicode_FromString("<ldb search iterator>");
2736 static PyTypeObject PyLdbSearchIterator = {
2737 .tp_name = "ldb.SearchIterator",
2738 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2739 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2740 .tp_iter = PyObject_SelfIter,
2741 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2742 .tp_methods = py_ldb_search_iterator_methods,
2743 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2744 .tp_doc = "LDB search_iterator.",
2745 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2748 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2750 return PyUnicode_FromFormat("<ldb module '%s'>",
2751 pyldb_Module_AsModule(self)->ops->name);
2754 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2756 return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
2759 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
2760 PyObject *Py_UNUSED(ignored))
2762 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2763 Py_RETURN_NONE;
2766 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
2767 PyObject *Py_UNUSED(ignored))
2769 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2770 Py_RETURN_NONE;
2773 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
2774 PyObject *Py_UNUSED(ignored))
2776 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2777 Py_RETURN_NONE;
2780 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2782 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2783 int ret, scope;
2784 struct ldb_request *req;
2785 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2786 struct ldb_module *mod;
2787 const char * const*attrs;
2789 /* type "int" rather than "enum" for "scope" is intentional */
2790 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2791 discard_const_p(char *, kwnames),
2792 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2793 return NULL;
2795 mod = self->mod;
2797 if (py_attrs == Py_None) {
2798 attrs = NULL;
2799 } else {
2800 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2801 if (attrs == NULL)
2802 return NULL;
2805 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
2806 scope, NULL /* expr */, attrs,
2807 NULL /* controls */, NULL, NULL, NULL);
2809 talloc_steal(req, attrs);
2811 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2813 req->op.search.res = NULL;
2815 ret = mod->ops->search(mod, req);
2817 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2819 py_ret = PyLdbResult_FromResult(req->op.search.res);
2821 talloc_free(req);
2823 return py_ret;
2827 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2829 struct ldb_request *req;
2830 PyObject *py_message;
2831 int ret;
2832 struct ldb_module *mod;
2834 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2835 return NULL;
2837 req = talloc_zero(NULL, struct ldb_request);
2838 req->operation = LDB_ADD;
2839 req->op.add.message = pyldb_Message_AsMessage(py_message);
2841 mod = pyldb_Module_AsModule(self);
2842 ret = mod->ops->add(mod, req);
2844 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2846 Py_RETURN_NONE;
2849 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2851 int ret;
2852 struct ldb_request *req;
2853 PyObject *py_message;
2854 struct ldb_module *mod;
2856 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2857 return NULL;
2859 req = talloc_zero(NULL, struct ldb_request);
2860 req->operation = LDB_MODIFY;
2861 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2863 mod = pyldb_Module_AsModule(self);
2864 ret = mod->ops->modify(mod, req);
2866 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2868 Py_RETURN_NONE;
2871 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2873 int ret;
2874 struct ldb_request *req;
2875 PyObject *py_dn;
2877 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2878 return NULL;
2880 req = talloc_zero(NULL, struct ldb_request);
2881 req->operation = LDB_DELETE;
2882 req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
2884 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2886 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2888 Py_RETURN_NONE;
2891 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2893 int ret;
2894 struct ldb_request *req;
2895 PyObject *py_dn1, *py_dn2;
2897 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2898 return NULL;
2900 req = talloc_zero(NULL, struct ldb_request);
2902 req->operation = LDB_RENAME;
2903 req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
2904 req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
2906 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2908 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2910 Py_RETURN_NONE;
2913 static PyMethodDef py_ldb_module_methods[] = {
2914 { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
2915 METH_VARARGS|METH_KEYWORDS, NULL },
2916 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2917 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2918 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2919 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2920 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2921 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2922 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2923 {0},
2926 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2928 talloc_free(self->mem_ctx);
2929 PyObject_Del(self);
2932 static PyTypeObject PyLdbModule = {
2933 .tp_name = "ldb.LdbModule",
2934 .tp_methods = py_ldb_module_methods,
2935 .tp_repr = (reprfunc)py_ldb_module_repr,
2936 .tp_str = (reprfunc)py_ldb_module_str,
2937 .tp_basicsize = sizeof(PyLdbModuleObject),
2938 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2939 .tp_flags = Py_TPFLAGS_DEFAULT,
2940 .tp_doc = "LDB module (extension)",
2945 * Create a ldb_message_element from a Python object.
2947 * This will accept any sequence objects that contains strings, or
2948 * a string object.
2950 * A reference to set_obj will be borrowed.
2952 * @param mem_ctx Memory context
2953 * @param set_obj Python object to convert
2954 * @param flags ldb_message_element flags to set
2955 * @param attr_name Name of the attribute
2956 * @return New ldb_message_element, allocated as child of mem_ctx
2958 static struct ldb_message_element *PyObject_AsMessageElement(
2959 TALLOC_CTX *mem_ctx,
2960 PyObject *set_obj,
2961 unsigned int flags,
2962 const char *attr_name)
2964 struct ldb_message_element *me;
2965 const char *msg = NULL;
2966 Py_ssize_t size;
2967 int result;
2969 if (pyldb_MessageElement_Check(set_obj)) {
2970 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2971 /* We have to talloc_reference() the memory context, not the pointer
2972 * which may not actually be it's own context */
2973 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2974 return pyldb_MessageElement_AsMessageElement(set_obj);
2976 return NULL;
2979 me = talloc(mem_ctx, struct ldb_message_element);
2980 if (me == NULL) {
2981 PyErr_NoMemory();
2982 return NULL;
2985 me->name = talloc_strdup(me, attr_name);
2986 me->flags = flags;
2987 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2988 me->num_values = 1;
2989 me->values = talloc_array(me, struct ldb_val, me->num_values);
2990 if (PyBytes_Check(set_obj)) {
2991 char *_msg = NULL;
2992 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2993 if (result != 0) {
2994 talloc_free(me);
2995 return NULL;
2997 msg = _msg;
2998 } else {
2999 msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
3000 if (msg == NULL) {
3001 talloc_free(me);
3002 return NULL;
3005 me->values[0].data = talloc_memdup(me,
3006 (const uint8_t *)msg,
3007 size+1);
3008 me->values[0].length = size;
3009 } else if (PySequence_Check(set_obj)) {
3010 Py_ssize_t i;
3011 me->num_values = PySequence_Size(set_obj);
3012 me->values = talloc_array(me, struct ldb_val, me->num_values);
3013 for (i = 0; i < me->num_values; i++) {
3014 PyObject *obj = PySequence_GetItem(set_obj, i);
3015 if (PyBytes_Check(obj)) {
3016 char *_msg = NULL;
3017 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
3018 if (result != 0) {
3019 talloc_free(me);
3020 return NULL;
3022 msg = _msg;
3023 } else if (PyUnicode_Check(obj)) {
3024 msg = PyUnicode_AsUTF8AndSize(obj, &size);
3025 if (msg == NULL) {
3026 talloc_free(me);
3027 return NULL;
3029 } else {
3030 PyErr_Format(PyExc_TypeError,
3031 "Expected string as element %zd in list", i);
3032 talloc_free(me);
3033 return NULL;
3035 me->values[i].data = talloc_memdup(me,
3036 (const uint8_t *)msg,
3037 size+1);
3038 me->values[i].length = size;
3040 } else {
3041 PyErr_Format(PyExc_TypeError,
3042 "String or List type expected for '%s' attribute", attr_name);
3043 talloc_free(me);
3044 me = NULL;
3047 return me;
3051 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3052 struct ldb_message_element *me)
3054 Py_ssize_t i;
3055 PyObject *result;
3057 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3058 result = PyList_New(me->num_values);
3060 for (i = 0; i < me->num_values; i++) {
3061 PyList_SetItem(result, i,
3062 PyObject_FromLdbValue(&me->values[i]));
3065 return result;
3068 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3070 unsigned int i;
3071 if (!PyArg_ParseTuple(args, "I", &i))
3072 return NULL;
3073 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3074 Py_RETURN_NONE;
3076 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3079 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3081 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3082 return PyLong_FromLong(el->flags);
3085 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3087 unsigned int flags;
3088 struct ldb_message_element *el;
3089 if (!PyArg_ParseTuple(args, "I", &flags))
3090 return NULL;
3092 el = pyldb_MessageElement_AsMessageElement(self);
3093 el->flags = flags;
3094 Py_RETURN_NONE;
3097 static PyMethodDef py_ldb_msg_element_methods[] = {
3098 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3099 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3100 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3101 {0},
3104 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3106 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3109 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3111 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3112 if (idx < 0 || idx >= el->num_values) {
3113 PyErr_SetString(PyExc_IndexError, "Out of range");
3114 return NULL;
3116 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3119 static PySequenceMethods py_ldb_msg_element_seq = {
3120 .sq_length = (lenfunc)py_ldb_msg_element_len,
3121 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3124 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3126 int ret;
3127 if (!pyldb_MessageElement_Check(other)) {
3128 Py_INCREF(Py_NotImplemented);
3129 return Py_NotImplemented;
3131 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3132 pyldb_MessageElement_AsMessageElement(other));
3133 return richcmp(ret, op);
3136 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3138 PyObject *el = ldb_msg_element_to_set(NULL,
3139 pyldb_MessageElement_AsMessageElement(self));
3140 PyObject *ret = PyObject_GetIter(el);
3141 Py_DECREF(el);
3142 return ret;
3145 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3147 PyLdbMessageElementObject *ret;
3148 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3149 if (ret == NULL) {
3150 PyErr_NoMemory();
3151 return NULL;
3153 ret->mem_ctx = talloc_new(NULL);
3154 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3155 PyErr_NoMemory();
3156 return NULL;
3158 ret->el = el;
3159 return (PyObject *)ret;
3162 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3164 PyObject *py_elements = NULL;
3165 struct ldb_message_element *el;
3166 unsigned int flags = 0;
3167 char *name = NULL;
3168 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3169 PyLdbMessageElementObject *ret;
3170 TALLOC_CTX *mem_ctx;
3171 const char *msg = NULL;
3172 Py_ssize_t size;
3173 int result;
3175 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3176 discard_const_p(char *, kwnames),
3177 &py_elements, &flags, &name))
3178 return NULL;
3180 mem_ctx = talloc_new(NULL);
3181 if (mem_ctx == NULL) {
3182 PyErr_NoMemory();
3183 return NULL;
3186 el = talloc_zero(mem_ctx, struct ldb_message_element);
3187 if (el == NULL) {
3188 PyErr_NoMemory();
3189 talloc_free(mem_ctx);
3190 return NULL;
3193 if (py_elements != NULL) {
3194 Py_ssize_t i;
3195 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3196 char *_msg = NULL;
3197 el->num_values = 1;
3198 el->values = talloc_array(el, struct ldb_val, 1);
3199 if (el->values == NULL) {
3200 talloc_free(mem_ctx);
3201 PyErr_NoMemory();
3202 return NULL;
3204 if (PyBytes_Check(py_elements)) {
3205 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3206 msg = _msg;
3207 } else {
3208 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
3209 result = (msg == NULL) ? -1 : 0;
3211 if (result != 0) {
3212 talloc_free(mem_ctx);
3213 return NULL;
3215 el->values[0].data = talloc_memdup(el->values,
3216 (const uint8_t *)msg, size + 1);
3217 el->values[0].length = size;
3218 } else if (PySequence_Check(py_elements)) {
3219 el->num_values = PySequence_Size(py_elements);
3220 el->values = talloc_array(el, struct ldb_val, el->num_values);
3221 if (el->values == NULL) {
3222 talloc_free(mem_ctx);
3223 PyErr_NoMemory();
3224 return NULL;
3226 for (i = 0; i < el->num_values; i++) {
3227 PyObject *item = PySequence_GetItem(py_elements, i);
3228 if (item == NULL) {
3229 talloc_free(mem_ctx);
3230 return NULL;
3232 if (PyBytes_Check(item)) {
3233 char *_msg = NULL;
3234 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3235 msg = _msg;
3236 } else if (PyUnicode_Check(item)) {
3237 msg = PyUnicode_AsUTF8AndSize(item, &size);
3238 result = (msg == NULL) ? -1 : 0;
3239 } else {
3240 PyErr_Format(PyExc_TypeError,
3241 "Expected string as element %zd in list", i);
3242 result = -1;
3244 if (result != 0) {
3245 talloc_free(mem_ctx);
3246 return NULL;
3248 el->values[i].data = talloc_memdup(el,
3249 (const uint8_t *)msg, size+1);
3250 el->values[i].length = size;
3252 } else {
3253 PyErr_SetString(PyExc_TypeError,
3254 "Expected string or list");
3255 talloc_free(mem_ctx);
3256 return NULL;
3260 el->flags = flags;
3261 el->name = talloc_strdup(el, name);
3263 ret = PyObject_New(PyLdbMessageElementObject, type);
3264 if (ret == NULL) {
3265 talloc_free(mem_ctx);
3266 return NULL;
3269 ret->mem_ctx = mem_ctx;
3270 ret->el = el;
3271 return (PyObject *)ret;
3274 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3276 char *element_str = NULL;
3277 Py_ssize_t i;
3278 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3279 PyObject *ret, *repr;
3281 for (i = 0; i < el->num_values; i++) {
3282 PyObject *o = py_ldb_msg_element_find(self, i);
3283 repr = PyObject_Repr(o);
3284 if (element_str == NULL)
3285 element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
3286 else
3287 element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
3288 Py_DECREF(repr);
3291 if (element_str != NULL) {
3292 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
3293 talloc_free(element_str);
3294 } else {
3295 ret = PyUnicode_FromString("MessageElement([])");
3298 return ret;
3301 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3303 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3305 if (el->num_values == 1)
3306 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3307 else
3308 Py_RETURN_NONE;
3311 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3313 talloc_free(self->mem_ctx);
3314 PyObject_Del(self);
3317 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3319 return wrap_text("MessageElementTextWrapper", self);
3322 static PyGetSetDef py_ldb_msg_element_getset[] = {
3324 .name = discard_const_p(char, "text"),
3325 .get = (getter)py_ldb_msg_element_get_text,
3327 { .name = NULL }
3330 static PyTypeObject PyLdbMessageElement = {
3331 .tp_name = "ldb.MessageElement",
3332 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3333 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3334 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3335 .tp_str = (reprfunc)py_ldb_msg_element_str,
3336 .tp_methods = py_ldb_msg_element_methods,
3337 .tp_getset = py_ldb_msg_element_getset,
3338 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3339 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3340 .tp_as_sequence = &py_ldb_msg_element_seq,
3341 .tp_new = py_ldb_msg_element_new,
3342 .tp_flags = Py_TPFLAGS_DEFAULT,
3343 .tp_doc = "An element of a Message",
3347 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3349 PyObject *py_ldb;
3350 PyObject *py_dict;
3351 PyObject *py_ret;
3352 struct ldb_message *msg;
3353 struct ldb_context *ldb_ctx;
3354 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3356 if (!PyArg_ParseTuple(args, "O!O!|I",
3357 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3358 &mod_flags)) {
3359 return NULL;
3362 if (!PyLdb_Check(py_ldb)) {
3363 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3364 return NULL;
3367 /* mask only flags we are going to use */
3368 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3369 if (!mod_flags) {
3370 PyErr_SetString(PyExc_ValueError,
3371 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3372 " expected as mod_flag value");
3373 return NULL;
3376 ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
3378 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3379 if (!msg) {
3380 return NULL;
3383 py_ret = PyLdbMessage_FromMessage(msg);
3385 talloc_unlink(ldb_ctx, msg);
3387 return py_ret;
3390 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3392 char *name;
3393 if (!PyArg_ParseTuple(args, "s", &name))
3394 return NULL;
3396 ldb_msg_remove_attr(self->msg, name);
3398 Py_RETURN_NONE;
3401 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
3402 PyObject *Py_UNUSED(ignored))
3404 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3405 Py_ssize_t i, j = 0;
3406 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3407 if (msg->dn != NULL) {
3408 PyList_SetItem(obj, j, PyUnicode_FromString("dn"));
3409 j++;
3411 for (i = 0; i < msg->num_elements; i++) {
3412 PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name));
3413 j++;
3415 return obj;
3418 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3420 struct ldb_message_element *el;
3421 const char *name;
3422 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3423 name = PyUnicode_AsUTF8(py_name);
3424 if (name == NULL) {
3425 PyErr_SetNone(PyExc_TypeError);
3426 return NULL;
3428 if (!ldb_attr_cmp(name, "dn"))
3429 return pyldb_Dn_FromDn(msg->dn);
3430 el = ldb_msg_find_element(msg, name);
3431 if (el == NULL) {
3432 return NULL;
3434 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3437 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3439 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3440 if (ret == NULL) {
3441 PyErr_SetString(PyExc_KeyError, "No such element");
3442 return NULL;
3444 return ret;
3447 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3449 PyObject *def = NULL;
3450 const char *kwnames[] = { "name", "default", "idx", NULL };
3451 const char *name = NULL;
3452 int idx = -1;
3453 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3454 struct ldb_message_element *el;
3456 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3457 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3458 return NULL;
3461 if (strcasecmp(name, "dn") == 0) {
3462 return pyldb_Dn_FromDn(msg->dn);
3465 el = ldb_msg_find_element(msg, name);
3467 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3468 if (def != NULL) {
3469 Py_INCREF(def);
3470 return def;
3472 Py_RETURN_NONE;
3475 if (idx == -1) {
3476 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3479 return PyObject_FromLdbValue(&el->values[idx]);
3482 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
3483 PyObject *Py_UNUSED(ignored))
3485 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3486 Py_ssize_t i, j = 0;
3487 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3488 if (l == NULL) {
3489 return PyErr_NoMemory();
3491 if (msg->dn != NULL) {
3492 PyObject *value = NULL;
3493 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3494 int res = 0;
3495 value = Py_BuildValue("(sO)", "dn", obj);
3496 Py_CLEAR(obj);
3497 if (value == NULL) {
3498 Py_CLEAR(l);
3499 return NULL;
3501 res = PyList_SetItem(l, 0, value);
3502 if (res == -1) {
3503 Py_CLEAR(l);
3504 return NULL;
3506 j++;
3508 for (i = 0; i < msg->num_elements; i++, j++) {
3509 PyObject *value = NULL;
3510 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3511 int res = 0;
3512 Py_CLEAR(py_el);
3513 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3514 if (value == NULL ) {
3515 Py_CLEAR(l);
3516 return NULL;
3518 res = PyList_SetItem(l, 0, value);
3519 if (res == -1) {
3520 Py_CLEAR(l);
3521 return NULL;
3524 return l;
3527 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
3528 PyObject *Py_UNUSED(ignored))
3530 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3531 Py_ssize_t i = 0;
3532 PyObject *l = PyList_New(msg->num_elements);
3533 for (i = 0; i < msg->num_elements; i++) {
3534 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3536 return l;
3539 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3541 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3542 PyLdbMessageElementObject *py_element;
3543 int i, ret;
3544 struct ldb_message_element *el;
3545 struct ldb_message_element *el_new;
3547 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3548 return NULL;
3550 el = py_element->el;
3551 if (el == NULL) {
3552 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3553 return NULL;
3555 if (el->name == NULL) {
3556 PyErr_SetString(PyExc_ValueError,
3557 "The element has no name");
3558 return NULL;
3560 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3561 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3563 /* now deep copy all attribute values */
3564 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3565 if (el_new->values == NULL) {
3566 PyErr_NoMemory();
3567 return NULL;
3569 el_new->num_values = el->num_values;
3571 for (i = 0; i < el->num_values; i++) {
3572 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3573 if (el_new->values[i].data == NULL
3574 && el->values[i].length != 0) {
3575 PyErr_NoMemory();
3576 return NULL;
3580 Py_RETURN_NONE;
3583 static PyMethodDef py_ldb_msg_methods[] = {
3584 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3585 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3586 "Class method to create ldb.Message object from Dictionary.\n"
3587 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3588 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3589 "S.keys() -> list\n\n"
3590 "Return sequence of all attribute names." },
3591 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3592 "S.remove(name)\n\n"
3593 "Remove all entries for attributes with the specified name."},
3594 { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
3595 METH_VARARGS | METH_KEYWORDS,
3596 "msg.get(name,default=None,idx=None) -> string\n"
3597 "idx is the index into the values array\n"
3598 "if idx is None, then a list is returned\n"
3599 "if idx is not None, then the element with that index is returned\n"
3600 "if you pass the special name 'dn' then the DN object is returned\n"},
3601 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3602 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3603 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3604 "S.add(element)\n\n"
3605 "Add an element to this message." },
3606 {0},
3609 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3611 PyObject *list, *iter;
3613 list = py_ldb_msg_keys(self, NULL);
3614 iter = PyObject_GetIter(list);
3615 Py_DECREF(list);
3616 return iter;
3619 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3621 const char *attr_name;
3623 attr_name = PyUnicode_AsUTF8(name);
3624 if (attr_name == NULL) {
3625 PyErr_SetNone(PyExc_TypeError);
3626 return -1;
3629 if (value == NULL) {
3630 /* delitem */
3631 ldb_msg_remove_attr(self->msg, attr_name);
3632 } else {
3633 int ret;
3634 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3635 value, 0, attr_name);
3636 if (el == NULL) {
3637 return -1;
3639 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3640 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3641 if (ret != LDB_SUCCESS) {
3642 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3643 return -1;
3646 return 0;
3649 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3651 return pyldb_Message_AsMessage(self)->num_elements;
3654 static PyMappingMethods py_ldb_msg_mapping = {
3655 .mp_length = (lenfunc)py_ldb_msg_length,
3656 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3657 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3660 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3662 const char * const kwnames[] = { "dn", NULL };
3663 struct ldb_message *ret;
3664 TALLOC_CTX *mem_ctx;
3665 PyObject *pydn = NULL;
3666 PyLdbMessageObject *py_ret;
3668 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3669 discard_const_p(char *, kwnames),
3670 &pydn))
3671 return NULL;
3673 mem_ctx = talloc_new(NULL);
3674 if (mem_ctx == NULL) {
3675 PyErr_NoMemory();
3676 return NULL;
3679 ret = ldb_msg_new(mem_ctx);
3680 if (ret == NULL) {
3681 talloc_free(mem_ctx);
3682 PyErr_NoMemory();
3683 return NULL;
3686 if (pydn != NULL) {
3687 struct ldb_dn *dn;
3688 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3689 talloc_free(mem_ctx);
3690 return NULL;
3692 ret->dn = talloc_reference(ret, dn);
3695 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3696 if (py_ret == NULL) {
3697 PyErr_NoMemory();
3698 talloc_free(mem_ctx);
3699 return NULL;
3702 py_ret->mem_ctx = mem_ctx;
3703 py_ret->msg = ret;
3704 return (PyObject *)py_ret;
3707 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3709 PyLdbMessageObject *ret;
3711 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3712 if (ret == NULL) {
3713 PyErr_NoMemory();
3714 return NULL;
3716 ret->mem_ctx = talloc_new(NULL);
3717 ret->msg = talloc_reference(ret->mem_ctx, msg);
3718 return (PyObject *)ret;
3721 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3723 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3724 return pyldb_Dn_FromDn(msg->dn);
3727 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3729 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3730 if (!pyldb_Dn_Check(value)) {
3731 PyErr_SetString(PyExc_TypeError, "expected dn");
3732 return -1;
3735 msg->dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
3736 return 0;
3739 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3741 return wrap_text("MessageTextWrapper", self);
3744 static PyGetSetDef py_ldb_msg_getset[] = {
3746 .name = discard_const_p(char, "dn"),
3747 .get = (getter)py_ldb_msg_get_dn,
3748 .set = (setter)py_ldb_msg_set_dn,
3751 .name = discard_const_p(char, "text"),
3752 .get = (getter)py_ldb_msg_get_text,
3754 { .name = NULL },
3757 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3759 PyObject *dict = PyDict_New(), *ret, *repr;
3760 if (PyDict_Update(dict, (PyObject *)self) != 0)
3761 return NULL;
3762 repr = PyObject_Repr(dict);
3763 if (repr == NULL) {
3764 Py_DECREF(dict);
3765 return NULL;
3767 ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr));
3768 Py_DECREF(repr);
3769 Py_DECREF(dict);
3770 return ret;
3773 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3775 talloc_free(self->mem_ctx);
3776 PyObject_Del(self);
3779 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3780 PyLdbMessageObject *py_msg2, int op)
3782 struct ldb_message *msg1, *msg2;
3783 unsigned int i;
3784 int ret;
3786 if (!PyLdbMessage_Check(py_msg2)) {
3787 Py_INCREF(Py_NotImplemented);
3788 return Py_NotImplemented;
3791 msg1 = pyldb_Message_AsMessage(py_msg1),
3792 msg2 = pyldb_Message_AsMessage(py_msg2);
3794 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3795 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3796 if (ret != 0) {
3797 return richcmp(ret, op);
3801 ret = msg1->num_elements - msg2->num_elements;
3802 if (ret != 0) {
3803 return richcmp(ret, op);
3806 for (i = 0; i < msg1->num_elements; i++) {
3807 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3808 &msg2->elements[i]);
3809 if (ret != 0) {
3810 return richcmp(ret, op);
3813 ret = ldb_msg_element_compare(&msg1->elements[i],
3814 &msg2->elements[i]);
3815 if (ret != 0) {
3816 return richcmp(ret, op);
3820 return richcmp(0, op);
3823 static PyTypeObject PyLdbMessage = {
3824 .tp_name = "ldb.Message",
3825 .tp_methods = py_ldb_msg_methods,
3826 .tp_getset = py_ldb_msg_getset,
3827 .tp_as_mapping = &py_ldb_msg_mapping,
3828 .tp_basicsize = sizeof(PyLdbMessageObject),
3829 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3830 .tp_new = py_ldb_msg_new,
3831 .tp_repr = (reprfunc)py_ldb_msg_repr,
3832 .tp_flags = Py_TPFLAGS_DEFAULT,
3833 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3834 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3835 .tp_doc = "A LDB Message",
3838 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3840 PyLdbTreeObject *ret;
3842 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3843 if (ret == NULL) {
3844 PyErr_NoMemory();
3845 return NULL;
3848 ret->mem_ctx = talloc_new(NULL);
3849 ret->tree = talloc_reference(ret->mem_ctx, tree);
3850 return (PyObject *)ret;
3853 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3855 talloc_free(self->mem_ctx);
3856 PyObject_Del(self);
3859 static PyTypeObject PyLdbTree = {
3860 .tp_name = "ldb.Tree",
3861 .tp_basicsize = sizeof(PyLdbTreeObject),
3862 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3863 .tp_flags = Py_TPFLAGS_DEFAULT,
3864 .tp_doc = "A search tree",
3867 /* Ldb_module */
3868 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3870 PyObject *py_ldb = (PyObject *)mod->private_data;
3871 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3873 py_base = pyldb_Dn_FromDn(req->op.search.base);
3875 if (py_base == NULL)
3876 return LDB_ERR_OPERATIONS_ERROR;
3878 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3880 if (py_tree == NULL)
3881 return LDB_ERR_OPERATIONS_ERROR;
3883 if (req->op.search.attrs == NULL) {
3884 py_attrs = Py_None;
3885 } else {
3886 int i, len;
3887 for (len = 0; req->op.search.attrs[len]; len++);
3888 py_attrs = PyList_New(len);
3889 for (i = 0; i < len; i++)
3890 PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i]));
3893 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3894 discard_const_p(char, "OiOO"),
3895 py_base, req->op.search.scope, py_tree, py_attrs);
3897 Py_DECREF(py_attrs);
3898 Py_DECREF(py_tree);
3899 Py_DECREF(py_base);
3901 if (py_result == NULL) {
3902 return LDB_ERR_PYTHON_EXCEPTION;
3905 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3906 if (req->op.search.res == NULL) {
3907 return LDB_ERR_PYTHON_EXCEPTION;
3910 Py_DECREF(py_result);
3912 return LDB_SUCCESS;
3915 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3917 PyObject *py_ldb = (PyObject *)mod->private_data;
3918 PyObject *py_result, *py_msg;
3920 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3922 if (py_msg == NULL) {
3923 return LDB_ERR_OPERATIONS_ERROR;
3926 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3927 discard_const_p(char, "O"),
3928 py_msg);
3930 Py_DECREF(py_msg);
3932 if (py_result == NULL) {
3933 return LDB_ERR_PYTHON_EXCEPTION;
3936 Py_DECREF(py_result);
3938 return LDB_SUCCESS;
3941 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3943 PyObject *py_ldb = (PyObject *)mod->private_data;
3944 PyObject *py_result, *py_msg;
3946 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3948 if (py_msg == NULL) {
3949 return LDB_ERR_OPERATIONS_ERROR;
3952 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3953 discard_const_p(char, "O"),
3954 py_msg);
3956 Py_DECREF(py_msg);
3958 if (py_result == NULL) {
3959 return LDB_ERR_PYTHON_EXCEPTION;
3962 Py_DECREF(py_result);
3964 return LDB_SUCCESS;
3967 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3969 PyObject *py_ldb = (PyObject *)mod->private_data;
3970 PyObject *py_result, *py_dn;
3972 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3974 if (py_dn == NULL)
3975 return LDB_ERR_OPERATIONS_ERROR;
3977 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3978 discard_const_p(char, "O"),
3979 py_dn);
3981 if (py_result == NULL) {
3982 return LDB_ERR_PYTHON_EXCEPTION;
3985 Py_DECREF(py_result);
3987 return LDB_SUCCESS;
3990 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3992 PyObject *py_ldb = (PyObject *)mod->private_data;
3993 PyObject *py_result, *py_olddn, *py_newdn;
3995 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3997 if (py_olddn == NULL)
3998 return LDB_ERR_OPERATIONS_ERROR;
4000 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
4002 if (py_newdn == NULL)
4003 return LDB_ERR_OPERATIONS_ERROR;
4005 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
4006 discard_const_p(char, "OO"),
4007 py_olddn, py_newdn);
4009 Py_DECREF(py_olddn);
4010 Py_DECREF(py_newdn);
4012 if (py_result == NULL) {
4013 return LDB_ERR_PYTHON_EXCEPTION;
4016 Py_DECREF(py_result);
4018 return LDB_SUCCESS;
4021 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
4023 PyObject *py_ldb = (PyObject *)mod->private_data;
4024 PyObject *py_result;
4026 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
4027 discard_const_p(char, ""));
4029 Py_XDECREF(py_result);
4031 return LDB_ERR_OPERATIONS_ERROR;
4034 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4036 PyObject *py_ldb = (PyObject *)mod->private_data;
4037 PyObject *py_result;
4039 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4040 discard_const_p(char, ""));
4042 Py_XDECREF(py_result);
4044 return LDB_ERR_OPERATIONS_ERROR;
4047 static int py_module_start_transaction(struct ldb_module *mod)
4049 PyObject *py_ldb = (PyObject *)mod->private_data;
4050 PyObject *py_result;
4052 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4053 discard_const_p(char, ""));
4055 if (py_result == NULL) {
4056 return LDB_ERR_PYTHON_EXCEPTION;
4059 Py_DECREF(py_result);
4061 return LDB_SUCCESS;
4064 static int py_module_end_transaction(struct ldb_module *mod)
4066 PyObject *py_ldb = (PyObject *)mod->private_data;
4067 PyObject *py_result;
4069 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4070 discard_const_p(char, ""));
4072 if (py_result == NULL) {
4073 return LDB_ERR_PYTHON_EXCEPTION;
4076 Py_DECREF(py_result);
4078 return LDB_SUCCESS;
4081 static int py_module_del_transaction(struct ldb_module *mod)
4083 PyObject *py_ldb = (PyObject *)mod->private_data;
4084 PyObject *py_result;
4086 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4087 discard_const_p(char, ""));
4089 if (py_result == NULL) {
4090 return LDB_ERR_PYTHON_EXCEPTION;
4093 Py_DECREF(py_result);
4095 return LDB_SUCCESS;
4098 static int py_module_destructor(struct ldb_module *mod)
4100 Py_DECREF((PyObject *)mod->private_data);
4101 return 0;
4104 static int py_module_init(struct ldb_module *mod)
4106 PyObject *py_class = (PyObject *)mod->ops->private_data;
4107 PyObject *py_result, *py_next, *py_ldb;
4109 py_ldb = PyLdb_FromLdbContext(mod->ldb);
4111 if (py_ldb == NULL)
4112 return LDB_ERR_OPERATIONS_ERROR;
4114 py_next = PyLdbModule_FromModule(mod->next);
4116 if (py_next == NULL)
4117 return LDB_ERR_OPERATIONS_ERROR;
4119 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4120 py_ldb, py_next);
4122 if (py_result == NULL) {
4123 return LDB_ERR_PYTHON_EXCEPTION;
4126 mod->private_data = py_result;
4128 talloc_set_destructor(mod, py_module_destructor);
4130 return ldb_next_init(mod);
4133 static PyObject *py_register_module(PyObject *module, PyObject *args)
4135 int ret;
4136 struct ldb_module_ops *ops;
4137 PyObject *input;
4138 PyObject *tmp = NULL;
4139 const char *name = NULL;
4141 if (!PyArg_ParseTuple(args, "O", &input))
4142 return NULL;
4144 ops = talloc_zero(NULL, struct ldb_module_ops);
4145 if (ops == NULL) {
4146 PyErr_NoMemory();
4147 return NULL;
4150 tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
4151 if (tmp == NULL) {
4152 return NULL;
4154 name = PyUnicode_AsUTF8(tmp);
4155 if (name == NULL) {
4156 return NULL;
4158 Py_XDECREF(tmp);
4159 Py_INCREF(input);
4161 ops->name = talloc_strdup(ops, name);
4162 ops->private_data = input;
4163 ops->init_context = py_module_init;
4164 ops->search = py_module_search;
4165 ops->add = py_module_add;
4166 ops->modify = py_module_modify;
4167 ops->del = py_module_del;
4168 ops->rename = py_module_rename;
4169 ops->request = py_module_request;
4170 ops->extended = py_module_extended;
4171 ops->start_transaction = py_module_start_transaction;
4172 ops->end_transaction = py_module_end_transaction;
4173 ops->del_transaction = py_module_del_transaction;
4175 ret = ldb_register_module(ops);
4176 if (ret != LDB_SUCCESS) {
4177 TALLOC_FREE(ops);
4180 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4182 Py_RETURN_NONE;
4185 static PyObject *py_timestring(PyObject *module, PyObject *args)
4187 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4188 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4189 long int t_val;
4190 char *tresult;
4191 PyObject *ret;
4192 if (!PyArg_ParseTuple(args, "l", &t_val))
4193 return NULL;
4194 tresult = ldb_timestring(NULL, (time_t) t_val);
4195 ret = PyUnicode_FromString(tresult);
4196 talloc_free(tresult);
4197 return ret;
4200 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4202 char *str;
4203 if (!PyArg_ParseTuple(args, "s", &str))
4204 return NULL;
4206 return PyLong_FromLong(ldb_string_to_time(str));
4209 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4211 char *name;
4212 if (!PyArg_ParseTuple(args, "s", &name))
4213 return NULL;
4214 return PyBool_FromLong(ldb_valid_attr_name(name));
4218 encode a string using RFC2254 rules
4220 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4222 char *str, *encoded;
4223 Py_ssize_t size = 0;
4224 struct ldb_val val;
4225 PyObject *ret;
4227 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4228 return NULL;
4229 val.data = (uint8_t *)str;
4230 val.length = size;
4232 encoded = ldb_binary_encode(NULL, val);
4233 if (encoded == NULL) {
4234 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4235 return NULL;
4237 ret = PyUnicode_FromString(encoded);
4238 talloc_free(encoded);
4239 return ret;
4243 decode a string using RFC2254 rules
4245 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4247 char *str;
4248 struct ldb_val val;
4249 PyObject *ret;
4251 if (!PyArg_ParseTuple(args, "s", &str))
4252 return NULL;
4254 val = ldb_binary_decode(NULL, str);
4255 if (val.data == NULL) {
4256 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4257 return NULL;
4259 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4260 talloc_free(val.data);
4261 return ret;
4264 static PyMethodDef py_ldb_global_methods[] = {
4265 { "register_module", py_register_module, METH_VARARGS,
4266 "S.register_module(module) -> None\n\n"
4267 "Register a LDB module."},
4268 { "timestring", py_timestring, METH_VARARGS,
4269 "S.timestring(int) -> string\n\n"
4270 "Generate a LDAP time string from a UNIX timestamp" },
4271 { "string_to_time", py_string_to_time, METH_VARARGS,
4272 "S.string_to_time(string) -> int\n\n"
4273 "Parse a LDAP time string into a UNIX timestamp." },
4274 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4275 "S.valid_attr_name(name) -> bool\n\nn"
4276 "Check whether the supplied name is a valid attribute name." },
4277 { "binary_encode", py_binary_encode, METH_VARARGS,
4278 "S.binary_encode(string) -> string\n\n"
4279 "Perform a RFC2254 binary encoding on a string" },
4280 { "binary_decode", py_binary_decode, METH_VARARGS,
4281 "S.binary_decode(string) -> string\n\n"
4282 "Perform a RFC2254 binary decode on a string" },
4286 #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."
4288 #if PY_MAJOR_VERSION >= 3
4289 static struct PyModuleDef moduledef = {
4290 PyModuleDef_HEAD_INIT,
4291 .m_name = "ldb",
4292 .m_doc = MODULE_DOC,
4293 .m_size = -1,
4294 .m_methods = py_ldb_global_methods,
4296 #endif
4298 static PyObject* module_init(void)
4300 PyObject *m;
4302 PyLdbBytesType.tp_base = &PyBytes_Type;
4303 if (PyType_Ready(&PyLdbBytesType) < 0) {
4304 return NULL;
4307 if (PyType_Ready(&PyLdbDn) < 0)
4308 return NULL;
4310 if (PyType_Ready(&PyLdbMessage) < 0)
4311 return NULL;
4313 if (PyType_Ready(&PyLdbMessageElement) < 0)
4314 return NULL;
4316 if (PyType_Ready(&PyLdb) < 0)
4317 return NULL;
4319 if (PyType_Ready(&PyLdbModule) < 0)
4320 return NULL;
4322 if (PyType_Ready(&PyLdbTree) < 0)
4323 return NULL;
4325 if (PyType_Ready(&PyLdbResult) < 0)
4326 return NULL;
4328 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4329 return NULL;
4331 if (PyType_Ready(&PyLdbControl) < 0)
4332 return NULL;
4334 #if PY_MAJOR_VERSION >= 3
4335 m = PyModule_Create(&moduledef);
4336 #else
4337 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4338 #endif
4339 if (m == NULL)
4340 return NULL;
4342 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4344 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4345 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4346 ADD_LDB_INT(SEQ_NEXT);
4347 ADD_LDB_INT(SCOPE_DEFAULT);
4348 ADD_LDB_INT(SCOPE_BASE);
4349 ADD_LDB_INT(SCOPE_ONELEVEL);
4350 ADD_LDB_INT(SCOPE_SUBTREE);
4352 ADD_LDB_INT(CHANGETYPE_NONE);
4353 ADD_LDB_INT(CHANGETYPE_ADD);
4354 ADD_LDB_INT(CHANGETYPE_DELETE);
4355 ADD_LDB_INT(CHANGETYPE_MODIFY);
4357 ADD_LDB_INT(FLAG_MOD_ADD);
4358 ADD_LDB_INT(FLAG_MOD_REPLACE);
4359 ADD_LDB_INT(FLAG_MOD_DELETE);
4360 ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
4362 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4363 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4364 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4365 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4367 ADD_LDB_INT(SUCCESS);
4368 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4369 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4370 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4371 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4372 ADD_LDB_INT(ERR_COMPARE_FALSE);
4373 ADD_LDB_INT(ERR_COMPARE_TRUE);
4374 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4375 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4376 ADD_LDB_INT(ERR_REFERRAL);
4377 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4378 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4379 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4380 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4381 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4382 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4383 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4384 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4385 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4386 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4387 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4388 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4389 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4390 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4391 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4392 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4393 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4394 ADD_LDB_INT(ERR_BUSY);
4395 ADD_LDB_INT(ERR_UNAVAILABLE);
4396 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4397 ADD_LDB_INT(ERR_LOOP_DETECT);
4398 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4399 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4400 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4401 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4402 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4403 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4404 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4405 ADD_LDB_INT(ERR_OTHER);
4407 ADD_LDB_INT(FLG_RDONLY);
4408 ADD_LDB_INT(FLG_NOSYNC);
4409 ADD_LDB_INT(FLG_RECONNECT);
4410 ADD_LDB_INT(FLG_NOMMAP);
4411 ADD_LDB_INT(FLG_SHOW_BINARY);
4412 ADD_LDB_INT(FLG_ENABLE_TRACING);
4413 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4415 ADD_LDB_INT(PACKING_FORMAT);
4416 ADD_LDB_INT(PACKING_FORMAT_V2);
4418 /* Historical misspelling */
4419 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4421 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4423 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4424 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4426 Py_INCREF(&PyLdb);
4427 Py_INCREF(&PyLdbDn);
4428 Py_INCREF(&PyLdbModule);
4429 Py_INCREF(&PyLdbMessage);
4430 Py_INCREF(&PyLdbMessageElement);
4431 Py_INCREF(&PyLdbTree);
4432 Py_INCREF(&PyLdbResult);
4433 Py_INCREF(&PyLdbControl);
4435 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4436 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4437 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4438 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4439 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4440 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4441 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4443 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4445 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4447 ADD_LDB_STRING(SYNTAX_DN);
4448 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4449 ADD_LDB_STRING(SYNTAX_INTEGER);
4450 ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
4451 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4452 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4453 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4454 ADD_LDB_STRING(OID_COMPARATOR_AND);
4455 ADD_LDB_STRING(OID_COMPARATOR_OR);
4457 return m;
4460 #if PY_MAJOR_VERSION >= 3
4461 PyMODINIT_FUNC PyInit_ldb(void);
4462 PyMODINIT_FUNC PyInit_ldb(void)
4464 return module_init();
4466 #else
4467 void initldb(void);
4468 void initldb(void)
4470 module_init();
4472 #endif