lib/util: inline lib/util/util_runcmd.h again
[Samba.git] / lib / ldb / pyldb.c
blob3deb393e467c41cb6a6f6d8fdc614bae91699830
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 struct py_ldb_search_iterator_reply;
39 typedef struct {
40 PyObject_HEAD
41 TALLOC_CTX *mem_ctx;
42 PyLdbObject *ldb;
43 struct {
44 struct ldb_request *req;
45 struct py_ldb_search_iterator_reply *next;
46 struct py_ldb_search_iterator_reply *result;
47 PyObject *exception;
48 } state;
49 } PyLdbSearchIteratorObject;
51 struct py_ldb_search_iterator_reply {
52 struct py_ldb_search_iterator_reply *prev, *next;
53 PyLdbSearchIteratorObject *py_iter;
54 PyObject *obj;
57 void initldb(void);
58 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
59 static PyObject *PyExc_LdbError;
61 static PyTypeObject PyLdbControl;
62 static PyTypeObject PyLdbResult;
63 static PyTypeObject PyLdbSearchIterator;
64 static PyTypeObject PyLdbMessage;
65 #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
66 static PyTypeObject PyLdbModule;
67 static PyTypeObject PyLdbDn;
68 #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
69 static PyTypeObject PyLdb;
70 #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
71 static PyTypeObject PyLdbMessageElement;
72 #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
74 static PyTypeObject PyLdbTree;
75 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
76 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
77 static struct ldb_message_element *PyObject_AsMessageElement(
78 TALLOC_CTX *mem_ctx,
79 PyObject *set_obj,
80 unsigned int flags,
81 const char *attr_name);
82 static PyTypeObject PyLdbBytesType;
84 #if PY_MAJOR_VERSION >= 3
85 #define PyStr_Check PyUnicode_Check
86 #define PyStr_FromString PyUnicode_FromString
87 #define PyStr_FromStringAndSize PyUnicode_FromStringAndSize
88 #define PyStr_FromFormat PyUnicode_FromFormat
89 #define PyStr_FromFormatV PyUnicode_FromFormatV
90 #define PyStr_AsUTF8 PyUnicode_AsUTF8
91 #define PyStr_AsUTF8AndSize PyUnicode_AsUTF8AndSize
92 #define PyInt_FromLong PyLong_FromLong
94 #define PYARG_STR_UNI "es"
96 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
98 PyObject* result = NULL;
99 PyObject* args = NULL;
100 args = Py_BuildValue("(y#)", msg, size);
101 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
102 Py_DECREF(args);
103 return result;
105 #else
106 #define PyStr_Check PyString_Check
107 #define PyStr_FromString PyString_FromString
108 #define PyStr_FromStringAndSize PyString_FromStringAndSize
109 #define PyStr_FromFormat PyString_FromFormat
110 #define PyStr_FromFormatV PyString_FromFormatV
111 #define PyStr_AsUTF8 PyString_AsString
112 #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
114 #define PYARG_STR_UNI "et"
116 const char *PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr);
117 const char *
118 PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr)
120 const char * ret = PyString_AsString(pystr);
121 if (ret == NULL)
122 return NULL;
123 *sizeptr = PyString_Size(pystr);
124 return ret;
126 #endif
128 static PyObject *richcmp(int cmp_val, int op)
130 int ret;
131 switch (op) {
132 case Py_LT: ret = cmp_val < 0; break;
133 case Py_LE: ret = cmp_val <= 0; break;
134 case Py_EQ: ret = cmp_val == 0; break;
135 case Py_NE: ret = cmp_val != 0; break;
136 case Py_GT: ret = cmp_val > 0; break;
137 case Py_GE: ret = cmp_val >= 0; break;
138 default:
139 Py_INCREF(Py_NotImplemented);
140 return Py_NotImplemented;
142 return PyBool_FromLong(ret);
146 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
148 if (self->data != NULL) {
149 char* control = ldb_control_to_string(self->mem_ctx, self->data);
150 if (control == NULL) {
151 PyErr_NoMemory();
152 return NULL;
154 return PyStr_FromString(control);
155 } else {
156 return PyStr_FromString("ldb control");
160 static void py_ldb_control_dealloc(PyLdbControlObject *self)
162 if (self->mem_ctx != NULL) {
163 talloc_free(self->mem_ctx);
165 self->data = NULL;
166 Py_TYPE(self)->tp_free(self);
169 /* Create a text (rather than bytes) interface for a LDB result object */
170 static PyObject *wrap_text(const char *type, PyObject *wrapped)
172 PyObject *mod, *cls, *constructor, *inst;
173 mod = PyImport_ImportModule("_ldb_text");
174 if (mod == NULL)
175 return NULL;
176 cls = PyObject_GetAttrString(mod, type);
177 Py_DECREF(mod);
178 if (cls == NULL) {
179 Py_DECREF(mod);
180 return NULL;
182 constructor = PyObject_GetAttrString(cls, "_wrap");
183 Py_DECREF(cls);
184 if (constructor == NULL) {
185 return NULL;
187 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
188 Py_DECREF(constructor);
189 return inst;
192 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
194 return PyStr_FromString(self->data->oid);
197 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
199 return PyBool_FromLong(self->data->critical);
202 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
204 if (PyObject_IsTrue(value)) {
205 self->data->critical = true;
206 } else {
207 self->data->critical = false;
209 return 0;
212 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
214 char *data = NULL;
215 const char * const kwnames[] = { "ldb", "data", NULL };
216 struct ldb_control *parsed_controls;
217 PyLdbControlObject *ret;
218 PyObject *py_ldb;
219 TALLOC_CTX *mem_ctx;
220 struct ldb_context *ldb_ctx;
222 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
223 discard_const_p(char *, kwnames),
224 &PyLdb, &py_ldb, &data))
225 return NULL;
227 mem_ctx = talloc_new(NULL);
228 if (mem_ctx == NULL) {
229 PyErr_NoMemory();
230 return NULL;
233 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
234 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
236 if (!parsed_controls) {
237 talloc_free(mem_ctx);
238 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
239 return NULL;
242 ret = PyObject_New(PyLdbControlObject, type);
243 if (ret == NULL) {
244 PyErr_NoMemory();
245 talloc_free(mem_ctx);
246 return NULL;
249 ret->mem_ctx = mem_ctx;
251 ret->data = talloc_move(mem_ctx, &parsed_controls);
252 if (ret->data == NULL) {
253 Py_DECREF(ret);
254 PyErr_NoMemory();
255 talloc_free(mem_ctx);
256 return NULL;
259 return (PyObject *)ret;
262 static PyGetSetDef py_ldb_control_getset[] = {
264 .name = discard_const_p(char, "oid"),
265 .get = (getter)py_ldb_control_get_oid,
268 .name = discard_const_p(char, "critical"),
269 .get = (getter)py_ldb_control_get_critical,
270 .set = (setter)py_ldb_control_set_critical,
272 { .name = NULL },
275 static PyTypeObject PyLdbControl = {
276 .tp_name = "ldb.control",
277 .tp_dealloc = (destructor)py_ldb_control_dealloc,
278 .tp_getattro = PyObject_GenericGetAttr,
279 .tp_basicsize = sizeof(PyLdbControlObject),
280 .tp_getset = py_ldb_control_getset,
281 .tp_doc = "LDB control.",
282 .tp_str = (reprfunc)py_ldb_control_str,
283 .tp_new = py_ldb_control_new,
284 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
287 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
289 if (ret == LDB_ERR_PYTHON_EXCEPTION)
290 return; /* Python exception should already be set, just keep that */
292 PyErr_SetObject(error,
293 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
294 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
296 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
298 char *msg = NULL;
299 Py_ssize_t size;
300 int result = 0;
301 if (!PyBytes_Check(self)) {
302 PyErr_Format(PyExc_TypeError,"Unexpected type");
303 return NULL;
305 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
306 if (result != 0) {
307 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
308 return NULL;
310 return PyUnicode_FromStringAndSize(msg, size);
313 static PyTypeObject PyLdbBytesType = {
314 PyVarObject_HEAD_INIT(NULL, 0)
315 .tp_name = "ldb.bytes",
316 .tp_doc = "str/bytes (with custom str)",
317 .tp_str = (reprfunc)py_ldb_bytes_str,
318 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
321 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
323 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
326 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
328 return PyStr_FromStringAndSize((const char *)val->data, val->length);
332 * Create a Python object from a ldb_result.
334 * @param result LDB result to convert
335 * @return Python object with converted result (a list object)
337 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
339 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
340 PyLdbControlObject *ctrl;
341 if (ctl_ctx == NULL) {
342 PyErr_NoMemory();
343 return NULL;
346 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
347 if (ctrl == NULL) {
348 talloc_free(ctl_ctx);
349 PyErr_NoMemory();
350 return NULL;
352 ctrl->mem_ctx = ctl_ctx;
353 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
354 if (ctrl->data == NULL) {
355 Py_DECREF(ctrl);
356 PyErr_NoMemory();
357 return NULL;
359 return (PyObject*) ctrl;
363 * Create a Python object from a ldb_result.
365 * @param result LDB result to convert
366 * @return Python object with converted result (a list object)
368 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
370 PyLdbResultObject *ret;
371 PyObject *list, *controls, *referals;
372 Py_ssize_t i;
374 if (result == NULL) {
375 Py_RETURN_NONE;
378 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
379 if (ret == NULL) {
380 PyErr_NoMemory();
381 return NULL;
384 list = PyList_New(result->count);
385 if (list == NULL) {
386 PyErr_NoMemory();
387 Py_DECREF(ret);
388 return NULL;
391 for (i = 0; i < result->count; i++) {
392 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
395 ret->mem_ctx = talloc_new(NULL);
396 if (ret->mem_ctx == NULL) {
397 Py_DECREF(list);
398 Py_DECREF(ret);
399 PyErr_NoMemory();
400 return NULL;
403 ret->msgs = list;
405 if (result->controls) {
406 i = 0;
407 while (result->controls[i]) {
408 i++;
410 controls = PyList_New(i);
411 if (controls == NULL) {
412 Py_DECREF(ret);
413 PyErr_NoMemory();
414 return NULL;
416 for (i=0; result->controls[i]; i++) {
417 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
418 if (ctrl == NULL) {
419 Py_DECREF(ret);
420 Py_DECREF(controls);
421 PyErr_NoMemory();
422 return NULL;
424 PyList_SetItem(controls, i, ctrl);
426 } else {
428 * No controls so we keep an empty list
430 controls = PyList_New(0);
431 if (controls == NULL) {
432 Py_DECREF(ret);
433 PyErr_NoMemory();
434 return NULL;
438 ret->controls = controls;
440 i = 0;
442 while (result->refs && result->refs[i]) {
443 i++;
446 referals = PyList_New(i);
447 if (referals == NULL) {
448 Py_DECREF(ret);
449 PyErr_NoMemory();
450 return NULL;
453 for (i = 0;result->refs && result->refs[i]; i++) {
454 PyList_SetItem(referals, i, PyStr_FromString(result->refs[i]));
456 ret->referals = referals;
457 return (PyObject *)ret;
461 * Create a LDB Result from a Python object.
462 * If conversion fails, NULL will be returned and a Python exception set.
464 * Note: the result object only includes the messages at the moment; extended
465 * result, controls and referrals are ignored.
467 * @param mem_ctx Memory context in which to allocate the LDB Result
468 * @param obj Python object to convert
469 * @return a ldb_result, or NULL if the conversion failed
471 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
472 PyObject *obj)
474 struct ldb_result *res;
475 Py_ssize_t i;
477 if (obj == Py_None)
478 return NULL;
480 res = talloc_zero(mem_ctx, struct ldb_result);
481 res->count = PyList_Size(obj);
482 res->msgs = talloc_array(res, struct ldb_message *, res->count);
483 for (i = 0; i < res->count; i++) {
484 PyObject *item = PyList_GetItem(obj, i);
485 res->msgs[i] = pyldb_Message_AsMessage(item);
487 return res;
490 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
492 return PyBool_FromLong(ldb_dn_validate(self->dn));
495 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
497 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
500 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
502 return PyBool_FromLong(ldb_dn_is_special(self->dn));
505 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
507 return PyBool_FromLong(ldb_dn_is_null(self->dn));
510 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
512 return PyStr_FromString(ldb_dn_get_casefold(self->dn));
515 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
517 return PyStr_FromString(ldb_dn_get_linearized(self->dn));
520 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
522 return PyStr_FromString(ldb_dn_canonical_string(self->dn, self->dn));
525 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
527 return PyStr_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
530 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
532 const char * const kwnames[] = { "mode", NULL };
533 int mode = 1;
534 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
535 discard_const_p(char *, kwnames),
536 &mode))
537 return NULL;
538 return PyStr_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
541 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
543 char *name;
544 const struct ldb_val *val;
546 if (!PyArg_ParseTuple(args, "s", &name))
547 return NULL;
548 val = ldb_dn_get_extended_component(self->dn, name);
549 if (val == NULL) {
550 Py_RETURN_NONE;
553 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
556 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
558 char *name;
559 int err;
560 uint8_t *value = NULL;
561 Py_ssize_t size = 0;
563 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
564 return NULL;
566 if (value == NULL) {
567 err = ldb_dn_set_extended_component(self->dn, name, NULL);
568 } else {
569 struct ldb_val val;
570 val.data = (uint8_t *)value;
571 val.length = size;
572 err = ldb_dn_set_extended_component(self->dn, name, &val);
575 if (err != LDB_SUCCESS) {
576 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
577 return NULL;
580 Py_RETURN_NONE;
583 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
585 PyObject *str = PyStr_FromString(ldb_dn_get_linearized(self->dn));
586 PyObject *repr, *result;
587 if (str == NULL)
588 return NULL;
589 repr = PyObject_Repr(str);
590 if (repr == NULL) {
591 Py_DECREF(str);
592 return NULL;
594 result = PyStr_FromFormat("Dn(%s)", PyStr_AsUTF8(repr));
595 Py_DECREF(str);
596 Py_DECREF(repr);
597 return result;
600 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
602 char *name;
604 if (!PyArg_ParseTuple(args, "s", &name))
605 return NULL;
607 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
610 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
612 int ret;
613 if (!pyldb_Dn_Check(dn2)) {
614 Py_INCREF(Py_NotImplemented);
615 return Py_NotImplemented;
617 ret = ldb_dn_compare(pyldb_Dn_AsDn(dn1), pyldb_Dn_AsDn(dn2));
618 return richcmp(ret, op);
621 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
623 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
624 struct ldb_dn *parent;
625 PyLdbDnObject *py_ret;
626 TALLOC_CTX *mem_ctx = talloc_new(NULL);
628 parent = ldb_dn_get_parent(mem_ctx, dn);
629 if (parent == NULL) {
630 talloc_free(mem_ctx);
631 Py_RETURN_NONE;
634 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
635 if (py_ret == NULL) {
636 PyErr_NoMemory();
637 talloc_free(mem_ctx);
638 return NULL;
640 py_ret->mem_ctx = mem_ctx;
641 py_ret->dn = parent;
642 return (PyObject *)py_ret;
645 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
647 PyObject *py_other;
648 struct ldb_dn *dn, *other;
649 if (!PyArg_ParseTuple(args, "O", &py_other))
650 return NULL;
652 dn = pyldb_Dn_AsDn((PyObject *)self);
654 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
655 return NULL;
657 return PyBool_FromLong(ldb_dn_add_child(dn, other));
660 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
662 PyObject *py_other;
663 struct ldb_dn *other, *dn;
664 if (!PyArg_ParseTuple(args, "O", &py_other))
665 return NULL;
667 dn = pyldb_Dn_AsDn((PyObject *)self);
669 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
670 return NULL;
672 return PyBool_FromLong(ldb_dn_add_base(dn, other));
675 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
677 struct ldb_dn *dn;
678 int i;
679 if (!PyArg_ParseTuple(args, "i", &i))
680 return NULL;
682 dn = pyldb_Dn_AsDn((PyObject *)self);
684 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
687 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
689 PyObject *py_base;
690 struct ldb_dn *dn, *base;
691 if (!PyArg_ParseTuple(args, "O", &py_base))
692 return NULL;
694 dn = pyldb_Dn_AsDn((PyObject *)self);
696 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
697 return NULL;
699 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
702 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
704 struct ldb_dn *dn;
705 const char *name;
706 unsigned int num = 0;
708 if (!PyArg_ParseTuple(args, "I", &num))
709 return NULL;
711 dn = pyldb_Dn_AsDn((PyObject *)self);
713 name = ldb_dn_get_component_name(dn, num);
714 if (name == NULL) {
715 Py_RETURN_NONE;
718 return PyStr_FromString(name);
721 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
723 struct ldb_dn *dn;
724 const struct ldb_val *val;
725 unsigned int num = 0;
727 if (!PyArg_ParseTuple(args, "I", &num))
728 return NULL;
730 dn = pyldb_Dn_AsDn((PyObject *)self);
732 val = ldb_dn_get_component_val(dn, num);
733 if (val == NULL) {
734 Py_RETURN_NONE;
737 return PyStr_FromLdbValue(val);
740 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
742 unsigned int num = 0;
743 char *name = NULL, *value = NULL;
744 struct ldb_val val = { NULL, };
745 int err;
746 Py_ssize_t size = 0;
748 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
749 return NULL;
751 val.data = (unsigned char*) value;
752 val.length = size;
754 err = ldb_dn_set_component(self->dn, num, name, val);
755 if (err != LDB_SUCCESS) {
756 PyErr_SetString(PyExc_TypeError, "Failed to set component");
757 return NULL;
760 Py_RETURN_NONE;
763 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
765 struct ldb_dn *dn;
766 const char *name;
768 dn = pyldb_Dn_AsDn((PyObject *)self);
770 name = ldb_dn_get_rdn_name(dn);
771 if (name == NULL) {
772 Py_RETURN_NONE;
775 return PyStr_FromString(name);
778 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
780 struct ldb_dn *dn;
781 const struct ldb_val *val;
783 dn = pyldb_Dn_AsDn((PyObject *)self);
785 val = ldb_dn_get_rdn_val(dn);
786 if (val == NULL) {
787 Py_RETURN_NONE;
790 return PyStr_FromLdbValue(val);
793 static PyMethodDef py_ldb_dn_methods[] = {
794 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
795 "S.validate() -> bool\n"
796 "Validate DN is correct." },
797 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
798 "S.is_valid() -> bool\n" },
799 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
800 "S.is_special() -> bool\n"
801 "Check whether this is a special LDB DN." },
802 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
803 "Check whether this is a null DN." },
804 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
805 NULL },
806 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
807 NULL },
808 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
809 "S.canonical_str() -> string\n"
810 "Canonical version of this DN (like a posix path)." },
811 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
812 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
813 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
814 "S.canonical_ex_str() -> string\n"
815 "Canonical version of this DN (like a posix path, with terminating newline)." },
816 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
817 "S.extended_str(mode=1) -> string\n"
818 "Extended version of this DN" },
819 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
820 "S.parent() -> dn\n"
821 "Get the parent for this DN." },
822 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
823 "S.add_child(dn) -> None\n"
824 "Add a child DN to this DN." },
825 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
826 "S.add_base(dn) -> None\n"
827 "Add a base DN to this DN." },
828 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
829 "S.remove_base_components(int) -> bool\n"
830 "Remove a number of DN components from the base of this DN." },
831 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
832 "S.check_special(name) -> bool\n\n"
833 "Check if name is a special DN name"},
834 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
835 "S.get_extended_component(name) -> string\n\n"
836 "returns a DN extended component as a binary string"},
837 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
838 "S.set_extended_component(name, value) -> None\n\n"
839 "set a DN extended component as a binary string"},
840 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
841 "S.get_component_name(num) -> string\n"
842 "get the attribute name of the specified component" },
843 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
844 "S.get_component_value(num) -> string\n"
845 "get the attribute value of the specified component as a binary string" },
846 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
847 "S.get_component_value(num, name, value) -> None\n"
848 "set the attribute name and value of the specified component" },
849 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
850 "S.get_rdn_name() -> string\n"
851 "get the RDN attribute name" },
852 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
853 "S.get_rdn_value() -> string\n"
854 "get the RDN attribute value as a binary string" },
855 { NULL }
858 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
860 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
864 copy a DN as a python object
866 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
868 PyLdbDnObject *py_ret;
870 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
871 if (py_ret == NULL) {
872 PyErr_NoMemory();
873 return NULL;
875 py_ret->mem_ctx = talloc_new(NULL);
876 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
877 return (PyObject *)py_ret;
880 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
882 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
883 *other;
884 PyLdbDnObject *py_ret;
886 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
887 return NULL;
889 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
890 if (py_ret == NULL) {
891 PyErr_NoMemory();
892 return NULL;
894 py_ret->mem_ctx = talloc_new(NULL);
895 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
896 ldb_dn_add_base(py_ret->dn, other);
897 return (PyObject *)py_ret;
900 static PySequenceMethods py_ldb_dn_seq = {
901 .sq_length = (lenfunc)py_ldb_dn_len,
902 .sq_concat = (binaryfunc)py_ldb_dn_concat,
905 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
907 struct ldb_dn *ret = NULL;
908 char *str = NULL;
909 PyObject *py_ldb = NULL;
910 struct ldb_context *ldb_ctx = NULL;
911 TALLOC_CTX *mem_ctx = NULL;
912 PyLdbDnObject *py_ret = NULL;
913 const char * const kwnames[] = { "ldb", "dn", NULL };
915 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
916 discard_const_p(char *, kwnames),
917 &py_ldb, "utf8", &str))
918 goto out;
920 if (!PyLdb_Check(py_ldb)) {
921 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
922 goto out;
925 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
927 mem_ctx = talloc_new(NULL);
928 if (mem_ctx == NULL) {
929 PyErr_NoMemory();
930 goto out;
933 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
934 if (!ldb_dn_validate(ret)) {
935 talloc_free(mem_ctx);
936 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
937 goto out;
940 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
941 if (py_ret == NULL) {
942 talloc_free(mem_ctx);
943 PyErr_NoMemory();
944 goto out;
946 py_ret->mem_ctx = mem_ctx;
947 py_ret->dn = ret;
948 out:
949 if (str != NULL) {
950 PyMem_Free(discard_const_p(char, str));
952 return (PyObject *)py_ret;
955 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
957 talloc_free(self->mem_ctx);
958 PyObject_Del(self);
961 static PyTypeObject PyLdbDn = {
962 .tp_name = "ldb.Dn",
963 .tp_methods = py_ldb_dn_methods,
964 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
965 .tp_repr = (reprfunc)py_ldb_dn_repr,
966 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
967 .tp_as_sequence = &py_ldb_dn_seq,
968 .tp_doc = "A LDB distinguished name.",
969 .tp_new = py_ldb_dn_new,
970 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
971 .tp_basicsize = sizeof(PyLdbDnObject),
972 .tp_flags = Py_TPFLAGS_DEFAULT,
975 /* Debug */
976 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
977 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
979 PyObject *fn = (PyObject *)context;
980 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyStr_FromFormatV(fmt, ap));
983 static PyObject *py_ldb_debug_func;
985 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
987 PyObject *cb;
988 struct ldb_context *ldb_ctx;
990 if (!PyArg_ParseTuple(args, "O", &cb))
991 return NULL;
993 if (py_ldb_debug_func != NULL) {
994 Py_DECREF(py_ldb_debug_func);
997 Py_INCREF(cb);
998 /* FIXME: DECREF cb when exiting program */
999 py_ldb_debug_func = cb;
1000 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1001 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
1002 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
1003 ldb_ctx);
1005 Py_RETURN_NONE;
1008 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
1010 unsigned int perms;
1011 if (!PyArg_ParseTuple(args, "I", &perms))
1012 return NULL;
1014 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
1016 Py_RETURN_NONE;
1019 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1021 char *modules_dir;
1022 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1023 return NULL;
1025 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
1027 Py_RETURN_NONE;
1030 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
1032 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1033 int ldb_err;
1034 ldb_err = ldb_transaction_start(ldb_ctx);
1035 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1036 Py_RETURN_NONE;
1039 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
1041 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1042 int ldb_err;
1043 ldb_err = ldb_transaction_commit(ldb_ctx);
1044 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1045 Py_RETURN_NONE;
1048 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
1050 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1051 int ldb_err;
1052 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1053 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1054 Py_RETURN_NONE;
1057 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
1059 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1060 int ldb_err;
1061 ldb_err = ldb_transaction_cancel(ldb_ctx);
1062 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1063 Py_RETURN_NONE;
1066 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
1068 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1069 int ldb_err;
1070 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1071 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1072 Py_RETURN_NONE;
1075 static PyObject *py_ldb_repr(PyLdbObject *self)
1077 return PyStr_FromString("<ldb connection>");
1080 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
1082 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(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)
1091 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
1092 if (dn == NULL)
1093 Py_RETURN_NONE;
1094 return py_ldb_dn_copy(dn);
1097 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
1099 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
1100 if (dn == NULL)
1101 Py_RETURN_NONE;
1102 return py_ldb_dn_copy(dn);
1105 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
1107 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
1108 if (dn == NULL)
1109 Py_RETURN_NONE;
1110 return py_ldb_dn_copy(dn);
1113 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1114 const char *paramname)
1116 const char **ret;
1117 Py_ssize_t i;
1118 if (!PyList_Check(list)) {
1119 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1120 return NULL;
1122 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1123 if (ret == NULL) {
1124 PyErr_NoMemory();
1125 return NULL;
1128 for (i = 0; i < PyList_Size(list); i++) {
1129 const char *str = NULL;
1130 Py_ssize_t size;
1131 PyObject *item = PyList_GetItem(list, i);
1132 if (!(PyStr_Check(item) || PyUnicode_Check(item))) {
1133 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1134 talloc_free(ret);
1135 return NULL;
1137 str = PyStr_AsUTF8AndSize(item, &size);
1138 if (str == NULL) {
1139 talloc_free(ret);
1140 return NULL;
1142 ret[i] = talloc_strndup(ret, str, size);
1144 ret[i] = NULL;
1145 return ret;
1148 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1150 const char * const kwnames[] = { "url", "flags", "options", NULL };
1151 char *url = NULL;
1152 PyObject *py_options = Py_None;
1153 const char **options;
1154 unsigned int flags = 0;
1155 int ret;
1156 struct ldb_context *ldb;
1158 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1159 discard_const_p(char *, kwnames),
1160 &url, &flags, &py_options))
1161 return -1;
1163 ldb = pyldb_Ldb_AsLdbContext(self);
1165 if (py_options == Py_None) {
1166 options = NULL;
1167 } else {
1168 options = PyList_AsStrList(ldb, py_options, "options");
1169 if (options == NULL)
1170 return -1;
1173 if (url != NULL) {
1174 ret = ldb_connect(ldb, url, flags, options);
1175 if (ret != LDB_SUCCESS) {
1176 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1177 return -1;
1181 talloc_free(options);
1182 return 0;
1185 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1187 PyLdbObject *ret;
1188 struct ldb_context *ldb;
1189 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1190 if (ret == NULL) {
1191 PyErr_NoMemory();
1192 return NULL;
1194 ret->mem_ctx = talloc_new(NULL);
1195 ldb = ldb_init(ret->mem_ctx, NULL);
1197 if (ldb == NULL) {
1198 PyErr_NoMemory();
1199 return NULL;
1202 ret->ldb_ctx = ldb;
1203 return (PyObject *)ret;
1206 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1208 char *url = NULL;
1209 unsigned int flags = 0;
1210 PyObject *py_options = Py_None;
1211 int ret;
1212 const char **options;
1213 const char * const kwnames[] = { "url", "flags", "options", NULL };
1214 struct ldb_context *ldb_ctx;
1216 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
1217 discard_const_p(char *, kwnames),
1218 &url, &flags, &py_options))
1219 return NULL;
1221 if (py_options == Py_None) {
1222 options = NULL;
1223 } else {
1224 options = PyList_AsStrList(NULL, py_options, "options");
1225 if (options == NULL)
1226 return NULL;
1229 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1230 ret = ldb_connect(ldb_ctx, url, flags, options);
1231 talloc_free(options);
1233 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1235 Py_RETURN_NONE;
1238 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1240 PyObject *py_msg;
1241 PyObject *py_controls = Py_None;
1242 struct ldb_context *ldb_ctx;
1243 struct ldb_request *req;
1244 struct ldb_control **parsed_controls;
1245 struct ldb_message *msg;
1246 int ret;
1247 TALLOC_CTX *mem_ctx;
1248 bool validate=true;
1249 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1251 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1252 discard_const_p(char *, kwnames),
1253 &py_msg, &py_controls, &validate))
1254 return NULL;
1256 mem_ctx = talloc_new(NULL);
1257 if (mem_ctx == NULL) {
1258 PyErr_NoMemory();
1259 return NULL;
1261 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1263 if (py_controls == Py_None) {
1264 parsed_controls = NULL;
1265 } else {
1266 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1267 if (controls == NULL) {
1268 talloc_free(mem_ctx);
1269 return NULL;
1271 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1272 talloc_free(controls);
1275 if (!PyLdbMessage_Check(py_msg)) {
1276 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1277 talloc_free(mem_ctx);
1278 return NULL;
1280 msg = pyldb_Message_AsMessage(py_msg);
1282 if (validate) {
1283 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1284 if (ret != LDB_SUCCESS) {
1285 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1286 talloc_free(mem_ctx);
1287 return NULL;
1291 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1292 NULL, ldb_op_default_callback, NULL);
1293 if (ret != LDB_SUCCESS) {
1294 PyErr_SetString(PyExc_TypeError, "failed to build request");
1295 talloc_free(mem_ctx);
1296 return NULL;
1299 /* do request and autostart a transaction */
1300 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1302 ret = ldb_transaction_start(ldb_ctx);
1303 if (ret != LDB_SUCCESS) {
1304 talloc_free(mem_ctx);
1305 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1306 return NULL;
1309 ret = ldb_request(ldb_ctx, req);
1310 if (ret == LDB_SUCCESS) {
1311 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1314 if (ret == LDB_SUCCESS) {
1315 ret = ldb_transaction_commit(ldb_ctx);
1316 } else {
1317 ldb_transaction_cancel(ldb_ctx);
1320 talloc_free(mem_ctx);
1321 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1323 Py_RETURN_NONE;
1328 * Obtain a ldb message from a Python Dictionary object.
1330 * @param mem_ctx Memory context
1331 * @param py_obj Python Dictionary object
1332 * @param ldb_ctx LDB context
1333 * @param mod_flags Flags to be set on every message element
1334 * @return ldb_message on success or NULL on failure
1336 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1337 PyObject *py_obj,
1338 struct ldb_context *ldb_ctx,
1339 unsigned int mod_flags)
1341 struct ldb_message *msg;
1342 unsigned int msg_pos = 0;
1343 Py_ssize_t dict_pos = 0;
1344 PyObject *key, *value;
1345 struct ldb_message_element *msg_el;
1346 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1348 msg = ldb_msg_new(mem_ctx);
1349 if (msg == NULL) {
1350 PyErr_NoMemory();
1351 return NULL;
1353 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1355 if (dn_value) {
1356 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1357 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1358 return NULL;
1360 if (msg->dn == NULL) {
1361 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1362 return NULL;
1364 } else {
1365 PyErr_SetString(PyExc_TypeError, "no dn set");
1366 return NULL;
1369 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1370 const char *key_str = PyStr_AsUTF8(key);
1371 if (ldb_attr_cmp(key_str, "dn") != 0) {
1372 msg_el = PyObject_AsMessageElement(msg->elements, value,
1373 mod_flags, key_str);
1374 if (msg_el == NULL) {
1375 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1376 return NULL;
1378 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1379 msg_pos++;
1383 msg->num_elements = msg_pos;
1385 return msg;
1388 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1390 PyObject *py_obj;
1391 int ret;
1392 struct ldb_context *ldb_ctx;
1393 struct ldb_request *req;
1394 struct ldb_message *msg = NULL;
1395 PyObject *py_controls = Py_None;
1396 TALLOC_CTX *mem_ctx;
1397 struct ldb_control **parsed_controls;
1398 const char * const kwnames[] = { "message", "controls", NULL };
1400 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1401 discard_const_p(char *, kwnames),
1402 &py_obj, &py_controls))
1403 return NULL;
1405 mem_ctx = talloc_new(NULL);
1406 if (mem_ctx == NULL) {
1407 PyErr_NoMemory();
1408 return NULL;
1410 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1412 if (py_controls == Py_None) {
1413 parsed_controls = NULL;
1414 } else {
1415 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1416 if (controls == NULL) {
1417 talloc_free(mem_ctx);
1418 return NULL;
1420 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1421 talloc_free(controls);
1424 if (PyLdbMessage_Check(py_obj)) {
1425 msg = pyldb_Message_AsMessage(py_obj);
1426 } else if (PyDict_Check(py_obj)) {
1427 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1428 } else {
1429 PyErr_SetString(PyExc_TypeError,
1430 "Dictionary or LdbMessage object expected!");
1433 if (!msg) {
1434 /* we should have a PyErr already set */
1435 talloc_free(mem_ctx);
1436 return NULL;
1439 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1440 if (ret != LDB_SUCCESS) {
1441 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1442 talloc_free(mem_ctx);
1443 return NULL;
1446 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1447 NULL, ldb_op_default_callback, NULL);
1448 if (ret != LDB_SUCCESS) {
1449 PyErr_SetString(PyExc_TypeError, "failed to build request");
1450 talloc_free(mem_ctx);
1451 return NULL;
1454 /* do request and autostart a transaction */
1455 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1457 ret = ldb_transaction_start(ldb_ctx);
1458 if (ret != LDB_SUCCESS) {
1459 talloc_free(mem_ctx);
1460 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1461 return NULL;
1464 ret = ldb_request(ldb_ctx, req);
1465 if (ret == LDB_SUCCESS) {
1466 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1469 if (ret == LDB_SUCCESS) {
1470 ret = ldb_transaction_commit(ldb_ctx);
1471 } else {
1472 ldb_transaction_cancel(ldb_ctx);
1475 talloc_free(mem_ctx);
1476 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1478 Py_RETURN_NONE;
1481 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1483 PyObject *py_dn;
1484 struct ldb_dn *dn;
1485 int ret;
1486 struct ldb_context *ldb_ctx;
1487 struct ldb_request *req;
1488 PyObject *py_controls = Py_None;
1489 TALLOC_CTX *mem_ctx;
1490 struct ldb_control **parsed_controls;
1491 const char * const kwnames[] = { "dn", "controls", NULL };
1493 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1494 discard_const_p(char *, kwnames),
1495 &py_dn, &py_controls))
1496 return NULL;
1498 mem_ctx = talloc_new(NULL);
1499 if (mem_ctx == NULL) {
1500 PyErr_NoMemory();
1501 return NULL;
1503 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1505 if (py_controls == Py_None) {
1506 parsed_controls = NULL;
1507 } else {
1508 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1509 if (controls == NULL) {
1510 talloc_free(mem_ctx);
1511 return NULL;
1513 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1514 talloc_free(controls);
1517 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1518 talloc_free(mem_ctx);
1519 return NULL;
1522 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1523 NULL, ldb_op_default_callback, NULL);
1524 if (ret != LDB_SUCCESS) {
1525 PyErr_SetString(PyExc_TypeError, "failed to build request");
1526 talloc_free(mem_ctx);
1527 return NULL;
1530 /* do request and autostart a transaction */
1531 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1533 ret = ldb_transaction_start(ldb_ctx);
1534 if (ret != LDB_SUCCESS) {
1535 talloc_free(mem_ctx);
1536 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1537 return NULL;
1540 ret = ldb_request(ldb_ctx, req);
1541 if (ret == LDB_SUCCESS) {
1542 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1545 if (ret == LDB_SUCCESS) {
1546 ret = ldb_transaction_commit(ldb_ctx);
1547 } else {
1548 ldb_transaction_cancel(ldb_ctx);
1551 talloc_free(mem_ctx);
1552 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1554 Py_RETURN_NONE;
1557 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1559 PyObject *py_dn1, *py_dn2;
1560 struct ldb_dn *dn1, *dn2;
1561 int ret;
1562 TALLOC_CTX *mem_ctx;
1563 PyObject *py_controls = Py_None;
1564 struct ldb_control **parsed_controls;
1565 struct ldb_context *ldb_ctx;
1566 struct ldb_request *req;
1567 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1569 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1571 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1572 discard_const_p(char *, kwnames),
1573 &py_dn1, &py_dn2, &py_controls))
1574 return NULL;
1577 mem_ctx = talloc_new(NULL);
1578 if (mem_ctx == NULL) {
1579 PyErr_NoMemory();
1580 return NULL;
1583 if (py_controls == Py_None) {
1584 parsed_controls = NULL;
1585 } else {
1586 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1587 if (controls == NULL) {
1588 talloc_free(mem_ctx);
1589 return NULL;
1591 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1592 talloc_free(controls);
1596 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1597 talloc_free(mem_ctx);
1598 return NULL;
1601 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1602 talloc_free(mem_ctx);
1603 return NULL;
1606 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1607 NULL, ldb_op_default_callback, NULL);
1608 if (ret != LDB_SUCCESS) {
1609 PyErr_SetString(PyExc_TypeError, "failed to build request");
1610 talloc_free(mem_ctx);
1611 return NULL;
1614 /* do request and autostart a transaction */
1615 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1617 ret = ldb_transaction_start(ldb_ctx);
1618 if (ret != LDB_SUCCESS) {
1619 talloc_free(mem_ctx);
1620 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1621 return NULL;
1624 ret = ldb_request(ldb_ctx, req);
1625 if (ret == LDB_SUCCESS) {
1626 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1629 if (ret == LDB_SUCCESS) {
1630 ret = ldb_transaction_commit(ldb_ctx);
1631 } else {
1632 ldb_transaction_cancel(ldb_ctx);
1635 talloc_free(mem_ctx);
1636 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1638 Py_RETURN_NONE;
1641 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1643 char *name;
1644 if (!PyArg_ParseTuple(args, "s", &name))
1645 return NULL;
1647 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1649 Py_RETURN_NONE;
1652 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1654 char *attribute, *syntax;
1655 unsigned int flags;
1656 int ret;
1657 struct ldb_context *ldb_ctx;
1659 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1660 return NULL;
1662 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1663 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1665 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1667 Py_RETURN_NONE;
1670 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1672 if (ldif == NULL) {
1673 Py_RETURN_NONE;
1674 } else {
1675 /* We don't want this attached to the 'ldb' any more */
1676 PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
1677 PyObject *result =
1678 Py_BuildValue(discard_const_p(char, "(iO)"),
1679 ldif->changetype,
1680 obj);
1681 Py_CLEAR(obj);
1682 return result;
1687 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1689 int changetype;
1690 PyObject *py_msg;
1691 struct ldb_ldif ldif;
1692 PyObject *ret;
1693 char *string;
1694 TALLOC_CTX *mem_ctx;
1696 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1697 return NULL;
1699 if (!PyLdbMessage_Check(py_msg)) {
1700 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1701 return NULL;
1704 ldif.msg = pyldb_Message_AsMessage(py_msg);
1705 ldif.changetype = changetype;
1707 mem_ctx = talloc_new(NULL);
1709 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1710 if (!string) {
1711 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1712 return NULL;
1715 ret = PyStr_FromString(string);
1717 talloc_free(mem_ctx);
1719 return ret;
1722 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1724 PyObject *list, *ret;
1725 struct ldb_ldif *ldif;
1726 const char *s;
1727 struct ldb_dn *last_dn = NULL;
1729 TALLOC_CTX *mem_ctx;
1731 if (!PyArg_ParseTuple(args, "s", &s))
1732 return NULL;
1734 mem_ctx = talloc_new(NULL);
1735 if (!mem_ctx) {
1736 Py_RETURN_NONE;
1739 list = PyList_New(0);
1740 while (s && *s != '\0') {
1741 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1742 talloc_steal(mem_ctx, ldif);
1743 if (ldif) {
1744 int res = 0;
1745 PyObject *py_ldif = ldb_ldif_to_pyobject(ldif);
1746 if (py_ldif == NULL) {
1747 Py_CLEAR(list);
1748 PyErr_BadArgument();
1749 talloc_free(mem_ctx);
1750 return NULL;
1752 res = PyList_Append(list, py_ldif);
1753 Py_CLEAR(py_ldif);
1754 if (res == -1) {
1755 Py_CLEAR(list);
1756 talloc_free(mem_ctx);
1757 return NULL;
1759 last_dn = ldif->msg->dn;
1760 } else {
1761 const char *last_dn_str = NULL;
1762 const char *err_string = NULL;
1763 if (last_dn == NULL) {
1764 PyErr_SetString(PyExc_ValueError,
1765 "unable to parse LDIF "
1766 "string at first chunk");
1767 Py_CLEAR(list);
1768 talloc_free(mem_ctx);
1769 return NULL;
1772 last_dn_str
1773 = ldb_dn_get_linearized(last_dn);
1775 err_string
1776 = talloc_asprintf(mem_ctx,
1777 "unable to parse ldif "
1778 "string AFTER %s",
1779 last_dn_str);
1781 PyErr_SetString(PyExc_ValueError,
1782 err_string);
1783 talloc_free(mem_ctx);
1784 Py_CLEAR(list);
1785 return NULL;
1788 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1789 ret = PyObject_GetIter(list);
1790 Py_DECREF(list);
1791 return ret;
1794 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1796 int ldb_ret;
1797 PyObject *py_msg_old;
1798 PyObject *py_msg_new;
1799 struct ldb_message *diff;
1800 struct ldb_context *ldb;
1801 PyObject *py_ret;
1803 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1804 return NULL;
1806 if (!PyLdbMessage_Check(py_msg_old)) {
1807 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1808 return NULL;
1811 if (!PyLdbMessage_Check(py_msg_new)) {
1812 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1813 return NULL;
1816 ldb = pyldb_Ldb_AsLdbContext(self);
1817 ldb_ret = ldb_msg_difference(ldb, ldb,
1818 pyldb_Message_AsMessage(py_msg_old),
1819 pyldb_Message_AsMessage(py_msg_new),
1820 &diff);
1821 if (ldb_ret != LDB_SUCCESS) {
1822 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1823 return NULL;
1826 py_ret = PyLdbMessage_FromMessage(diff);
1828 talloc_unlink(ldb, diff);
1830 return py_ret;
1833 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1835 const struct ldb_schema_attribute *a;
1836 struct ldb_val old_val;
1837 struct ldb_val new_val;
1838 TALLOC_CTX *mem_ctx;
1839 PyObject *ret;
1840 char *element_name;
1841 PyObject *val;
1842 Py_ssize_t size;
1843 int result;
1845 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1846 return NULL;
1848 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1849 old_val.length = size;
1851 if (result != 0) {
1852 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1853 return NULL;
1856 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1858 if (a == NULL) {
1859 Py_RETURN_NONE;
1862 mem_ctx = talloc_new(NULL);
1863 if (mem_ctx == NULL) {
1864 PyErr_NoMemory();
1865 return NULL;
1868 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1869 talloc_free(mem_ctx);
1870 Py_RETURN_NONE;
1873 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1875 talloc_free(mem_ctx);
1877 return ret;
1880 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1882 PyObject *py_base = Py_None;
1883 int scope = LDB_SCOPE_DEFAULT;
1884 char *expr = NULL;
1885 PyObject *py_attrs = Py_None;
1886 PyObject *py_controls = Py_None;
1887 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1888 int ret;
1889 struct ldb_result *res;
1890 struct ldb_request *req;
1891 const char **attrs;
1892 struct ldb_context *ldb_ctx;
1893 struct ldb_control **parsed_controls;
1894 struct ldb_dn *base;
1895 PyObject *py_ret;
1896 TALLOC_CTX *mem_ctx;
1898 /* type "int" rather than "enum" for "scope" is intentional */
1899 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1900 discard_const_p(char *, kwnames),
1901 &py_base, &scope, &expr, &py_attrs, &py_controls))
1902 return NULL;
1905 mem_ctx = talloc_new(NULL);
1906 if (mem_ctx == NULL) {
1907 PyErr_NoMemory();
1908 return NULL;
1910 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1912 if (py_attrs == Py_None) {
1913 attrs = NULL;
1914 } else {
1915 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1916 if (attrs == NULL) {
1917 talloc_free(mem_ctx);
1918 return NULL;
1922 if (py_base == Py_None) {
1923 base = ldb_get_default_basedn(ldb_ctx);
1924 } else {
1925 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1926 talloc_free(mem_ctx);
1927 return NULL;
1931 if (py_controls == Py_None) {
1932 parsed_controls = NULL;
1933 } else {
1934 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1935 if (controls == NULL) {
1936 talloc_free(mem_ctx);
1937 return NULL;
1939 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1940 talloc_free(controls);
1943 res = talloc_zero(mem_ctx, struct ldb_result);
1944 if (res == NULL) {
1945 PyErr_NoMemory();
1946 talloc_free(mem_ctx);
1947 return NULL;
1950 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1951 base,
1952 scope,
1953 expr,
1954 attrs,
1955 parsed_controls,
1956 res,
1957 ldb_search_default_callback,
1958 NULL);
1960 if (ret != LDB_SUCCESS) {
1961 talloc_free(mem_ctx);
1962 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1963 return NULL;
1966 talloc_steal(req, attrs);
1968 ret = ldb_request(ldb_ctx, req);
1970 if (ret == LDB_SUCCESS) {
1971 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1974 if (ret != LDB_SUCCESS) {
1975 talloc_free(mem_ctx);
1976 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1977 return NULL;
1980 py_ret = PyLdbResult_FromResult(res);
1982 talloc_free(mem_ctx);
1984 return py_ret;
1987 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1989 if (reply->py_iter != NULL) {
1990 DLIST_REMOVE(reply->py_iter->state.next, reply);
1991 if (reply->py_iter->state.result == reply) {
1992 reply->py_iter->state.result = NULL;
1994 reply->py_iter = NULL;
1997 if (reply->obj != NULL) {
1998 Py_DECREF(reply->obj);
1999 reply->obj = NULL;
2002 return 0;
2005 static int py_ldb_search_iterator_callback(struct ldb_request *req,
2006 struct ldb_reply *ares)
2008 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
2009 struct ldb_result result = { .msgs = NULL };
2010 struct py_ldb_search_iterator_reply *reply = NULL;
2012 if (ares == NULL) {
2013 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2016 if (ares->error != LDB_SUCCESS) {
2017 int ret = ares->error;
2018 TALLOC_FREE(ares);
2019 return ldb_request_done(req, ret);
2022 reply = talloc_zero(py_iter->mem_ctx,
2023 struct py_ldb_search_iterator_reply);
2024 if (reply == NULL) {
2025 TALLOC_FREE(ares);
2026 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2028 reply->py_iter = py_iter;
2029 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2031 switch (ares->type) {
2032 case LDB_REPLY_ENTRY:
2033 reply->obj = PyLdbMessage_FromMessage(ares->message);
2034 if (reply->obj == NULL) {
2035 TALLOC_FREE(ares);
2036 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2038 DLIST_ADD_END(py_iter->state.next, reply);
2039 TALLOC_FREE(ares);
2040 return LDB_SUCCESS;
2042 case LDB_REPLY_REFERRAL:
2043 reply->obj = PyStr_FromString(ares->referral);
2044 if (reply->obj == NULL) {
2045 TALLOC_FREE(ares);
2046 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2048 DLIST_ADD_END(py_iter->state.next, reply);
2049 TALLOC_FREE(ares);
2050 return LDB_SUCCESS;
2052 case LDB_REPLY_DONE:
2053 result = (struct ldb_result) { .controls = ares->controls };
2054 reply->obj = PyLdbResult_FromResult(&result);
2055 if (reply->obj == NULL) {
2056 TALLOC_FREE(ares);
2057 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2059 py_iter->state.result = reply;
2060 TALLOC_FREE(ares);
2061 return ldb_request_done(req, LDB_SUCCESS);
2064 TALLOC_FREE(ares);
2065 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2068 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2070 PyObject *py_base = Py_None;
2071 int scope = LDB_SCOPE_DEFAULT;
2072 int timeout = 0;
2073 char *expr = NULL;
2074 PyObject *py_attrs = Py_None;
2075 PyObject *py_controls = Py_None;
2076 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2077 int ret;
2078 const char **attrs;
2079 struct ldb_context *ldb_ctx;
2080 struct ldb_control **parsed_controls;
2081 struct ldb_dn *base;
2082 PyLdbSearchIteratorObject *py_iter;
2084 /* type "int" rather than "enum" for "scope" is intentional */
2085 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2086 discard_const_p(char *, kwnames),
2087 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2088 return NULL;
2090 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2091 if (py_iter == NULL) {
2092 PyErr_NoMemory();
2093 return NULL;
2095 py_iter->ldb = self;
2096 Py_INCREF(self);
2097 ZERO_STRUCT(py_iter->state);
2098 py_iter->mem_ctx = talloc_new(NULL);
2099 if (py_iter->mem_ctx == NULL) {
2100 Py_DECREF(py_iter);
2101 PyErr_NoMemory();
2102 return NULL;
2105 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2107 if (py_attrs == Py_None) {
2108 attrs = NULL;
2109 } else {
2110 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2111 if (attrs == NULL) {
2112 Py_DECREF(py_iter);
2113 PyErr_NoMemory();
2114 return NULL;
2118 if (py_base == Py_None) {
2119 base = ldb_get_default_basedn(ldb_ctx);
2120 } else {
2121 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2122 Py_DECREF(py_iter);
2123 PyErr_NoMemory();
2124 return NULL;
2128 if (py_controls == Py_None) {
2129 parsed_controls = NULL;
2130 } else {
2131 const char **controls = NULL;
2133 controls = PyList_AsStrList(py_iter->mem_ctx,
2134 py_controls, "controls");
2135 if (controls == NULL) {
2136 Py_DECREF(py_iter);
2137 PyErr_NoMemory();
2138 return NULL;
2141 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2142 py_iter->mem_ctx,
2143 controls);
2144 if (controls[0] != NULL && parsed_controls == NULL) {
2145 Py_DECREF(py_iter);
2146 PyErr_NoMemory();
2147 return NULL;
2149 talloc_free(controls);
2152 ret = ldb_build_search_req(&py_iter->state.req,
2153 ldb_ctx,
2154 py_iter->mem_ctx,
2155 base,
2156 scope,
2157 expr,
2158 attrs,
2159 parsed_controls,
2160 py_iter,
2161 py_ldb_search_iterator_callback,
2162 NULL);
2163 if (ret != LDB_SUCCESS) {
2164 Py_DECREF(py_iter);
2165 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2166 return NULL;
2169 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2171 ret = ldb_request(ldb_ctx, py_iter->state.req);
2172 if (ret != LDB_SUCCESS) {
2173 Py_DECREF(py_iter);
2174 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2175 return NULL;
2178 return (PyObject *)py_iter;
2181 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2183 char *name;
2184 void *data;
2186 if (!PyArg_ParseTuple(args, "s", &name))
2187 return NULL;
2189 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
2191 if (data == NULL)
2192 Py_RETURN_NONE;
2194 /* FIXME: More interpretation */
2196 Py_RETURN_TRUE;
2199 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2201 char *name;
2202 PyObject *data;
2204 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2205 return NULL;
2207 /* FIXME: More interpretation */
2209 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
2211 Py_RETURN_NONE;
2214 static PyObject *py_ldb_modules(PyLdbObject *self)
2216 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2217 PyObject *ret = PyList_New(0);
2218 struct ldb_module *mod;
2220 if (ret == NULL) {
2221 return PyErr_NoMemory();
2223 for (mod = ldb->modules; mod; mod = mod->next) {
2224 PyObject *item = PyLdbModule_FromModule(mod);
2225 int res = 0;
2226 if (item == NULL) {
2227 PyErr_SetString(PyExc_RuntimeError,
2228 "Failed to load LdbModule");
2229 Py_CLEAR(ret);
2230 return NULL;
2232 res = PyList_Append(ret, item);
2233 Py_CLEAR(item);
2234 if (res == -1) {
2235 Py_CLEAR(ret);
2236 return NULL;
2240 return ret;
2243 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2245 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2246 int type, ret;
2247 uint64_t value;
2249 if (!PyArg_ParseTuple(args, "i", &type))
2250 return NULL;
2252 /* FIXME: More interpretation */
2254 ret = ldb_sequence_number(ldb, type, &value);
2256 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2258 return PyLong_FromLongLong(value);
2262 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2263 .name = "TEST",
2264 .read_fn = ldb_handler_copy,
2265 .write_clear_fn = ldb_handler_copy,
2266 .write_hex_fn = ldb_handler_copy,
2269 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self)
2271 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2272 int ret;
2274 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2276 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2278 Py_RETURN_NONE;
2282 static PyMethodDef py_ldb_methods[] = {
2283 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2284 "S.set_debug(callback) -> None\n"
2285 "Set callback for LDB debug messages.\n"
2286 "The callback should accept a debug level and debug text." },
2287 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2288 "S.set_create_perms(mode) -> None\n"
2289 "Set mode to use when creating new LDB files." },
2290 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2291 "S.set_modules_dir(path) -> None\n"
2292 "Set path LDB should search for modules" },
2293 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2294 "S.transaction_start() -> None\n"
2295 "Start a new transaction." },
2296 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2297 "S.transaction_prepare_commit() -> None\n"
2298 "prepare to commit a new transaction (2-stage commit)." },
2299 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2300 "S.transaction_commit() -> None\n"
2301 "commit a new transaction." },
2302 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2303 "S.transaction_cancel() -> None\n"
2304 "cancel a new transaction." },
2305 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2306 NULL },
2307 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2308 NULL },
2309 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2310 NULL },
2311 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2312 NULL },
2313 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2314 NULL },
2315 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
2316 "S.connect(url, flags=0, options=None) -> None\n"
2317 "Connect to a LDB URL." },
2318 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
2319 "S.modify(message, controls=None, validate=False) -> None\n"
2320 "Modify an entry." },
2321 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
2322 "S.add(message, controls=None) -> None\n"
2323 "Add an entry." },
2324 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
2325 "S.delete(dn, controls=None) -> None\n"
2326 "Remove an entry." },
2327 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
2328 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2329 "Rename an entry." },
2330 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
2331 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2332 "Search in a database.\n"
2333 "\n"
2334 ":param base: Optional base DN to search\n"
2335 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2336 ":param expression: Optional search expression\n"
2337 ":param attrs: Attributes to return (defaults to all)\n"
2338 ":param controls: Optional list of controls\n"
2339 ":return: ldb.Result object\n"
2341 { "search_iterator", (PyCFunction)py_ldb_search_iterator, METH_VARARGS|METH_KEYWORDS,
2342 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2343 "Search in a database.\n"
2344 "\n"
2345 ":param base: Optional base DN to search\n"
2346 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2347 ":param expression: Optional search expression\n"
2348 ":param attrs: Attributes to return (defaults to all)\n"
2349 ":param controls: Optional list of controls\n"
2350 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2351 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2353 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2354 NULL },
2355 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2356 NULL },
2357 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2358 NULL },
2359 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2360 "S.parse_ldif(ldif) -> iter(messages)\n"
2361 "Parse a string formatted using LDIF." },
2362 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2363 "S.write_ldif(message, changetype) -> ldif\n"
2364 "Print the message as a string formatted using LDIF." },
2365 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2366 "S.msg_diff(Message) -> Message\n"
2367 "Return an LDB Message of the difference between two Message objects." },
2368 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2369 "S.get_opaque(name) -> value\n"
2370 "Get an opaque value set on this LDB connection. \n"
2371 ":note: The returned value may not be useful in Python."
2373 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2374 "S.set_opaque(name, value) -> None\n"
2375 "Set an opaque value on this LDB connection. \n"
2376 ":note: Passing incorrect values may cause crashes." },
2377 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2378 "S.modules() -> list\n"
2379 "Return the list of modules on this LDB connection " },
2380 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2381 "S.sequence_number(type) -> value\n"
2382 "Return the value of the sequence according to the requested type" },
2383 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2384 "S._register_test_extensions() -> None\n"
2385 "Register internal extensions used in testing" },
2386 { NULL },
2389 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2391 PyLdbModuleObject *ret;
2393 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2394 if (ret == NULL) {
2395 PyErr_NoMemory();
2396 return NULL;
2398 ret->mem_ctx = talloc_new(NULL);
2399 ret->mod = talloc_reference(ret->mem_ctx, mod);
2400 return (PyObject *)ret;
2403 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2405 struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules;
2406 if (mod == NULL) {
2407 Py_RETURN_NONE;
2409 return PyLdbModule_FromModule(mod);
2412 static PyGetSetDef py_ldb_getset[] = {
2414 .name = discard_const_p(char, "firstmodule"),
2415 .get = (getter)py_ldb_get_firstmodule,
2417 { .name = NULL },
2420 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2422 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2423 struct ldb_dn *dn;
2424 struct ldb_result *result;
2425 unsigned int count;
2426 int ret;
2428 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2429 return -1;
2432 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2433 NULL);
2434 if (ret != LDB_SUCCESS) {
2435 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2436 return -1;
2439 count = result->count;
2441 talloc_free(result);
2443 if (count > 1) {
2444 PyErr_Format(PyExc_RuntimeError,
2445 "Searching for [%s] dn gave %u results!",
2446 ldb_dn_get_linearized(dn),
2447 count);
2448 return -1;
2451 return count;
2454 static PySequenceMethods py_ldb_seq = {
2455 .sq_contains = (objobjproc)py_ldb_contains,
2458 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2460 PyLdbObject *ret;
2462 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2463 if (ret == NULL) {
2464 PyErr_NoMemory();
2465 return NULL;
2467 ret->mem_ctx = talloc_new(NULL);
2468 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2469 return (PyObject *)ret;
2472 static void py_ldb_dealloc(PyLdbObject *self)
2474 talloc_free(self->mem_ctx);
2475 Py_TYPE(self)->tp_free(self);
2478 static PyTypeObject PyLdb = {
2479 .tp_name = "ldb.Ldb",
2480 .tp_methods = py_ldb_methods,
2481 .tp_repr = (reprfunc)py_ldb_repr,
2482 .tp_new = py_ldb_new,
2483 .tp_init = (initproc)py_ldb_init,
2484 .tp_dealloc = (destructor)py_ldb_dealloc,
2485 .tp_getset = py_ldb_getset,
2486 .tp_getattro = PyObject_GenericGetAttr,
2487 .tp_basicsize = sizeof(PyLdbObject),
2488 .tp_doc = "Connection to a LDB database.",
2489 .tp_as_sequence = &py_ldb_seq,
2490 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2493 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2495 talloc_free(self->mem_ctx);
2496 Py_DECREF(self->msgs);
2497 Py_DECREF(self->referals);
2498 Py_DECREF(self->controls);
2499 Py_TYPE(self)->tp_free(self);
2502 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2504 Py_INCREF(self->msgs);
2505 return self->msgs;
2508 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2510 Py_INCREF(self->controls);
2511 return self->controls;
2514 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2516 Py_INCREF(self->referals);
2517 return self->referals;
2520 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2522 Py_ssize_t size;
2523 if (self->msgs == NULL) {
2524 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2525 return NULL;
2527 size = PyList_Size(self->msgs);
2528 return PyInt_FromLong(size);
2531 static PyGetSetDef py_ldb_result_getset[] = {
2533 .name = discard_const_p(char, "controls"),
2534 .get = (getter)py_ldb_result_get_controls,
2537 .name = discard_const_p(char, "msgs"),
2538 .get = (getter)py_ldb_result_get_msgs,
2541 .name = discard_const_p(char, "referals"),
2542 .get = (getter)py_ldb_result_get_referals,
2545 .name = discard_const_p(char, "count"),
2546 .get = (getter)py_ldb_result_get_count,
2548 { .name = NULL },
2551 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2553 return PyObject_GetIter(self->msgs);
2556 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2558 return PySequence_Size(self->msgs);
2561 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2563 return PySequence_GetItem(self->msgs, idx);
2566 static PySequenceMethods py_ldb_result_seq = {
2567 .sq_length = (lenfunc)py_ldb_result_len,
2568 .sq_item = (ssizeargfunc)py_ldb_result_find,
2571 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2573 return PyStr_FromString("<ldb result>");
2577 static PyTypeObject PyLdbResult = {
2578 .tp_name = "ldb.Result",
2579 .tp_repr = (reprfunc)py_ldb_result_repr,
2580 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2581 .tp_iter = (getiterfunc)py_ldb_result_iter,
2582 .tp_getset = py_ldb_result_getset,
2583 .tp_getattro = PyObject_GenericGetAttr,
2584 .tp_basicsize = sizeof(PyLdbResultObject),
2585 .tp_as_sequence = &py_ldb_result_seq,
2586 .tp_doc = "LDB result.",
2587 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2590 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2592 Py_XDECREF(self->state.exception);
2593 TALLOC_FREE(self->mem_ctx);
2594 ZERO_STRUCT(self->state);
2595 Py_DECREF(self->ldb);
2596 Py_TYPE(self)->tp_free(self);
2599 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2601 PyObject *py_ret = NULL;
2603 if (self->state.req == NULL) {
2604 PyErr_SetString(PyExc_RuntimeError,
2605 "ldb.SearchIterator request already finished");
2606 return NULL;
2610 * TODO: do we want a non-blocking mode?
2611 * In future we may add an optional 'nonblocking'
2612 * argument to search_iterator().
2614 * For now we keep it simple and wait for at
2615 * least one reply.
2618 while (self->state.next == NULL) {
2619 int ret;
2621 if (self->state.result != NULL) {
2623 * We (already) got a final result from the server.
2625 * We stop the iteration and let
2626 * py_ldb_search_iterator_result() will deliver
2627 * the result details.
2629 TALLOC_FREE(self->state.req);
2630 PyErr_SetNone(PyExc_StopIteration);
2631 return NULL;
2634 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2635 if (ret != LDB_SUCCESS) {
2636 struct ldb_context *ldb_ctx;
2637 TALLOC_FREE(self->state.req);
2638 ldb_ctx = pyldb_Ldb_AsLdbContext(self->ldb);
2640 * We stop the iteration and let
2641 * py_ldb_search_iterator_result() will deliver
2642 * the exception.
2644 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2645 ret, ldb_errstring(ldb_ctx));
2646 PyErr_SetNone(PyExc_StopIteration);
2647 return NULL;
2651 py_ret = self->state.next->obj;
2652 self->state.next->obj = NULL;
2653 /* no TALLOC_FREE() as self->state.next is a list */
2654 talloc_free(self->state.next);
2655 return py_ret;
2658 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self)
2660 PyObject *py_ret = NULL;
2662 if (self->state.req != NULL) {
2663 PyErr_SetString(PyExc_RuntimeError,
2664 "ldb.SearchIterator request running");
2665 return NULL;
2668 if (self->state.next != NULL) {
2669 PyErr_SetString(PyExc_RuntimeError,
2670 "ldb.SearchIterator not fully consumed.");
2671 return NULL;
2674 if (self->state.exception != NULL) {
2675 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2676 self->state.exception = NULL;
2677 return NULL;
2680 if (self->state.result == NULL) {
2681 PyErr_SetString(PyExc_RuntimeError,
2682 "ldb.SearchIterator result already consumed");
2683 return NULL;
2686 py_ret = self->state.result->obj;
2687 self->state.result->obj = NULL;
2688 TALLOC_FREE(self->state.result);
2689 return py_ret;
2692 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self)
2694 if (self->state.req == NULL) {
2695 PyErr_SetString(PyExc_RuntimeError,
2696 "ldb.SearchIterator request already finished");
2697 return NULL;
2700 Py_XDECREF(self->state.exception);
2701 TALLOC_FREE(self->mem_ctx);
2702 ZERO_STRUCT(self->state);
2703 Py_RETURN_NONE;
2706 static PyMethodDef py_ldb_search_iterator_methods[] = {
2707 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2708 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2709 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2710 "S.abandon()\n" },
2711 { NULL }
2714 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2716 return PyStr_FromString("<ldb search iterator>");
2719 static PyTypeObject PyLdbSearchIterator = {
2720 .tp_name = "ldb.SearchIterator",
2721 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2722 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2723 .tp_iter = PyObject_SelfIter,
2724 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2725 .tp_methods = py_ldb_search_iterator_methods,
2726 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2727 .tp_doc = "LDB search_iterator.",
2728 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2731 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2733 return PyStr_FromFormat("<ldb module '%s'>",
2734 pyldb_Module_AsModule(self)->ops->name);
2737 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2739 return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
2742 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2744 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2745 Py_RETURN_NONE;
2748 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2750 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2751 Py_RETURN_NONE;
2754 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2756 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2757 Py_RETURN_NONE;
2760 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2762 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2763 int ret, scope;
2764 struct ldb_request *req;
2765 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2766 struct ldb_module *mod;
2767 const char * const*attrs;
2769 /* type "int" rather than "enum" for "scope" is intentional */
2770 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2771 discard_const_p(char *, kwnames),
2772 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2773 return NULL;
2775 mod = self->mod;
2777 if (py_attrs == Py_None) {
2778 attrs = NULL;
2779 } else {
2780 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2781 if (attrs == NULL)
2782 return NULL;
2785 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2786 scope, NULL /* expr */, attrs,
2787 NULL /* controls */, NULL, NULL, NULL);
2789 talloc_steal(req, attrs);
2791 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2793 req->op.search.res = NULL;
2795 ret = mod->ops->search(mod, req);
2797 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2799 py_ret = PyLdbResult_FromResult(req->op.search.res);
2801 talloc_free(req);
2803 return py_ret;
2807 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2809 struct ldb_request *req;
2810 PyObject *py_message;
2811 int ret;
2812 struct ldb_module *mod;
2814 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2815 return NULL;
2817 req = talloc_zero(NULL, struct ldb_request);
2818 req->operation = LDB_ADD;
2819 req->op.add.message = pyldb_Message_AsMessage(py_message);
2821 mod = pyldb_Module_AsModule(self);
2822 ret = mod->ops->add(mod, req);
2824 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2826 Py_RETURN_NONE;
2829 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2831 int ret;
2832 struct ldb_request *req;
2833 PyObject *py_message;
2834 struct ldb_module *mod;
2836 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2837 return NULL;
2839 req = talloc_zero(NULL, struct ldb_request);
2840 req->operation = LDB_MODIFY;
2841 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2843 mod = pyldb_Module_AsModule(self);
2844 ret = mod->ops->modify(mod, req);
2846 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2848 Py_RETURN_NONE;
2851 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2853 int ret;
2854 struct ldb_request *req;
2855 PyObject *py_dn;
2857 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2858 return NULL;
2860 req = talloc_zero(NULL, struct ldb_request);
2861 req->operation = LDB_DELETE;
2862 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2864 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2866 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2868 Py_RETURN_NONE;
2871 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2873 int ret;
2874 struct ldb_request *req;
2875 PyObject *py_dn1, *py_dn2;
2877 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2878 return NULL;
2880 req = talloc_zero(NULL, struct ldb_request);
2882 req->operation = LDB_RENAME;
2883 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2884 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2886 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2888 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2890 Py_RETURN_NONE;
2893 static PyMethodDef py_ldb_module_methods[] = {
2894 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2895 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2896 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2897 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2898 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2899 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2900 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2901 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2902 { NULL },
2905 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2907 talloc_free(self->mem_ctx);
2908 PyObject_Del(self);
2911 static PyTypeObject PyLdbModule = {
2912 .tp_name = "ldb.LdbModule",
2913 .tp_methods = py_ldb_module_methods,
2914 .tp_repr = (reprfunc)py_ldb_module_repr,
2915 .tp_str = (reprfunc)py_ldb_module_str,
2916 .tp_basicsize = sizeof(PyLdbModuleObject),
2917 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2918 .tp_flags = Py_TPFLAGS_DEFAULT,
2919 .tp_doc = "LDB module (extension)",
2924 * Create a ldb_message_element from a Python object.
2926 * This will accept any sequence objects that contains strings, or
2927 * a string object.
2929 * A reference to set_obj will be borrowed.
2931 * @param mem_ctx Memory context
2932 * @param set_obj Python object to convert
2933 * @param flags ldb_message_element flags to set
2934 * @param attr_name Name of the attribute
2935 * @return New ldb_message_element, allocated as child of mem_ctx
2937 static struct ldb_message_element *PyObject_AsMessageElement(
2938 TALLOC_CTX *mem_ctx,
2939 PyObject *set_obj,
2940 unsigned int flags,
2941 const char *attr_name)
2943 struct ldb_message_element *me;
2944 const char *msg = NULL;
2945 Py_ssize_t size;
2946 int result;
2948 if (pyldb_MessageElement_Check(set_obj)) {
2949 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2950 /* We have to talloc_reference() the memory context, not the pointer
2951 * which may not actually be it's own context */
2952 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2953 return pyldb_MessageElement_AsMessageElement(set_obj);
2955 return NULL;
2958 me = talloc(mem_ctx, struct ldb_message_element);
2959 if (me == NULL) {
2960 PyErr_NoMemory();
2961 return NULL;
2964 me->name = talloc_strdup(me, attr_name);
2965 me->flags = flags;
2966 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2967 me->num_values = 1;
2968 me->values = talloc_array(me, struct ldb_val, me->num_values);
2969 if (PyBytes_Check(set_obj)) {
2970 char *_msg = NULL;
2971 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2972 if (result != 0) {
2973 talloc_free(me);
2974 return NULL;
2976 msg = _msg;
2977 } else {
2978 msg = PyStr_AsUTF8AndSize(set_obj, &size);
2979 if (msg == NULL) {
2980 talloc_free(me);
2981 return NULL;
2984 me->values[0].data = talloc_memdup(me,
2985 (const uint8_t *)msg,
2986 size+1);
2987 me->values[0].length = size;
2988 } else if (PySequence_Check(set_obj)) {
2989 Py_ssize_t i;
2990 me->num_values = PySequence_Size(set_obj);
2991 me->values = talloc_array(me, struct ldb_val, me->num_values);
2992 for (i = 0; i < me->num_values; i++) {
2993 PyObject *obj = PySequence_GetItem(set_obj, i);
2994 if (PyBytes_Check(obj)) {
2995 char *_msg = NULL;
2996 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
2997 if (result != 0) {
2998 talloc_free(me);
2999 return NULL;
3001 msg = _msg;
3002 } else if (PyUnicode_Check(obj)) {
3003 msg = PyStr_AsUTF8AndSize(obj, &size);
3004 if (msg == NULL) {
3005 talloc_free(me);
3006 return NULL;
3008 } else {
3009 PyErr_Format(PyExc_TypeError,
3010 "Expected string as element %zd in list", i);
3011 talloc_free(me);
3012 return NULL;
3014 me->values[i].data = talloc_memdup(me,
3015 (const uint8_t *)msg,
3016 size+1);
3017 me->values[i].length = size;
3019 } else {
3020 PyErr_Format(PyExc_TypeError,
3021 "String or List type expected for '%s' attribute", attr_name);
3022 talloc_free(me);
3023 me = NULL;
3026 return me;
3030 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
3031 struct ldb_message_element *me)
3033 Py_ssize_t i;
3034 PyObject *result;
3036 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
3037 result = PyList_New(me->num_values);
3039 for (i = 0; i < me->num_values; i++) {
3040 PyList_SetItem(result, i,
3041 PyObject_FromLdbValue(&me->values[i]));
3044 return result;
3047 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
3049 unsigned int i;
3050 if (!PyArg_ParseTuple(args, "I", &i))
3051 return NULL;
3052 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
3053 Py_RETURN_NONE;
3055 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
3058 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
3060 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3061 return PyInt_FromLong(el->flags);
3064 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3066 unsigned int flags;
3067 struct ldb_message_element *el;
3068 if (!PyArg_ParseTuple(args, "I", &flags))
3069 return NULL;
3071 el = pyldb_MessageElement_AsMessageElement(self);
3072 el->flags = flags;
3073 Py_RETURN_NONE;
3076 static PyMethodDef py_ldb_msg_element_methods[] = {
3077 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3078 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3079 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3080 { NULL },
3083 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3085 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3088 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3090 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3091 if (idx < 0 || idx >= el->num_values) {
3092 PyErr_SetString(PyExc_IndexError, "Out of range");
3093 return NULL;
3095 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3098 static PySequenceMethods py_ldb_msg_element_seq = {
3099 .sq_length = (lenfunc)py_ldb_msg_element_len,
3100 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3103 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3105 int ret;
3106 if (!pyldb_MessageElement_Check(other)) {
3107 Py_INCREF(Py_NotImplemented);
3108 return Py_NotImplemented;
3110 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3111 pyldb_MessageElement_AsMessageElement(other));
3112 return richcmp(ret, op);
3115 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3117 PyObject *el = ldb_msg_element_to_set(NULL,
3118 pyldb_MessageElement_AsMessageElement(self));
3119 PyObject *ret = PyObject_GetIter(el);
3120 Py_DECREF(el);
3121 return ret;
3124 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3126 PyLdbMessageElementObject *ret;
3127 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3128 if (ret == NULL) {
3129 PyErr_NoMemory();
3130 return NULL;
3132 ret->mem_ctx = talloc_new(NULL);
3133 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3134 PyErr_NoMemory();
3135 return NULL;
3137 ret->el = el;
3138 return (PyObject *)ret;
3141 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3143 PyObject *py_elements = NULL;
3144 struct ldb_message_element *el;
3145 unsigned int flags = 0;
3146 char *name = NULL;
3147 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3148 PyLdbMessageElementObject *ret;
3149 TALLOC_CTX *mem_ctx;
3150 const char *msg = NULL;
3151 Py_ssize_t size;
3152 int result;
3154 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3155 discard_const_p(char *, kwnames),
3156 &py_elements, &flags, &name))
3157 return NULL;
3159 mem_ctx = talloc_new(NULL);
3160 if (mem_ctx == NULL) {
3161 PyErr_NoMemory();
3162 return NULL;
3165 el = talloc_zero(mem_ctx, struct ldb_message_element);
3166 if (el == NULL) {
3167 PyErr_NoMemory();
3168 talloc_free(mem_ctx);
3169 return NULL;
3172 if (py_elements != NULL) {
3173 Py_ssize_t i;
3174 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3175 char *_msg = NULL;
3176 el->num_values = 1;
3177 el->values = talloc_array(el, struct ldb_val, 1);
3178 if (el->values == NULL) {
3179 talloc_free(mem_ctx);
3180 PyErr_NoMemory();
3181 return NULL;
3183 if (PyBytes_Check(py_elements)) {
3184 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3185 msg = _msg;
3186 } else {
3187 msg = PyStr_AsUTF8AndSize(py_elements, &size);
3188 result = (msg == NULL) ? -1 : 0;
3190 if (result != 0) {
3191 talloc_free(mem_ctx);
3192 return NULL;
3194 el->values[0].data = talloc_memdup(el->values,
3195 (const uint8_t *)msg, size + 1);
3196 el->values[0].length = size;
3197 } else if (PySequence_Check(py_elements)) {
3198 el->num_values = PySequence_Size(py_elements);
3199 el->values = talloc_array(el, struct ldb_val, el->num_values);
3200 if (el->values == NULL) {
3201 talloc_free(mem_ctx);
3202 PyErr_NoMemory();
3203 return NULL;
3205 for (i = 0; i < el->num_values; i++) {
3206 PyObject *item = PySequence_GetItem(py_elements, i);
3207 if (item == NULL) {
3208 talloc_free(mem_ctx);
3209 return NULL;
3211 if (PyBytes_Check(item)) {
3212 char *_msg = NULL;
3213 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3214 msg = _msg;
3215 } else if (PyUnicode_Check(item)) {
3216 msg = PyStr_AsUTF8AndSize(item, &size);
3217 result = (msg == NULL) ? -1 : 0;
3218 } else {
3219 PyErr_Format(PyExc_TypeError,
3220 "Expected string as element %zd in list", i);
3221 result = -1;
3223 if (result != 0) {
3224 talloc_free(mem_ctx);
3225 return NULL;
3227 el->values[i].data = talloc_memdup(el,
3228 (const uint8_t *)msg, size+1);
3229 el->values[i].length = size;
3231 } else {
3232 PyErr_SetString(PyExc_TypeError,
3233 "Expected string or list");
3234 talloc_free(mem_ctx);
3235 return NULL;
3239 el->flags = flags;
3240 el->name = talloc_strdup(el, name);
3242 ret = PyObject_New(PyLdbMessageElementObject, type);
3243 if (ret == NULL) {
3244 talloc_free(mem_ctx);
3245 return NULL;
3248 ret->mem_ctx = mem_ctx;
3249 ret->el = el;
3250 return (PyObject *)ret;
3253 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3255 char *element_str = NULL;
3256 Py_ssize_t i;
3257 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3258 PyObject *ret, *repr;
3260 for (i = 0; i < el->num_values; i++) {
3261 PyObject *o = py_ldb_msg_element_find(self, i);
3262 repr = PyObject_Repr(o);
3263 if (element_str == NULL)
3264 element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
3265 else
3266 element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
3267 Py_DECREF(repr);
3270 if (element_str != NULL) {
3271 ret = PyStr_FromFormat("MessageElement([%s])", element_str);
3272 talloc_free(element_str);
3273 } else {
3274 ret = PyStr_FromString("MessageElement([])");
3277 return ret;
3280 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3282 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3284 if (el->num_values == 1)
3285 return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3286 else
3287 Py_RETURN_NONE;
3290 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3292 talloc_free(self->mem_ctx);
3293 PyObject_Del(self);
3296 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3298 return wrap_text("MessageElementTextWrapper", self);
3301 static PyGetSetDef py_ldb_msg_element_getset[] = {
3303 .name = discard_const_p(char, "text"),
3304 .get = (getter)py_ldb_msg_element_get_text,
3306 { .name = NULL }
3309 static PyTypeObject PyLdbMessageElement = {
3310 .tp_name = "ldb.MessageElement",
3311 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3312 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3313 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3314 .tp_str = (reprfunc)py_ldb_msg_element_str,
3315 .tp_methods = py_ldb_msg_element_methods,
3316 .tp_getset = py_ldb_msg_element_getset,
3317 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3318 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3319 .tp_as_sequence = &py_ldb_msg_element_seq,
3320 .tp_new = py_ldb_msg_element_new,
3321 .tp_flags = Py_TPFLAGS_DEFAULT,
3322 .tp_doc = "An element of a Message",
3326 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3328 PyObject *py_ldb;
3329 PyObject *py_dict;
3330 PyObject *py_ret;
3331 struct ldb_message *msg;
3332 struct ldb_context *ldb_ctx;
3333 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3335 if (!PyArg_ParseTuple(args, "O!O!|I",
3336 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3337 &mod_flags)) {
3338 return NULL;
3341 if (!PyLdb_Check(py_ldb)) {
3342 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3343 return NULL;
3346 /* mask only flags we are going to use */
3347 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3348 if (!mod_flags) {
3349 PyErr_SetString(PyExc_ValueError,
3350 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3351 " expected as mod_flag value");
3352 return NULL;
3355 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
3357 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3358 if (!msg) {
3359 return NULL;
3362 py_ret = PyLdbMessage_FromMessage(msg);
3364 talloc_unlink(ldb_ctx, msg);
3366 return py_ret;
3369 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3371 char *name;
3372 if (!PyArg_ParseTuple(args, "s", &name))
3373 return NULL;
3375 ldb_msg_remove_attr(self->msg, name);
3377 Py_RETURN_NONE;
3380 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
3382 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3383 Py_ssize_t i, j = 0;
3384 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3385 if (msg->dn != NULL) {
3386 PyList_SetItem(obj, j, PyStr_FromString("dn"));
3387 j++;
3389 for (i = 0; i < msg->num_elements; i++) {
3390 PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
3391 j++;
3393 return obj;
3396 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3398 struct ldb_message_element *el;
3399 const char *name;
3400 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3401 name = PyStr_AsUTF8(py_name);
3402 if (name == NULL) {
3403 PyErr_SetNone(PyExc_TypeError);
3404 return NULL;
3406 if (!ldb_attr_cmp(name, "dn"))
3407 return pyldb_Dn_FromDn(msg->dn);
3408 el = ldb_msg_find_element(msg, name);
3409 if (el == NULL) {
3410 return NULL;
3412 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3415 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3417 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3418 if (ret == NULL) {
3419 PyErr_SetString(PyExc_KeyError, "No such element");
3420 return NULL;
3422 return ret;
3425 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3427 PyObject *def = NULL;
3428 const char *kwnames[] = { "name", "default", "idx", NULL };
3429 const char *name = NULL;
3430 int idx = -1;
3431 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3432 struct ldb_message_element *el;
3434 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3435 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3436 return NULL;
3439 if (strcasecmp(name, "dn") == 0) {
3440 return pyldb_Dn_FromDn(msg->dn);
3443 el = ldb_msg_find_element(msg, name);
3445 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3446 if (def != NULL) {
3447 Py_INCREF(def);
3448 return def;
3450 Py_RETURN_NONE;
3453 if (idx == -1) {
3454 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3457 return PyObject_FromLdbValue(&el->values[idx]);
3460 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
3462 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3463 Py_ssize_t i, j = 0;
3464 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3465 if (l == NULL) {
3466 return PyErr_NoMemory();
3468 if (msg->dn != NULL) {
3469 PyObject *value = NULL;
3470 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
3471 int res = 0;
3472 value = Py_BuildValue("(sO)", "dn", obj);
3473 Py_CLEAR(obj);
3474 if (value == NULL) {
3475 Py_CLEAR(l);
3476 return NULL;
3478 res = PyList_SetItem(l, 0, value);
3479 if (res == -1) {
3480 Py_CLEAR(l);
3481 return NULL;
3483 j++;
3485 for (i = 0; i < msg->num_elements; i++, j++) {
3486 PyObject *value = NULL;
3487 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3488 int res = 0;
3489 Py_CLEAR(py_el);
3490 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3491 if (value == NULL ) {
3492 Py_CLEAR(l);
3493 return NULL;
3495 res = PyList_SetItem(l, 0, value);
3496 if (res == -1) {
3497 Py_CLEAR(l);
3498 return NULL;
3501 return l;
3504 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
3506 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3507 Py_ssize_t i = 0;
3508 PyObject *l = PyList_New(msg->num_elements);
3509 for (i = 0; i < msg->num_elements; i++) {
3510 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3512 return l;
3515 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3517 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3518 PyLdbMessageElementObject *py_element;
3519 int i, ret;
3520 struct ldb_message_element *el;
3521 struct ldb_message_element *el_new;
3523 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3524 return NULL;
3526 el = py_element->el;
3527 if (el == NULL) {
3528 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3529 return NULL;
3532 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3533 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3535 /* now deep copy all attribute values */
3536 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3537 if (el_new->values == NULL) {
3538 PyErr_NoMemory();
3539 return NULL;
3541 el_new->num_values = el->num_values;
3543 for (i = 0; i < el->num_values; i++) {
3544 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3545 if (el_new->values[i].data == NULL
3546 && el->values[i].length != 0) {
3547 PyErr_NoMemory();
3548 return NULL;
3552 Py_RETURN_NONE;
3555 static PyMethodDef py_ldb_msg_methods[] = {
3556 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3557 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3558 "Class method to create ldb.Message object from Dictionary.\n"
3559 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3560 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3561 "S.keys() -> list\n\n"
3562 "Return sequence of all attribute names." },
3563 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3564 "S.remove(name)\n\n"
3565 "Remove all entries for attributes with the specified name."},
3566 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
3567 "msg.get(name,default=None,idx=None) -> string\n"
3568 "idx is the index into the values array\n"
3569 "if idx is None, then a list is returned\n"
3570 "if idx is not None, then the element with that index is returned\n"
3571 "if you pass the special name 'dn' then the DN object is returned\n"},
3572 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3573 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3574 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3575 "S.add(element)\n\n"
3576 "Add an element to this message." },
3577 { NULL },
3580 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3582 PyObject *list, *iter;
3584 list = py_ldb_msg_keys(self);
3585 iter = PyObject_GetIter(list);
3586 Py_DECREF(list);
3587 return iter;
3590 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3592 const char *attr_name;
3594 attr_name = PyStr_AsUTF8(name);
3595 if (attr_name == NULL) {
3596 PyErr_SetNone(PyExc_TypeError);
3597 return -1;
3600 if (value == NULL) {
3601 /* delitem */
3602 ldb_msg_remove_attr(self->msg, attr_name);
3603 } else {
3604 int ret;
3605 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3606 value, 0, attr_name);
3607 if (el == NULL) {
3608 return -1;
3610 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3611 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3612 if (ret != LDB_SUCCESS) {
3613 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3614 return -1;
3617 return 0;
3620 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3622 return pyldb_Message_AsMessage(self)->num_elements;
3625 static PyMappingMethods py_ldb_msg_mapping = {
3626 .mp_length = (lenfunc)py_ldb_msg_length,
3627 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3628 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3631 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3633 const char * const kwnames[] = { "dn", NULL };
3634 struct ldb_message *ret;
3635 TALLOC_CTX *mem_ctx;
3636 PyObject *pydn = NULL;
3637 PyLdbMessageObject *py_ret;
3639 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3640 discard_const_p(char *, kwnames),
3641 &pydn))
3642 return NULL;
3644 mem_ctx = talloc_new(NULL);
3645 if (mem_ctx == NULL) {
3646 PyErr_NoMemory();
3647 return NULL;
3650 ret = ldb_msg_new(mem_ctx);
3651 if (ret == NULL) {
3652 talloc_free(mem_ctx);
3653 PyErr_NoMemory();
3654 return NULL;
3657 if (pydn != NULL) {
3658 struct ldb_dn *dn;
3659 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3660 talloc_free(mem_ctx);
3661 return NULL;
3663 ret->dn = talloc_reference(ret, dn);
3666 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3667 if (py_ret == NULL) {
3668 PyErr_NoMemory();
3669 talloc_free(mem_ctx);
3670 return NULL;
3673 py_ret->mem_ctx = mem_ctx;
3674 py_ret->msg = ret;
3675 return (PyObject *)py_ret;
3678 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3680 PyLdbMessageObject *ret;
3682 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3683 if (ret == NULL) {
3684 PyErr_NoMemory();
3685 return NULL;
3687 ret->mem_ctx = talloc_new(NULL);
3688 ret->msg = talloc_reference(ret->mem_ctx, msg);
3689 return (PyObject *)ret;
3692 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3694 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3695 return pyldb_Dn_FromDn(msg->dn);
3698 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3700 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3701 if (!pyldb_Dn_Check(value)) {
3702 PyErr_SetString(PyExc_TypeError, "expected dn");
3703 return -1;
3706 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
3707 return 0;
3710 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3712 return wrap_text("MessageTextWrapper", self);
3715 static PyGetSetDef py_ldb_msg_getset[] = {
3717 .name = discard_const_p(char, "dn"),
3718 .get = (getter)py_ldb_msg_get_dn,
3719 .set = (setter)py_ldb_msg_set_dn,
3722 .name = discard_const_p(char, "text"),
3723 .get = (getter)py_ldb_msg_get_text,
3725 { .name = NULL },
3728 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3730 PyObject *dict = PyDict_New(), *ret, *repr;
3731 if (PyDict_Update(dict, (PyObject *)self) != 0)
3732 return NULL;
3733 repr = PyObject_Repr(dict);
3734 if (repr == NULL) {
3735 Py_DECREF(dict);
3736 return NULL;
3738 ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
3739 Py_DECREF(repr);
3740 Py_DECREF(dict);
3741 return ret;
3744 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3746 talloc_free(self->mem_ctx);
3747 PyObject_Del(self);
3750 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3751 PyLdbMessageObject *py_msg2, int op)
3753 struct ldb_message *msg1, *msg2;
3754 unsigned int i;
3755 int ret;
3757 if (!PyLdbMessage_Check(py_msg2)) {
3758 Py_INCREF(Py_NotImplemented);
3759 return Py_NotImplemented;
3762 msg1 = pyldb_Message_AsMessage(py_msg1),
3763 msg2 = pyldb_Message_AsMessage(py_msg2);
3765 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3766 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3767 if (ret != 0) {
3768 return richcmp(ret, op);
3772 ret = msg1->num_elements - msg2->num_elements;
3773 if (ret != 0) {
3774 return richcmp(ret, op);
3777 for (i = 0; i < msg1->num_elements; i++) {
3778 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3779 &msg2->elements[i]);
3780 if (ret != 0) {
3781 return richcmp(ret, op);
3784 ret = ldb_msg_element_compare(&msg1->elements[i],
3785 &msg2->elements[i]);
3786 if (ret != 0) {
3787 return richcmp(ret, op);
3791 return richcmp(0, op);
3794 static PyTypeObject PyLdbMessage = {
3795 .tp_name = "ldb.Message",
3796 .tp_methods = py_ldb_msg_methods,
3797 .tp_getset = py_ldb_msg_getset,
3798 .tp_as_mapping = &py_ldb_msg_mapping,
3799 .tp_basicsize = sizeof(PyLdbMessageObject),
3800 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3801 .tp_new = py_ldb_msg_new,
3802 .tp_repr = (reprfunc)py_ldb_msg_repr,
3803 .tp_flags = Py_TPFLAGS_DEFAULT,
3804 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3805 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3806 .tp_doc = "A LDB Message",
3809 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3811 PyLdbTreeObject *ret;
3813 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3814 if (ret == NULL) {
3815 PyErr_NoMemory();
3816 return NULL;
3819 ret->mem_ctx = talloc_new(NULL);
3820 ret->tree = talloc_reference(ret->mem_ctx, tree);
3821 return (PyObject *)ret;
3824 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3826 talloc_free(self->mem_ctx);
3827 PyObject_Del(self);
3830 static PyTypeObject PyLdbTree = {
3831 .tp_name = "ldb.Tree",
3832 .tp_basicsize = sizeof(PyLdbTreeObject),
3833 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3834 .tp_flags = Py_TPFLAGS_DEFAULT,
3835 .tp_doc = "A search tree",
3838 /* Ldb_module */
3839 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3841 PyObject *py_ldb = (PyObject *)mod->private_data;
3842 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3844 py_base = pyldb_Dn_FromDn(req->op.search.base);
3846 if (py_base == NULL)
3847 return LDB_ERR_OPERATIONS_ERROR;
3849 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3851 if (py_tree == NULL)
3852 return LDB_ERR_OPERATIONS_ERROR;
3854 if (req->op.search.attrs == NULL) {
3855 py_attrs = Py_None;
3856 } else {
3857 int i, len;
3858 for (len = 0; req->op.search.attrs[len]; len++);
3859 py_attrs = PyList_New(len);
3860 for (i = 0; i < len; i++)
3861 PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
3864 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3865 discard_const_p(char, "OiOO"),
3866 py_base, req->op.search.scope, py_tree, py_attrs);
3868 Py_DECREF(py_attrs);
3869 Py_DECREF(py_tree);
3870 Py_DECREF(py_base);
3872 if (py_result == NULL) {
3873 return LDB_ERR_PYTHON_EXCEPTION;
3876 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3877 if (req->op.search.res == NULL) {
3878 return LDB_ERR_PYTHON_EXCEPTION;
3881 Py_DECREF(py_result);
3883 return LDB_SUCCESS;
3886 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3888 PyObject *py_ldb = (PyObject *)mod->private_data;
3889 PyObject *py_result, *py_msg;
3891 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3893 if (py_msg == NULL) {
3894 return LDB_ERR_OPERATIONS_ERROR;
3897 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3898 discard_const_p(char, "O"),
3899 py_msg);
3901 Py_DECREF(py_msg);
3903 if (py_result == NULL) {
3904 return LDB_ERR_PYTHON_EXCEPTION;
3907 Py_DECREF(py_result);
3909 return LDB_SUCCESS;
3912 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3914 PyObject *py_ldb = (PyObject *)mod->private_data;
3915 PyObject *py_result, *py_msg;
3917 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3919 if (py_msg == NULL) {
3920 return LDB_ERR_OPERATIONS_ERROR;
3923 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3924 discard_const_p(char, "O"),
3925 py_msg);
3927 Py_DECREF(py_msg);
3929 if (py_result == NULL) {
3930 return LDB_ERR_PYTHON_EXCEPTION;
3933 Py_DECREF(py_result);
3935 return LDB_SUCCESS;
3938 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3940 PyObject *py_ldb = (PyObject *)mod->private_data;
3941 PyObject *py_result, *py_dn;
3943 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3945 if (py_dn == NULL)
3946 return LDB_ERR_OPERATIONS_ERROR;
3948 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3949 discard_const_p(char, "O"),
3950 py_dn);
3952 if (py_result == NULL) {
3953 return LDB_ERR_PYTHON_EXCEPTION;
3956 Py_DECREF(py_result);
3958 return LDB_SUCCESS;
3961 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3963 PyObject *py_ldb = (PyObject *)mod->private_data;
3964 PyObject *py_result, *py_olddn, *py_newdn;
3966 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3968 if (py_olddn == NULL)
3969 return LDB_ERR_OPERATIONS_ERROR;
3971 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3973 if (py_newdn == NULL)
3974 return LDB_ERR_OPERATIONS_ERROR;
3976 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3977 discard_const_p(char, "OO"),
3978 py_olddn, py_newdn);
3980 Py_DECREF(py_olddn);
3981 Py_DECREF(py_newdn);
3983 if (py_result == NULL) {
3984 return LDB_ERR_PYTHON_EXCEPTION;
3987 Py_DECREF(py_result);
3989 return LDB_SUCCESS;
3992 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3994 PyObject *py_ldb = (PyObject *)mod->private_data;
3995 PyObject *py_result;
3997 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3998 discard_const_p(char, ""));
4000 Py_XDECREF(py_result);
4002 return LDB_ERR_OPERATIONS_ERROR;
4005 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
4007 PyObject *py_ldb = (PyObject *)mod->private_data;
4008 PyObject *py_result;
4010 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
4011 discard_const_p(char, ""));
4013 Py_XDECREF(py_result);
4015 return LDB_ERR_OPERATIONS_ERROR;
4018 static int py_module_start_transaction(struct ldb_module *mod)
4020 PyObject *py_ldb = (PyObject *)mod->private_data;
4021 PyObject *py_result;
4023 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
4024 discard_const_p(char, ""));
4026 if (py_result == NULL) {
4027 return LDB_ERR_PYTHON_EXCEPTION;
4030 Py_DECREF(py_result);
4032 return LDB_SUCCESS;
4035 static int py_module_end_transaction(struct ldb_module *mod)
4037 PyObject *py_ldb = (PyObject *)mod->private_data;
4038 PyObject *py_result;
4040 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
4041 discard_const_p(char, ""));
4043 if (py_result == NULL) {
4044 return LDB_ERR_PYTHON_EXCEPTION;
4047 Py_DECREF(py_result);
4049 return LDB_SUCCESS;
4052 static int py_module_del_transaction(struct ldb_module *mod)
4054 PyObject *py_ldb = (PyObject *)mod->private_data;
4055 PyObject *py_result;
4057 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
4058 discard_const_p(char, ""));
4060 if (py_result == NULL) {
4061 return LDB_ERR_PYTHON_EXCEPTION;
4064 Py_DECREF(py_result);
4066 return LDB_SUCCESS;
4069 static int py_module_destructor(struct ldb_module *mod)
4071 Py_DECREF((PyObject *)mod->private_data);
4072 return 0;
4075 static int py_module_init(struct ldb_module *mod)
4077 PyObject *py_class = (PyObject *)mod->ops->private_data;
4078 PyObject *py_result, *py_next, *py_ldb;
4080 py_ldb = PyLdb_FromLdbContext(mod->ldb);
4082 if (py_ldb == NULL)
4083 return LDB_ERR_OPERATIONS_ERROR;
4085 py_next = PyLdbModule_FromModule(mod->next);
4087 if (py_next == NULL)
4088 return LDB_ERR_OPERATIONS_ERROR;
4090 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
4091 py_ldb, py_next);
4093 if (py_result == NULL) {
4094 return LDB_ERR_PYTHON_EXCEPTION;
4097 mod->private_data = py_result;
4099 talloc_set_destructor(mod, py_module_destructor);
4101 return ldb_next_init(mod);
4104 static PyObject *py_register_module(PyObject *module, PyObject *args)
4106 int ret;
4107 struct ldb_module_ops *ops;
4108 PyObject *input;
4110 if (!PyArg_ParseTuple(args, "O", &input))
4111 return NULL;
4113 ops = talloc_zero(NULL, struct ldb_module_ops);
4114 if (ops == NULL) {
4115 PyErr_NoMemory();
4116 return NULL;
4119 ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
4121 Py_INCREF(input);
4122 ops->private_data = input;
4123 ops->init_context = py_module_init;
4124 ops->search = py_module_search;
4125 ops->add = py_module_add;
4126 ops->modify = py_module_modify;
4127 ops->del = py_module_del;
4128 ops->rename = py_module_rename;
4129 ops->request = py_module_request;
4130 ops->extended = py_module_extended;
4131 ops->start_transaction = py_module_start_transaction;
4132 ops->end_transaction = py_module_end_transaction;
4133 ops->del_transaction = py_module_del_transaction;
4135 ret = ldb_register_module(ops);
4136 if (ret != LDB_SUCCESS) {
4137 TALLOC_FREE(ops);
4140 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4142 Py_RETURN_NONE;
4145 static PyObject *py_timestring(PyObject *module, PyObject *args)
4147 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4148 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4149 long int t_val;
4150 char *tresult;
4151 PyObject *ret;
4152 if (!PyArg_ParseTuple(args, "l", &t_val))
4153 return NULL;
4154 tresult = ldb_timestring(NULL, (time_t) t_val);
4155 ret = PyStr_FromString(tresult);
4156 talloc_free(tresult);
4157 return ret;
4160 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4162 char *str;
4163 if (!PyArg_ParseTuple(args, "s", &str))
4164 return NULL;
4166 return PyInt_FromLong(ldb_string_to_time(str));
4169 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4171 char *name;
4172 if (!PyArg_ParseTuple(args, "s", &name))
4173 return NULL;
4174 return PyBool_FromLong(ldb_valid_attr_name(name));
4178 encode a string using RFC2254 rules
4180 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4182 char *str, *encoded;
4183 Py_ssize_t size = 0;
4184 struct ldb_val val;
4185 PyObject *ret;
4187 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4188 return NULL;
4189 val.data = (uint8_t *)str;
4190 val.length = size;
4192 encoded = ldb_binary_encode(NULL, val);
4193 if (encoded == NULL) {
4194 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4195 return NULL;
4197 ret = PyStr_FromString(encoded);
4198 talloc_free(encoded);
4199 return ret;
4203 decode a string using RFC2254 rules
4205 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4207 char *str;
4208 struct ldb_val val;
4209 PyObject *ret;
4211 if (!PyArg_ParseTuple(args, "s", &str))
4212 return NULL;
4214 val = ldb_binary_decode(NULL, str);
4215 if (val.data == NULL) {
4216 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4217 return NULL;
4219 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4220 talloc_free(val.data);
4221 return ret;
4224 static PyMethodDef py_ldb_global_methods[] = {
4225 { "register_module", py_register_module, METH_VARARGS,
4226 "S.register_module(module) -> None\n\n"
4227 "Register a LDB module."},
4228 { "timestring", py_timestring, METH_VARARGS,
4229 "S.timestring(int) -> string\n\n"
4230 "Generate a LDAP time string from a UNIX timestamp" },
4231 { "string_to_time", py_string_to_time, METH_VARARGS,
4232 "S.string_to_time(string) -> int\n\n"
4233 "Parse a LDAP time string into a UNIX timestamp." },
4234 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4235 "S.valid_attr_name(name) -> bool\n\nn"
4236 "Check whether the supplied name is a valid attribute name." },
4237 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
4238 "S.open() -> Ldb\n\n"
4239 "Open a new LDB context." },
4240 { "binary_encode", py_binary_encode, METH_VARARGS,
4241 "S.binary_encode(string) -> string\n\n"
4242 "Perform a RFC2254 binary encoding on a string" },
4243 { "binary_decode", py_binary_decode, METH_VARARGS,
4244 "S.binary_decode(string) -> string\n\n"
4245 "Perform a RFC2254 binary decode on a string" },
4246 { NULL }
4249 #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."
4251 #if PY_MAJOR_VERSION >= 3
4252 static struct PyModuleDef moduledef = {
4253 PyModuleDef_HEAD_INIT,
4254 .m_name = "ldb",
4255 .m_doc = MODULE_DOC,
4256 .m_size = -1,
4257 .m_methods = py_ldb_global_methods,
4259 #endif
4261 static PyObject* module_init(void)
4263 PyObject *m;
4265 PyLdbBytesType.tp_base = &PyBytes_Type;
4266 if (PyType_Ready(&PyLdbBytesType) < 0) {
4267 return NULL;
4270 if (PyType_Ready(&PyLdbDn) < 0)
4271 return NULL;
4273 if (PyType_Ready(&PyLdbMessage) < 0)
4274 return NULL;
4276 if (PyType_Ready(&PyLdbMessageElement) < 0)
4277 return NULL;
4279 if (PyType_Ready(&PyLdb) < 0)
4280 return NULL;
4282 if (PyType_Ready(&PyLdbModule) < 0)
4283 return NULL;
4285 if (PyType_Ready(&PyLdbTree) < 0)
4286 return NULL;
4288 if (PyType_Ready(&PyLdbResult) < 0)
4289 return NULL;
4291 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4292 return NULL;
4294 if (PyType_Ready(&PyLdbControl) < 0)
4295 return NULL;
4297 #if PY_MAJOR_VERSION >= 3
4298 m = PyModule_Create(&moduledef);
4299 #else
4300 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4301 #endif
4302 if (m == NULL)
4303 return NULL;
4305 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4307 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4308 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4309 ADD_LDB_INT(SEQ_NEXT);
4310 ADD_LDB_INT(SCOPE_DEFAULT);
4311 ADD_LDB_INT(SCOPE_BASE);
4312 ADD_LDB_INT(SCOPE_ONELEVEL);
4313 ADD_LDB_INT(SCOPE_SUBTREE);
4315 ADD_LDB_INT(CHANGETYPE_NONE);
4316 ADD_LDB_INT(CHANGETYPE_ADD);
4317 ADD_LDB_INT(CHANGETYPE_DELETE);
4318 ADD_LDB_INT(CHANGETYPE_MODIFY);
4320 ADD_LDB_INT(FLAG_MOD_ADD);
4321 ADD_LDB_INT(FLAG_MOD_REPLACE);
4322 ADD_LDB_INT(FLAG_MOD_DELETE);
4324 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4325 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4326 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4327 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4329 ADD_LDB_INT(SUCCESS);
4330 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4331 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4332 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4333 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4334 ADD_LDB_INT(ERR_COMPARE_FALSE);
4335 ADD_LDB_INT(ERR_COMPARE_TRUE);
4336 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4337 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4338 ADD_LDB_INT(ERR_REFERRAL);
4339 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4340 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4341 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4342 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4343 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4344 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4345 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4346 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4347 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4348 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4349 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4350 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4351 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4352 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4353 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4354 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4355 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4356 ADD_LDB_INT(ERR_BUSY);
4357 ADD_LDB_INT(ERR_UNAVAILABLE);
4358 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4359 ADD_LDB_INT(ERR_LOOP_DETECT);
4360 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4361 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4362 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4363 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4364 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4365 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4366 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4367 ADD_LDB_INT(ERR_OTHER);
4369 ADD_LDB_INT(FLG_RDONLY);
4370 ADD_LDB_INT(FLG_NOSYNC);
4371 ADD_LDB_INT(FLG_RECONNECT);
4372 ADD_LDB_INT(FLG_NOMMAP);
4373 ADD_LDB_INT(FLG_SHOW_BINARY);
4374 ADD_LDB_INT(FLG_ENABLE_TRACING);
4375 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4378 /* Historical misspelling */
4379 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4381 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4383 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4384 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4386 Py_INCREF(&PyLdb);
4387 Py_INCREF(&PyLdbDn);
4388 Py_INCREF(&PyLdbModule);
4389 Py_INCREF(&PyLdbMessage);
4390 Py_INCREF(&PyLdbMessageElement);
4391 Py_INCREF(&PyLdbTree);
4392 Py_INCREF(&PyLdbResult);
4393 Py_INCREF(&PyLdbControl);
4395 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4396 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4397 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4398 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4399 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4400 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4401 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4403 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4405 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4407 ADD_LDB_STRING(SYNTAX_DN);
4408 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4409 ADD_LDB_STRING(SYNTAX_INTEGER);
4410 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4411 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4412 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4413 ADD_LDB_STRING(OID_COMPARATOR_AND);
4414 ADD_LDB_STRING(OID_COMPARATOR_OR);
4416 return m;
4419 #if PY_MAJOR_VERSION >= 3
4420 PyMODINIT_FUNC PyInit_ldb(void);
4421 PyMODINIT_FUNC PyInit_ldb(void)
4423 return module_init();
4425 #else
4426 void initldb(void);
4427 void initldb(void)
4429 module_init();
4431 #endif