s4:rpc_server: fix DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN negotiation to match Windows
[Samba.git] / lib / ldb / pyldb.c
blobb417d4cf754d8add2b94ffcbabcc2407a119ad0c
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 static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
96 PyObject* result = NULL;
97 PyObject* args = NULL;
98 args = Py_BuildValue("(y#)", msg, size);
99 result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
100 Py_DECREF(args);
101 return result;
103 #else
104 #define PyStr_Check PyString_Check
105 #define PyStr_FromString PyString_FromString
106 #define PyStr_FromStringAndSize PyString_FromStringAndSize
107 #define PyStr_FromFormat PyString_FromFormat
108 #define PyStr_FromFormatV PyString_FromFormatV
109 #define PyStr_AsUTF8 PyString_AsString
110 #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
112 const char *PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr);
113 const char *
114 PyStr_AsUTF8AndSize(PyObject *pystr, Py_ssize_t *sizeptr)
116 const char * ret = PyString_AsString(pystr);
117 if (ret == NULL)
118 return NULL;
119 *sizeptr = PyString_Size(pystr);
120 return ret;
122 #endif
124 static PyObject *richcmp(int cmp_val, int op)
126 int ret;
127 switch (op) {
128 case Py_LT: ret = cmp_val < 0; break;
129 case Py_LE: ret = cmp_val <= 0; break;
130 case Py_EQ: ret = cmp_val == 0; break;
131 case Py_NE: ret = cmp_val != 0; break;
132 case Py_GT: ret = cmp_val > 0; break;
133 case Py_GE: ret = cmp_val >= 0; break;
134 default:
135 Py_INCREF(Py_NotImplemented);
136 return Py_NotImplemented;
138 return PyBool_FromLong(ret);
142 static PyObject *py_ldb_control_str(PyLdbControlObject *self)
144 if (self->data != NULL) {
145 char* control = ldb_control_to_string(self->mem_ctx, self->data);
146 if (control == NULL) {
147 PyErr_NoMemory();
148 return NULL;
150 return PyStr_FromString(control);
151 } else {
152 return PyStr_FromString("ldb control");
156 static void py_ldb_control_dealloc(PyLdbControlObject *self)
158 if (self->mem_ctx != NULL) {
159 talloc_free(self->mem_ctx);
161 self->data = NULL;
162 Py_TYPE(self)->tp_free(self);
165 /* Create a text (rather than bytes) interface for a LDB result object */
166 static PyObject *wrap_text(const char *type, PyObject *wrapped)
168 PyObject *mod, *cls, *constructor, *inst;
169 mod = PyImport_ImportModule("_ldb_text");
170 if (mod == NULL)
171 return NULL;
172 cls = PyObject_GetAttrString(mod, type);
173 Py_DECREF(mod);
174 if (cls == NULL) {
175 Py_DECREF(mod);
176 return NULL;
178 constructor = PyObject_GetAttrString(cls, "_wrap");
179 Py_DECREF(cls);
180 if (constructor == NULL) {
181 return NULL;
183 inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
184 Py_DECREF(constructor);
185 return inst;
188 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self)
190 return PyStr_FromString(self->data->oid);
193 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self)
195 return PyBool_FromLong(self->data->critical);
198 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
200 if (PyObject_IsTrue(value)) {
201 self->data->critical = true;
202 } else {
203 self->data->critical = false;
205 return 0;
208 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
210 char *data = NULL;
211 const char * const kwnames[] = { "ldb", "data", NULL };
212 struct ldb_control *parsed_controls;
213 PyLdbControlObject *ret;
214 PyObject *py_ldb;
215 TALLOC_CTX *mem_ctx;
216 struct ldb_context *ldb_ctx;
218 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
219 discard_const_p(char *, kwnames),
220 &PyLdb, &py_ldb, &data))
221 return NULL;
223 mem_ctx = talloc_new(NULL);
224 if (mem_ctx == NULL) {
225 PyErr_NoMemory();
226 return NULL;
229 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
230 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
232 if (!parsed_controls) {
233 talloc_free(mem_ctx);
234 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
235 return NULL;
238 ret = PyObject_New(PyLdbControlObject, type);
239 if (ret == NULL) {
240 PyErr_NoMemory();
241 talloc_free(mem_ctx);
242 return NULL;
245 ret->mem_ctx = mem_ctx;
247 ret->data = talloc_move(mem_ctx, &parsed_controls);
248 if (ret->data == NULL) {
249 Py_DECREF(ret);
250 PyErr_NoMemory();
251 talloc_free(mem_ctx);
252 return NULL;
255 return (PyObject *)ret;
258 static PyGetSetDef py_ldb_control_getset[] = {
259 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL },
260 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL },
261 { NULL }
264 static PyTypeObject PyLdbControl = {
265 .tp_name = "ldb.control",
266 .tp_dealloc = (destructor)py_ldb_control_dealloc,
267 .tp_getattro = PyObject_GenericGetAttr,
268 .tp_basicsize = sizeof(PyLdbControlObject),
269 .tp_getset = py_ldb_control_getset,
270 .tp_doc = "LDB control.",
271 .tp_str = (reprfunc)py_ldb_control_str,
272 .tp_new = py_ldb_control_new,
273 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
276 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
278 if (ret == LDB_ERR_PYTHON_EXCEPTION)
279 return; /* Python exception should already be set, just keep that */
281 PyErr_SetObject(error,
282 Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
283 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
285 static PyObject *py_ldb_bytes_str(PyBytesObject *self)
287 char *msg = NULL;
288 Py_ssize_t size;
289 int result = 0;
290 if (!PyBytes_Check(self)) {
291 PyErr_Format(PyExc_TypeError,"Unexpected type");
292 return NULL;
294 result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
295 if (result != 0) {
296 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
297 return NULL;
299 return PyUnicode_FromStringAndSize(msg, size);
302 static PyTypeObject PyLdbBytesType = {
303 PyVarObject_HEAD_INIT(NULL, 0)
304 .tp_name = "ldb.bytes",
305 .tp_doc = "str/bytes (with custom str)",
306 .tp_str = (reprfunc)py_ldb_bytes_str,
307 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
310 static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
312 return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
315 static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
317 return PyStr_FromStringAndSize((const char *)val->data, val->length);
321 * Create a Python object from a ldb_result.
323 * @param result LDB result to convert
324 * @return Python object with converted result (a list object)
326 static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
328 TALLOC_CTX *ctl_ctx = talloc_new(NULL);
329 PyLdbControlObject *ctrl;
330 if (ctl_ctx == NULL) {
331 PyErr_NoMemory();
332 return NULL;
335 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
336 if (ctrl == NULL) {
337 talloc_free(ctl_ctx);
338 PyErr_NoMemory();
339 return NULL;
341 ctrl->mem_ctx = ctl_ctx;
342 ctrl->data = talloc_steal(ctrl->mem_ctx, control);
343 if (ctrl->data == NULL) {
344 Py_DECREF(ctrl);
345 PyErr_NoMemory();
346 return NULL;
348 return (PyObject*) ctrl;
352 * Create a Python object from a ldb_result.
354 * @param result LDB result to convert
355 * @return Python object with converted result (a list object)
357 static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
359 PyLdbResultObject *ret;
360 PyObject *list, *controls, *referals;
361 Py_ssize_t i;
363 if (result == NULL) {
364 Py_RETURN_NONE;
367 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
368 if (ret == NULL) {
369 PyErr_NoMemory();
370 return NULL;
373 list = PyList_New(result->count);
374 if (list == NULL) {
375 PyErr_NoMemory();
376 Py_DECREF(ret);
377 return NULL;
380 for (i = 0; i < result->count; i++) {
381 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
384 ret->mem_ctx = talloc_new(NULL);
385 if (ret->mem_ctx == NULL) {
386 Py_DECREF(list);
387 Py_DECREF(ret);
388 PyErr_NoMemory();
389 return NULL;
392 ret->msgs = list;
394 if (result->controls) {
395 i = 0;
396 while (result->controls[i]) {
397 i++;
399 controls = PyList_New(i);
400 if (controls == NULL) {
401 Py_DECREF(ret);
402 PyErr_NoMemory();
403 return NULL;
405 for (i=0; result->controls[i]; i++) {
406 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
407 if (ctrl == NULL) {
408 Py_DECREF(ret);
409 Py_DECREF(controls);
410 PyErr_NoMemory();
411 return NULL;
413 PyList_SetItem(controls, i, ctrl);
415 } else {
417 * No controls so we keep an empty list
419 controls = PyList_New(0);
420 if (controls == NULL) {
421 Py_DECREF(ret);
422 PyErr_NoMemory();
423 return NULL;
427 ret->controls = controls;
429 i = 0;
431 while (result->refs && result->refs[i]) {
432 i++;
435 referals = PyList_New(i);
436 if (referals == NULL) {
437 Py_DECREF(ret);
438 PyErr_NoMemory();
439 return NULL;
442 for (i = 0;result->refs && result->refs[i]; i++) {
443 PyList_SetItem(referals, i, PyStr_FromString(result->refs[i]));
445 ret->referals = referals;
446 return (PyObject *)ret;
450 * Create a LDB Result from a Python object.
451 * If conversion fails, NULL will be returned and a Python exception set.
453 * Note: the result object only includes the messages at the moment; extended
454 * result, controls and referrals are ignored.
456 * @param mem_ctx Memory context in which to allocate the LDB Result
457 * @param obj Python object to convert
458 * @return a ldb_result, or NULL if the conversion failed
460 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
461 PyObject *obj)
463 struct ldb_result *res;
464 Py_ssize_t i;
466 if (obj == Py_None)
467 return NULL;
469 res = talloc_zero(mem_ctx, struct ldb_result);
470 res->count = PyList_Size(obj);
471 res->msgs = talloc_array(res, struct ldb_message *, res->count);
472 for (i = 0; i < res->count; i++) {
473 PyObject *item = PyList_GetItem(obj, i);
474 res->msgs[i] = pyldb_Message_AsMessage(item);
476 return res;
479 static PyObject *py_ldb_dn_validate(PyLdbDnObject *self)
481 return PyBool_FromLong(ldb_dn_validate(self->dn));
484 static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self)
486 return PyBool_FromLong(ldb_dn_is_valid(self->dn));
489 static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self)
491 return PyBool_FromLong(ldb_dn_is_special(self->dn));
494 static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self)
496 return PyBool_FromLong(ldb_dn_is_null(self->dn));
499 static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self)
501 return PyStr_FromString(ldb_dn_get_casefold(self->dn));
504 static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
506 return PyStr_FromString(ldb_dn_get_linearized(self->dn));
509 static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self)
511 return PyStr_FromString(ldb_dn_canonical_string(self->dn, self->dn));
514 static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self)
516 return PyStr_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
519 static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
521 const char * const kwnames[] = { "mode", NULL };
522 int mode = 1;
523 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
524 discard_const_p(char *, kwnames),
525 &mode))
526 return NULL;
527 return PyStr_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
530 static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
532 char *name;
533 const struct ldb_val *val;
535 if (!PyArg_ParseTuple(args, "s", &name))
536 return NULL;
537 val = ldb_dn_get_extended_component(self->dn, name);
538 if (val == NULL) {
539 Py_RETURN_NONE;
542 return PyBytes_FromStringAndSize((const char *)val->data, val->length);
545 static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
547 char *name;
548 int err;
549 uint8_t *value = NULL;
550 Py_ssize_t size = 0;
552 if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
553 return NULL;
555 if (value == NULL) {
556 err = ldb_dn_set_extended_component(self->dn, name, NULL);
557 } else {
558 struct ldb_val val;
559 val.data = (uint8_t *)value;
560 val.length = size;
561 err = ldb_dn_set_extended_component(self->dn, name, &val);
564 if (err != LDB_SUCCESS) {
565 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
566 return NULL;
569 Py_RETURN_NONE;
572 static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
574 PyObject *str = PyStr_FromString(ldb_dn_get_linearized(self->dn));
575 PyObject *repr, *result;
576 if (str == NULL)
577 return NULL;
578 repr = PyObject_Repr(str);
579 if (repr == NULL) {
580 Py_DECREF(str);
581 return NULL;
583 result = PyStr_FromFormat("Dn(%s)", PyStr_AsUTF8(repr));
584 Py_DECREF(str);
585 Py_DECREF(repr);
586 return result;
589 static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
591 char *name;
593 if (!PyArg_ParseTuple(args, "s", &name))
594 return NULL;
596 return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
599 static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
601 int ret;
602 if (!pyldb_Dn_Check(dn2)) {
603 Py_INCREF(Py_NotImplemented);
604 return Py_NotImplemented;
606 ret = ldb_dn_compare(pyldb_Dn_AsDn(dn1), pyldb_Dn_AsDn(dn2));
607 return richcmp(ret, op);
610 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
612 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self);
613 struct ldb_dn *parent;
614 PyLdbDnObject *py_ret;
615 TALLOC_CTX *mem_ctx = talloc_new(NULL);
617 parent = ldb_dn_get_parent(mem_ctx, dn);
618 if (parent == NULL) {
619 talloc_free(mem_ctx);
620 Py_RETURN_NONE;
623 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
624 if (py_ret == NULL) {
625 PyErr_NoMemory();
626 talloc_free(mem_ctx);
627 return NULL;
629 py_ret->mem_ctx = mem_ctx;
630 py_ret->dn = parent;
631 return (PyObject *)py_ret;
634 static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
636 PyObject *py_other;
637 struct ldb_dn *dn, *other;
638 if (!PyArg_ParseTuple(args, "O", &py_other))
639 return NULL;
641 dn = pyldb_Dn_AsDn((PyObject *)self);
643 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
644 return NULL;
646 return PyBool_FromLong(ldb_dn_add_child(dn, other));
649 static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
651 PyObject *py_other;
652 struct ldb_dn *other, *dn;
653 if (!PyArg_ParseTuple(args, "O", &py_other))
654 return NULL;
656 dn = pyldb_Dn_AsDn((PyObject *)self);
658 if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
659 return NULL;
661 return PyBool_FromLong(ldb_dn_add_base(dn, other));
664 static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
666 struct ldb_dn *dn;
667 int i;
668 if (!PyArg_ParseTuple(args, "i", &i))
669 return NULL;
671 dn = pyldb_Dn_AsDn((PyObject *)self);
673 return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
676 static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
678 PyObject *py_base;
679 struct ldb_dn *dn, *base;
680 if (!PyArg_ParseTuple(args, "O", &py_base))
681 return NULL;
683 dn = pyldb_Dn_AsDn((PyObject *)self);
685 if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
686 return NULL;
688 return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
691 static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
693 struct ldb_dn *dn;
694 const char *name;
695 unsigned int num = 0;
697 if (!PyArg_ParseTuple(args, "I", &num))
698 return NULL;
700 dn = pyldb_Dn_AsDn((PyObject *)self);
702 name = ldb_dn_get_component_name(dn, num);
703 if (name == NULL) {
704 Py_RETURN_NONE;
707 return PyStr_FromString(name);
710 static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
712 struct ldb_dn *dn;
713 const struct ldb_val *val;
714 unsigned int num = 0;
716 if (!PyArg_ParseTuple(args, "I", &num))
717 return NULL;
719 dn = pyldb_Dn_AsDn((PyObject *)self);
721 val = ldb_dn_get_component_val(dn, num);
722 if (val == NULL) {
723 Py_RETURN_NONE;
726 return PyStr_FromLdbValue(val);
729 static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
731 unsigned int num = 0;
732 char *name = NULL, *value = NULL;
733 struct ldb_val val = { NULL, };
734 int err;
735 Py_ssize_t size = 0;
737 if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
738 return NULL;
740 val.data = (unsigned char*) value;
741 val.length = size;
743 err = ldb_dn_set_component(self->dn, num, name, val);
744 if (err != LDB_SUCCESS) {
745 PyErr_SetString(PyExc_TypeError, "Failed to set component");
746 return NULL;
749 Py_RETURN_NONE;
752 static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self)
754 struct ldb_dn *dn;
755 const char *name;
757 dn = pyldb_Dn_AsDn((PyObject *)self);
759 name = ldb_dn_get_rdn_name(dn);
760 if (name == NULL) {
761 Py_RETURN_NONE;
764 return PyStr_FromString(name);
767 static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self)
769 struct ldb_dn *dn;
770 const struct ldb_val *val;
772 dn = pyldb_Dn_AsDn((PyObject *)self);
774 val = ldb_dn_get_rdn_val(dn);
775 if (val == NULL) {
776 Py_RETURN_NONE;
779 return PyStr_FromLdbValue(val);
782 static PyMethodDef py_ldb_dn_methods[] = {
783 { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS,
784 "S.validate() -> bool\n"
785 "Validate DN is correct." },
786 { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
787 "S.is_valid() -> bool\n" },
788 { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
789 "S.is_special() -> bool\n"
790 "Check whether this is a special LDB DN." },
791 { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
792 "Check whether this is a null DN." },
793 { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
794 NULL },
795 { "get_linearized", (PyCFunction)py_ldb_dn_get_linearized, METH_NOARGS,
796 NULL },
797 { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
798 "S.canonical_str() -> string\n"
799 "Canonical version of this DN (like a posix path)." },
800 { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
801 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
802 { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
803 "S.canonical_ex_str() -> string\n"
804 "Canonical version of this DN (like a posix path, with terminating newline)." },
805 { "extended_str", (PyCFunction)py_ldb_dn_extended_str, METH_VARARGS | METH_KEYWORDS,
806 "S.extended_str(mode=1) -> string\n"
807 "Extended version of this DN" },
808 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
809 "S.parent() -> dn\n"
810 "Get the parent for this DN." },
811 { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS,
812 "S.add_child(dn) -> None\n"
813 "Add a child DN to this DN." },
814 { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
815 "S.add_base(dn) -> None\n"
816 "Add a base DN to this DN." },
817 { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
818 "S.remove_base_components(int) -> bool\n"
819 "Remove a number of DN components from the base of this DN." },
820 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
821 "S.check_special(name) -> bool\n\n"
822 "Check if name is a special DN name"},
823 { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
824 "S.get_extended_component(name) -> string\n\n"
825 "returns a DN extended component as a binary string"},
826 { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
827 "S.set_extended_component(name, value) -> None\n\n"
828 "set a DN extended component as a binary string"},
829 { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
830 "S.get_component_name(num) -> string\n"
831 "get the attribute name of the specified component" },
832 { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
833 "S.get_component_value(num) -> string\n"
834 "get the attribute value of the specified component as a binary string" },
835 { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
836 "S.get_component_value(num, name, value) -> None\n"
837 "set the attribute name and value of the specified component" },
838 { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
839 "S.get_rdn_name() -> string\n"
840 "get the RDN attribute name" },
841 { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
842 "S.get_rdn_value() -> string\n"
843 "get the RDN attribute value as a binary string" },
844 { NULL }
847 static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
849 return ldb_dn_get_comp_num(pyldb_Dn_AsDn((PyObject *)self));
853 copy a DN as a python object
855 static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
857 PyLdbDnObject *py_ret;
859 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
860 if (py_ret == NULL) {
861 PyErr_NoMemory();
862 return NULL;
864 py_ret->mem_ctx = talloc_new(NULL);
865 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
866 return (PyObject *)py_ret;
869 static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
871 struct ldb_dn *dn = pyldb_Dn_AsDn((PyObject *)self),
872 *other;
873 PyLdbDnObject *py_ret;
875 if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
876 return NULL;
878 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
879 if (py_ret == NULL) {
880 PyErr_NoMemory();
881 return NULL;
883 py_ret->mem_ctx = talloc_new(NULL);
884 py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
885 ldb_dn_add_base(py_ret->dn, other);
886 return (PyObject *)py_ret;
889 static PySequenceMethods py_ldb_dn_seq = {
890 .sq_length = (lenfunc)py_ldb_dn_len,
891 .sq_concat = (binaryfunc)py_ldb_dn_concat,
894 static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
896 struct ldb_dn *ret = NULL;
897 char *str = NULL;
898 PyObject *py_ldb = NULL;
899 struct ldb_context *ldb_ctx = NULL;
900 TALLOC_CTX *mem_ctx = NULL;
901 PyLdbDnObject *py_ret = NULL;
902 const char * const kwnames[] = { "ldb", "dn", NULL };
904 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Oes",
905 discard_const_p(char *, kwnames),
906 &py_ldb, "utf8", &str))
907 goto out;
909 if (!PyLdb_Check(py_ldb)) {
910 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
911 goto out;
914 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
916 mem_ctx = talloc_new(NULL);
917 if (mem_ctx == NULL) {
918 PyErr_NoMemory();
919 goto out;
922 ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
923 if (!ldb_dn_validate(ret)) {
924 talloc_free(mem_ctx);
925 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
926 goto out;
929 py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
930 if (py_ret == NULL) {
931 talloc_free(mem_ctx);
932 PyErr_NoMemory();
933 goto out;
935 py_ret->mem_ctx = mem_ctx;
936 py_ret->dn = ret;
937 out:
938 if (str != NULL) {
939 PyMem_Free(discard_const_p(char, str));
941 return (PyObject *)py_ret;
944 static void py_ldb_dn_dealloc(PyLdbDnObject *self)
946 talloc_free(self->mem_ctx);
947 PyObject_Del(self);
950 static PyTypeObject PyLdbDn = {
951 .tp_name = "ldb.Dn",
952 .tp_methods = py_ldb_dn_methods,
953 .tp_str = (reprfunc)py_ldb_dn_get_linearized,
954 .tp_repr = (reprfunc)py_ldb_dn_repr,
955 .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
956 .tp_as_sequence = &py_ldb_dn_seq,
957 .tp_doc = "A LDB distinguished name.",
958 .tp_new = py_ldb_dn_new,
959 .tp_dealloc = (destructor)py_ldb_dn_dealloc,
960 .tp_basicsize = sizeof(PyLdbDnObject),
961 .tp_flags = Py_TPFLAGS_DEFAULT,
964 /* Debug */
965 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
966 static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
968 PyObject *fn = (PyObject *)context;
969 PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyStr_FromFormatV(fmt, ap));
972 static PyObject *py_ldb_debug_func;
974 static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
976 PyObject *cb;
977 struct ldb_context *ldb_ctx;
979 if (!PyArg_ParseTuple(args, "O", &cb))
980 return NULL;
982 if (py_ldb_debug_func != NULL) {
983 Py_DECREF(py_ldb_debug_func);
986 Py_INCREF(cb);
987 /* FIXME: DECREF cb when exiting program */
988 py_ldb_debug_func = cb;
989 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
990 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
991 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
992 ldb_ctx);
994 Py_RETURN_NONE;
997 static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
999 unsigned int perms;
1000 if (!PyArg_ParseTuple(args, "I", &perms))
1001 return NULL;
1003 ldb_set_create_perms(pyldb_Ldb_AsLdbContext(self), perms);
1005 Py_RETURN_NONE;
1008 static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
1010 char *modules_dir;
1011 if (!PyArg_ParseTuple(args, "s", &modules_dir))
1012 return NULL;
1014 ldb_set_modules_dir(pyldb_Ldb_AsLdbContext(self), modules_dir);
1016 Py_RETURN_NONE;
1019 static PyObject *py_ldb_transaction_start(PyLdbObject *self)
1021 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1022 int ldb_err;
1023 ldb_err = ldb_transaction_start(ldb_ctx);
1024 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1025 Py_RETURN_NONE;
1028 static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
1030 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1031 int ldb_err;
1032 ldb_err = ldb_transaction_commit(ldb_ctx);
1033 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1034 Py_RETURN_NONE;
1037 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self)
1039 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1040 int ldb_err;
1041 ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
1042 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1043 Py_RETURN_NONE;
1046 static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
1048 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1049 int ldb_err;
1050 ldb_err = ldb_transaction_cancel(ldb_ctx);
1051 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1052 Py_RETURN_NONE;
1055 static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
1057 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1058 int ldb_err;
1059 ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
1060 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
1061 Py_RETURN_NONE;
1064 static PyObject *py_ldb_repr(PyLdbObject *self)
1066 return PyStr_FromString("<ldb connection>");
1069 static PyObject *py_ldb_get_root_basedn(PyLdbObject *self)
1071 struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AsLdbContext(self));
1072 if (dn == NULL)
1073 Py_RETURN_NONE;
1074 return py_ldb_dn_copy(dn);
1078 static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
1080 struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AsLdbContext(self));
1081 if (dn == NULL)
1082 Py_RETURN_NONE;
1083 return py_ldb_dn_copy(dn);
1086 static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
1088 struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AsLdbContext(self));
1089 if (dn == NULL)
1090 Py_RETURN_NONE;
1091 return py_ldb_dn_copy(dn);
1094 static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
1096 struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AsLdbContext(self));
1097 if (dn == NULL)
1098 Py_RETURN_NONE;
1099 return py_ldb_dn_copy(dn);
1102 static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
1103 const char *paramname)
1105 const char **ret;
1106 Py_ssize_t i;
1107 if (!PyList_Check(list)) {
1108 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
1109 return NULL;
1111 ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
1112 if (ret == NULL) {
1113 PyErr_NoMemory();
1114 return NULL;
1117 for (i = 0; i < PyList_Size(list); i++) {
1118 const char *str = NULL;
1119 Py_ssize_t size;
1120 PyObject *item = PyList_GetItem(list, i);
1121 if (!(PyStr_Check(item) || PyUnicode_Check(item))) {
1122 PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
1123 talloc_free(ret);
1124 return NULL;
1126 str = PyStr_AsUTF8AndSize(item, &size);
1127 if (str == NULL) {
1128 talloc_free(ret);
1129 return NULL;
1131 ret[i] = talloc_strndup(ret, str, size);
1133 ret[i] = NULL;
1134 return ret;
1137 static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1139 const char * const kwnames[] = { "url", "flags", "options", NULL };
1140 char *url = NULL;
1141 PyObject *py_options = Py_None;
1142 const char **options;
1143 unsigned int flags = 0;
1144 int ret;
1145 struct ldb_context *ldb;
1147 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
1148 discard_const_p(char *, kwnames),
1149 &url, &flags, &py_options))
1150 return -1;
1152 ldb = pyldb_Ldb_AsLdbContext(self);
1154 if (py_options == Py_None) {
1155 options = NULL;
1156 } else {
1157 options = PyList_AsStrList(ldb, py_options, "options");
1158 if (options == NULL)
1159 return -1;
1162 if (url != NULL) {
1163 ret = ldb_connect(ldb, url, flags, options);
1164 if (ret != LDB_SUCCESS) {
1165 PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
1166 return -1;
1170 talloc_free(options);
1171 return 0;
1174 static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
1176 PyLdbObject *ret;
1177 struct ldb_context *ldb;
1178 ret = (PyLdbObject *)type->tp_alloc(type, 0);
1179 if (ret == NULL) {
1180 PyErr_NoMemory();
1181 return NULL;
1183 ret->mem_ctx = talloc_new(NULL);
1184 ldb = ldb_init(ret->mem_ctx, NULL);
1186 if (ldb == NULL) {
1187 PyErr_NoMemory();
1188 return NULL;
1191 ret->ldb_ctx = ldb;
1192 return (PyObject *)ret;
1195 static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1197 char *url = NULL;
1198 unsigned int flags = 0;
1199 PyObject *py_options = Py_None;
1200 int ret;
1201 const char **options;
1202 const char * const kwnames[] = { "url", "flags", "options", NULL };
1203 struct ldb_context *ldb_ctx;
1205 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO",
1206 discard_const_p(char *, kwnames),
1207 &url, &flags, &py_options))
1208 return NULL;
1210 if (py_options == Py_None) {
1211 options = NULL;
1212 } else {
1213 options = PyList_AsStrList(NULL, py_options, "options");
1214 if (options == NULL)
1215 return NULL;
1218 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1219 ret = ldb_connect(ldb_ctx, url, flags, options);
1220 talloc_free(options);
1222 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1224 Py_RETURN_NONE;
1227 static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1229 PyObject *py_msg;
1230 PyObject *py_controls = Py_None;
1231 struct ldb_context *ldb_ctx;
1232 struct ldb_request *req;
1233 struct ldb_control **parsed_controls;
1234 struct ldb_message *msg;
1235 int ret;
1236 TALLOC_CTX *mem_ctx;
1237 bool validate=true;
1238 const char * const kwnames[] = { "message", "controls", "validate", NULL };
1240 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
1241 discard_const_p(char *, kwnames),
1242 &py_msg, &py_controls, &validate))
1243 return NULL;
1245 mem_ctx = talloc_new(NULL);
1246 if (mem_ctx == NULL) {
1247 PyErr_NoMemory();
1248 return NULL;
1250 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1252 if (py_controls == Py_None) {
1253 parsed_controls = NULL;
1254 } else {
1255 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1256 if (controls == NULL) {
1257 talloc_free(mem_ctx);
1258 return NULL;
1260 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1261 talloc_free(controls);
1264 if (!PyLdbMessage_Check(py_msg)) {
1265 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
1266 talloc_free(mem_ctx);
1267 return NULL;
1269 msg = pyldb_Message_AsMessage(py_msg);
1271 if (validate) {
1272 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1273 if (ret != LDB_SUCCESS) {
1274 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1275 talloc_free(mem_ctx);
1276 return NULL;
1280 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1281 NULL, ldb_op_default_callback, NULL);
1282 if (ret != LDB_SUCCESS) {
1283 PyErr_SetString(PyExc_TypeError, "failed to build request");
1284 talloc_free(mem_ctx);
1285 return NULL;
1288 /* do request and autostart a transaction */
1289 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1291 ret = ldb_transaction_start(ldb_ctx);
1292 if (ret != LDB_SUCCESS) {
1293 talloc_free(mem_ctx);
1294 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1295 return NULL;
1298 ret = ldb_request(ldb_ctx, req);
1299 if (ret == LDB_SUCCESS) {
1300 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1303 if (ret == LDB_SUCCESS) {
1304 ret = ldb_transaction_commit(ldb_ctx);
1305 } else {
1306 ldb_transaction_cancel(ldb_ctx);
1309 talloc_free(mem_ctx);
1310 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1312 Py_RETURN_NONE;
1317 * Obtain a ldb message from a Python Dictionary object.
1319 * @param mem_ctx Memory context
1320 * @param py_obj Python Dictionary object
1321 * @param ldb_ctx LDB context
1322 * @param mod_flags Flags to be set on every message element
1323 * @return ldb_message on success or NULL on failure
1325 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
1326 PyObject *py_obj,
1327 struct ldb_context *ldb_ctx,
1328 unsigned int mod_flags)
1330 struct ldb_message *msg;
1331 unsigned int msg_pos = 0;
1332 Py_ssize_t dict_pos = 0;
1333 PyObject *key, *value;
1334 struct ldb_message_element *msg_el;
1335 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
1337 msg = ldb_msg_new(mem_ctx);
1338 if (msg == NULL) {
1339 PyErr_NoMemory();
1340 return NULL;
1342 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
1344 if (dn_value) {
1345 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
1346 PyErr_SetString(PyExc_TypeError, "unable to import dn object");
1347 return NULL;
1349 if (msg->dn == NULL) {
1350 PyErr_SetString(PyExc_TypeError, "dn set but not found");
1351 return NULL;
1353 } else {
1354 PyErr_SetString(PyExc_TypeError, "no dn set");
1355 return NULL;
1358 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
1359 const char *key_str = PyStr_AsUTF8(key);
1360 if (ldb_attr_cmp(key_str, "dn") != 0) {
1361 msg_el = PyObject_AsMessageElement(msg->elements, value,
1362 mod_flags, key_str);
1363 if (msg_el == NULL) {
1364 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
1365 return NULL;
1367 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
1368 msg_pos++;
1372 msg->num_elements = msg_pos;
1374 return msg;
1377 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1379 PyObject *py_obj;
1380 int ret;
1381 struct ldb_context *ldb_ctx;
1382 struct ldb_request *req;
1383 struct ldb_message *msg = NULL;
1384 PyObject *py_controls = Py_None;
1385 TALLOC_CTX *mem_ctx;
1386 struct ldb_control **parsed_controls;
1387 const char * const kwnames[] = { "message", "controls", NULL };
1389 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1390 discard_const_p(char *, kwnames),
1391 &py_obj, &py_controls))
1392 return NULL;
1394 mem_ctx = talloc_new(NULL);
1395 if (mem_ctx == NULL) {
1396 PyErr_NoMemory();
1397 return NULL;
1399 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1401 if (py_controls == Py_None) {
1402 parsed_controls = NULL;
1403 } else {
1404 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1405 if (controls == NULL) {
1406 talloc_free(mem_ctx);
1407 return NULL;
1409 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1410 talloc_free(controls);
1413 if (PyLdbMessage_Check(py_obj)) {
1414 msg = pyldb_Message_AsMessage(py_obj);
1415 } else if (PyDict_Check(py_obj)) {
1416 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
1417 } else {
1418 PyErr_SetString(PyExc_TypeError,
1419 "Dictionary or LdbMessage object expected!");
1422 if (!msg) {
1423 /* we should have a PyErr already set */
1424 talloc_free(mem_ctx);
1425 return NULL;
1428 ret = ldb_msg_sanity_check(ldb_ctx, msg);
1429 if (ret != LDB_SUCCESS) {
1430 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1431 talloc_free(mem_ctx);
1432 return NULL;
1435 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
1436 NULL, ldb_op_default_callback, NULL);
1437 if (ret != LDB_SUCCESS) {
1438 PyErr_SetString(PyExc_TypeError, "failed to build request");
1439 talloc_free(mem_ctx);
1440 return NULL;
1443 /* do request and autostart a transaction */
1444 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1446 ret = ldb_transaction_start(ldb_ctx);
1447 if (ret != LDB_SUCCESS) {
1448 talloc_free(mem_ctx);
1449 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1450 return NULL;
1453 ret = ldb_request(ldb_ctx, req);
1454 if (ret == LDB_SUCCESS) {
1455 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1458 if (ret == LDB_SUCCESS) {
1459 ret = ldb_transaction_commit(ldb_ctx);
1460 } else {
1461 ldb_transaction_cancel(ldb_ctx);
1464 talloc_free(mem_ctx);
1465 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1467 Py_RETURN_NONE;
1470 static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1472 PyObject *py_dn;
1473 struct ldb_dn *dn;
1474 int ret;
1475 struct ldb_context *ldb_ctx;
1476 struct ldb_request *req;
1477 PyObject *py_controls = Py_None;
1478 TALLOC_CTX *mem_ctx;
1479 struct ldb_control **parsed_controls;
1480 const char * const kwnames[] = { "dn", "controls", NULL };
1482 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
1483 discard_const_p(char *, kwnames),
1484 &py_dn, &py_controls))
1485 return NULL;
1487 mem_ctx = talloc_new(NULL);
1488 if (mem_ctx == NULL) {
1489 PyErr_NoMemory();
1490 return NULL;
1492 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1494 if (py_controls == Py_None) {
1495 parsed_controls = NULL;
1496 } else {
1497 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1498 if (controls == NULL) {
1499 talloc_free(mem_ctx);
1500 return NULL;
1502 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1503 talloc_free(controls);
1506 if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
1507 talloc_free(mem_ctx);
1508 return NULL;
1511 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
1512 NULL, ldb_op_default_callback, NULL);
1513 if (ret != LDB_SUCCESS) {
1514 PyErr_SetString(PyExc_TypeError, "failed to build request");
1515 talloc_free(mem_ctx);
1516 return NULL;
1519 /* do request and autostart a transaction */
1520 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1522 ret = ldb_transaction_start(ldb_ctx);
1523 if (ret != LDB_SUCCESS) {
1524 talloc_free(mem_ctx);
1525 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1526 return NULL;
1529 ret = ldb_request(ldb_ctx, req);
1530 if (ret == LDB_SUCCESS) {
1531 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1534 if (ret == LDB_SUCCESS) {
1535 ret = ldb_transaction_commit(ldb_ctx);
1536 } else {
1537 ldb_transaction_cancel(ldb_ctx);
1540 talloc_free(mem_ctx);
1541 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1543 Py_RETURN_NONE;
1546 static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1548 PyObject *py_dn1, *py_dn2;
1549 struct ldb_dn *dn1, *dn2;
1550 int ret;
1551 TALLOC_CTX *mem_ctx;
1552 PyObject *py_controls = Py_None;
1553 struct ldb_control **parsed_controls;
1554 struct ldb_context *ldb_ctx;
1555 struct ldb_request *req;
1556 const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
1558 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1560 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
1561 discard_const_p(char *, kwnames),
1562 &py_dn1, &py_dn2, &py_controls))
1563 return NULL;
1566 mem_ctx = talloc_new(NULL);
1567 if (mem_ctx == NULL) {
1568 PyErr_NoMemory();
1569 return NULL;
1572 if (py_controls == Py_None) {
1573 parsed_controls = NULL;
1574 } else {
1575 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1576 if (controls == NULL) {
1577 talloc_free(mem_ctx);
1578 return NULL;
1580 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1581 talloc_free(controls);
1585 if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
1586 talloc_free(mem_ctx);
1587 return NULL;
1590 if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
1591 talloc_free(mem_ctx);
1592 return NULL;
1595 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
1596 NULL, ldb_op_default_callback, NULL);
1597 if (ret != LDB_SUCCESS) {
1598 PyErr_SetString(PyExc_TypeError, "failed to build request");
1599 talloc_free(mem_ctx);
1600 return NULL;
1603 /* do request and autostart a transaction */
1604 /* Then let's LDB handle the message error in case of pb as they are meaningful */
1606 ret = ldb_transaction_start(ldb_ctx);
1607 if (ret != LDB_SUCCESS) {
1608 talloc_free(mem_ctx);
1609 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1610 return NULL;
1613 ret = ldb_request(ldb_ctx, req);
1614 if (ret == LDB_SUCCESS) {
1615 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1618 if (ret == LDB_SUCCESS) {
1619 ret = ldb_transaction_commit(ldb_ctx);
1620 } else {
1621 ldb_transaction_cancel(ldb_ctx);
1624 talloc_free(mem_ctx);
1625 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1627 Py_RETURN_NONE;
1630 static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
1632 char *name;
1633 if (!PyArg_ParseTuple(args, "s", &name))
1634 return NULL;
1636 ldb_schema_attribute_remove(pyldb_Ldb_AsLdbContext(self), name);
1638 Py_RETURN_NONE;
1641 static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
1643 char *attribute, *syntax;
1644 unsigned int flags;
1645 int ret;
1646 struct ldb_context *ldb_ctx;
1648 if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
1649 return NULL;
1651 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1652 ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
1654 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
1656 Py_RETURN_NONE;
1659 static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
1661 if (ldif == NULL) {
1662 Py_RETURN_NONE;
1663 } else {
1664 /* We don't want this attached to the 'ldb' any more */
1665 return Py_BuildValue(discard_const_p(char, "(iO)"),
1666 ldif->changetype,
1667 PyLdbMessage_FromMessage(ldif->msg));
1672 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
1674 int changetype;
1675 PyObject *py_msg;
1676 struct ldb_ldif ldif;
1677 PyObject *ret;
1678 char *string;
1679 TALLOC_CTX *mem_ctx;
1681 if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
1682 return NULL;
1684 if (!PyLdbMessage_Check(py_msg)) {
1685 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
1686 return NULL;
1689 ldif.msg = pyldb_Message_AsMessage(py_msg);
1690 ldif.changetype = changetype;
1692 mem_ctx = talloc_new(NULL);
1694 string = ldb_ldif_write_string(pyldb_Ldb_AsLdbContext(self), mem_ctx, &ldif);
1695 if (!string) {
1696 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
1697 return NULL;
1700 ret = PyStr_FromString(string);
1702 talloc_free(mem_ctx);
1704 return ret;
1707 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
1709 PyObject *list, *ret;
1710 struct ldb_ldif *ldif;
1711 const char *s;
1712 struct ldb_dn *last_dn = NULL;
1714 TALLOC_CTX *mem_ctx;
1716 if (!PyArg_ParseTuple(args, "s", &s))
1717 return NULL;
1719 mem_ctx = talloc_new(NULL);
1720 if (!mem_ctx) {
1721 Py_RETURN_NONE;
1724 list = PyList_New(0);
1725 while (s && *s != '\0') {
1726 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
1727 talloc_steal(mem_ctx, ldif);
1728 if (ldif) {
1729 PyList_Append(list, ldb_ldif_to_pyobject(ldif));
1730 last_dn = ldif->msg->dn;
1731 } else {
1732 const char *last_dn_str = NULL;
1733 const char *err_string = NULL;
1734 if (last_dn == NULL) {
1735 PyErr_SetString(PyExc_ValueError,
1736 "unable to parse LDIF "
1737 "string at first chunk");
1738 talloc_free(mem_ctx);
1739 return NULL;
1742 last_dn_str
1743 = ldb_dn_get_linearized(last_dn);
1745 err_string
1746 = talloc_asprintf(mem_ctx,
1747 "unable to parse ldif "
1748 "string AFTER %s",
1749 last_dn_str);
1751 PyErr_SetString(PyExc_ValueError,
1752 err_string);
1753 talloc_free(mem_ctx);
1754 return NULL;
1757 talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
1758 ret = PyObject_GetIter(list);
1759 Py_DECREF(list);
1760 return ret;
1763 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
1765 int ldb_ret;
1766 PyObject *py_msg_old;
1767 PyObject *py_msg_new;
1768 struct ldb_message *diff;
1769 struct ldb_context *ldb;
1770 PyObject *py_ret;
1772 if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
1773 return NULL;
1775 if (!PyLdbMessage_Check(py_msg_old)) {
1776 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
1777 return NULL;
1780 if (!PyLdbMessage_Check(py_msg_new)) {
1781 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
1782 return NULL;
1785 ldb = pyldb_Ldb_AsLdbContext(self);
1786 ldb_ret = ldb_msg_difference(ldb, ldb,
1787 pyldb_Message_AsMessage(py_msg_old),
1788 pyldb_Message_AsMessage(py_msg_new),
1789 &diff);
1790 if (ldb_ret != LDB_SUCCESS) {
1791 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
1792 return NULL;
1795 py_ret = PyLdbMessage_FromMessage(diff);
1797 talloc_unlink(ldb, diff);
1799 return py_ret;
1802 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
1804 const struct ldb_schema_attribute *a;
1805 struct ldb_val old_val;
1806 struct ldb_val new_val;
1807 TALLOC_CTX *mem_ctx;
1808 PyObject *ret;
1809 char *element_name;
1810 PyObject *val;
1811 Py_ssize_t size;
1812 int result;
1814 if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
1815 return NULL;
1817 result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
1818 old_val.length = size;
1820 if (result != 0) {
1821 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
1822 return NULL;
1825 a = ldb_schema_attribute_by_name(pyldb_Ldb_AsLdbContext(self), element_name);
1827 if (a == NULL) {
1828 Py_RETURN_NONE;
1831 mem_ctx = talloc_new(NULL);
1832 if (mem_ctx == NULL) {
1833 PyErr_NoMemory();
1834 return NULL;
1837 if (a->syntax->ldif_write_fn(pyldb_Ldb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
1838 talloc_free(mem_ctx);
1839 Py_RETURN_NONE;
1842 ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
1844 talloc_free(mem_ctx);
1846 return ret;
1849 static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
1851 PyObject *py_base = Py_None;
1852 int scope = LDB_SCOPE_DEFAULT;
1853 char *expr = NULL;
1854 PyObject *py_attrs = Py_None;
1855 PyObject *py_controls = Py_None;
1856 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
1857 int ret;
1858 struct ldb_result *res;
1859 struct ldb_request *req;
1860 const char **attrs;
1861 struct ldb_context *ldb_ctx;
1862 struct ldb_control **parsed_controls;
1863 struct ldb_dn *base;
1864 PyObject *py_ret;
1865 TALLOC_CTX *mem_ctx;
1867 /* type "int" rather than "enum" for "scope" is intentional */
1868 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
1869 discard_const_p(char *, kwnames),
1870 &py_base, &scope, &expr, &py_attrs, &py_controls))
1871 return NULL;
1874 mem_ctx = talloc_new(NULL);
1875 if (mem_ctx == NULL) {
1876 PyErr_NoMemory();
1877 return NULL;
1879 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
1881 if (py_attrs == Py_None) {
1882 attrs = NULL;
1883 } else {
1884 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
1885 if (attrs == NULL) {
1886 talloc_free(mem_ctx);
1887 return NULL;
1891 if (py_base == Py_None) {
1892 base = ldb_get_default_basedn(ldb_ctx);
1893 } else {
1894 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
1895 talloc_free(mem_ctx);
1896 return NULL;
1900 if (py_controls == Py_None) {
1901 parsed_controls = NULL;
1902 } else {
1903 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
1904 if (controls == NULL) {
1905 talloc_free(mem_ctx);
1906 return NULL;
1908 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
1909 talloc_free(controls);
1912 res = talloc_zero(mem_ctx, struct ldb_result);
1913 if (res == NULL) {
1914 PyErr_NoMemory();
1915 talloc_free(mem_ctx);
1916 return NULL;
1919 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
1920 base,
1921 scope,
1922 expr,
1923 attrs,
1924 parsed_controls,
1925 res,
1926 ldb_search_default_callback,
1927 NULL);
1929 if (ret != LDB_SUCCESS) {
1930 talloc_free(mem_ctx);
1931 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1932 return NULL;
1935 talloc_steal(req, attrs);
1937 ret = ldb_request(ldb_ctx, req);
1939 if (ret == LDB_SUCCESS) {
1940 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
1943 if (ret != LDB_SUCCESS) {
1944 talloc_free(mem_ctx);
1945 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
1946 return NULL;
1949 py_ret = PyLdbResult_FromResult(res);
1951 talloc_free(mem_ctx);
1953 return py_ret;
1956 static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
1958 if (reply->py_iter != NULL) {
1959 DLIST_REMOVE(reply->py_iter->state.next, reply);
1960 if (reply->py_iter->state.result == reply) {
1961 reply->py_iter->state.result = NULL;
1963 reply->py_iter = NULL;
1966 if (reply->obj != NULL) {
1967 Py_DECREF(reply->obj);
1968 reply->obj = NULL;
1971 return 0;
1974 static int py_ldb_search_iterator_callback(struct ldb_request *req,
1975 struct ldb_reply *ares)
1977 PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
1978 struct ldb_result result = { .msgs = NULL };
1979 struct py_ldb_search_iterator_reply *reply = NULL;
1981 if (ares == NULL) {
1982 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1985 if (ares->error != LDB_SUCCESS) {
1986 int ret = ares->error;
1987 TALLOC_FREE(ares);
1988 return ldb_request_done(req, ret);
1991 reply = talloc_zero(py_iter->mem_ctx,
1992 struct py_ldb_search_iterator_reply);
1993 if (reply == NULL) {
1994 TALLOC_FREE(ares);
1995 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
1997 reply->py_iter = py_iter;
1998 talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
2000 switch (ares->type) {
2001 case LDB_REPLY_ENTRY:
2002 reply->obj = PyLdbMessage_FromMessage(ares->message);
2003 if (reply->obj == NULL) {
2004 TALLOC_FREE(ares);
2005 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2007 DLIST_ADD_END(py_iter->state.next, reply);
2008 TALLOC_FREE(ares);
2009 return LDB_SUCCESS;
2011 case LDB_REPLY_REFERRAL:
2012 reply->obj = PyStr_FromString(ares->referral);
2013 if (reply->obj == NULL) {
2014 TALLOC_FREE(ares);
2015 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2017 DLIST_ADD_END(py_iter->state.next, reply);
2018 TALLOC_FREE(ares);
2019 return LDB_SUCCESS;
2021 case LDB_REPLY_DONE:
2022 result = (struct ldb_result) { .controls = ares->controls };
2023 reply->obj = PyLdbResult_FromResult(&result);
2024 if (reply->obj == NULL) {
2025 TALLOC_FREE(ares);
2026 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2028 py_iter->state.result = reply;
2029 TALLOC_FREE(ares);
2030 return ldb_request_done(req, LDB_SUCCESS);
2033 TALLOC_FREE(ares);
2034 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
2037 static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
2039 PyObject *py_base = Py_None;
2040 int scope = LDB_SCOPE_DEFAULT;
2041 int timeout = 0;
2042 char *expr = NULL;
2043 PyObject *py_attrs = Py_None;
2044 PyObject *py_controls = Py_None;
2045 const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
2046 int ret;
2047 const char **attrs;
2048 struct ldb_context *ldb_ctx;
2049 struct ldb_control **parsed_controls;
2050 struct ldb_dn *base;
2051 PyLdbSearchIteratorObject *py_iter;
2053 /* type "int" rather than "enum" for "scope" is intentional */
2054 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
2055 discard_const_p(char *, kwnames),
2056 &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
2057 return NULL;
2059 py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
2060 if (py_iter == NULL) {
2061 PyErr_NoMemory();
2062 return NULL;
2064 py_iter->ldb = self;
2065 Py_INCREF(self);
2066 ZERO_STRUCT(py_iter->state);
2067 py_iter->mem_ctx = talloc_new(NULL);
2068 if (py_iter->mem_ctx == NULL) {
2069 Py_DECREF(py_iter);
2070 PyErr_NoMemory();
2071 return NULL;
2074 ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2076 if (py_attrs == Py_None) {
2077 attrs = NULL;
2078 } else {
2079 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
2080 if (attrs == NULL) {
2081 Py_DECREF(py_iter);
2082 PyErr_NoMemory();
2083 return NULL;
2087 if (py_base == Py_None) {
2088 base = ldb_get_default_basedn(ldb_ctx);
2089 } else {
2090 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
2091 Py_DECREF(py_iter);
2092 PyErr_NoMemory();
2093 return NULL;
2097 if (py_controls == Py_None) {
2098 parsed_controls = NULL;
2099 } else {
2100 const char **controls = NULL;
2102 controls = PyList_AsStrList(py_iter->mem_ctx,
2103 py_controls, "controls");
2104 if (controls == NULL) {
2105 Py_DECREF(py_iter);
2106 PyErr_NoMemory();
2107 return NULL;
2110 parsed_controls = ldb_parse_control_strings(ldb_ctx,
2111 py_iter->mem_ctx,
2112 controls);
2113 if (controls[0] != NULL && parsed_controls == NULL) {
2114 Py_DECREF(py_iter);
2115 PyErr_NoMemory();
2116 return NULL;
2118 talloc_free(controls);
2121 ret = ldb_build_search_req(&py_iter->state.req,
2122 ldb_ctx,
2123 py_iter->mem_ctx,
2124 base,
2125 scope,
2126 expr,
2127 attrs,
2128 parsed_controls,
2129 py_iter,
2130 py_ldb_search_iterator_callback,
2131 NULL);
2132 if (ret != LDB_SUCCESS) {
2133 Py_DECREF(py_iter);
2134 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2135 return NULL;
2138 ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
2140 ret = ldb_request(ldb_ctx, py_iter->state.req);
2141 if (ret != LDB_SUCCESS) {
2142 Py_DECREF(py_iter);
2143 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2144 return NULL;
2147 return (PyObject *)py_iter;
2150 static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
2152 char *name;
2153 void *data;
2155 if (!PyArg_ParseTuple(args, "s", &name))
2156 return NULL;
2158 data = ldb_get_opaque(pyldb_Ldb_AsLdbContext(self), name);
2160 if (data == NULL)
2161 Py_RETURN_NONE;
2163 /* FIXME: More interpretation */
2165 Py_RETURN_TRUE;
2168 static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
2170 char *name;
2171 PyObject *data;
2173 if (!PyArg_ParseTuple(args, "sO", &name, &data))
2174 return NULL;
2176 /* FIXME: More interpretation */
2178 ldb_set_opaque(pyldb_Ldb_AsLdbContext(self), name, data);
2180 Py_RETURN_NONE;
2183 static PyObject *py_ldb_modules(PyLdbObject *self)
2185 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2186 PyObject *ret = PyList_New(0);
2187 struct ldb_module *mod;
2189 for (mod = ldb->modules; mod; mod = mod->next) {
2190 PyList_Append(ret, PyLdbModule_FromModule(mod));
2193 return ret;
2196 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
2198 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2199 int type, ret;
2200 uint64_t value;
2202 if (!PyArg_ParseTuple(args, "i", &type))
2203 return NULL;
2205 /* FIXME: More interpretation */
2207 ret = ldb_sequence_number(ldb, type, &value);
2209 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2211 return PyLong_FromLongLong(value);
2215 static const struct ldb_dn_extended_syntax test_dn_syntax = {
2216 .name = "TEST",
2217 .read_fn = ldb_handler_copy,
2218 .write_clear_fn = ldb_handler_copy,
2219 .write_hex_fn = ldb_handler_copy,
2222 static PyObject *py_ldb_register_test_extensions(PyLdbObject *self)
2224 struct ldb_context *ldb = pyldb_Ldb_AsLdbContext(self);
2225 int ret;
2227 ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
2229 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
2231 Py_RETURN_NONE;
2235 static PyMethodDef py_ldb_methods[] = {
2236 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS,
2237 "S.set_debug(callback) -> None\n"
2238 "Set callback for LDB debug messages.\n"
2239 "The callback should accept a debug level and debug text." },
2240 { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS,
2241 "S.set_create_perms(mode) -> None\n"
2242 "Set mode to use when creating new LDB files." },
2243 { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
2244 "S.set_modules_dir(path) -> None\n"
2245 "Set path LDB should search for modules" },
2246 { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS,
2247 "S.transaction_start() -> None\n"
2248 "Start a new transaction." },
2249 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
2250 "S.transaction_prepare_commit() -> None\n"
2251 "prepare to commit a new transaction (2-stage commit)." },
2252 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS,
2253 "S.transaction_commit() -> None\n"
2254 "commit a new transaction." },
2255 { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS,
2256 "S.transaction_cancel() -> None\n"
2257 "cancel a new transaction." },
2258 { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS,
2259 NULL },
2260 { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
2261 NULL },
2262 { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
2263 NULL },
2264 { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
2265 NULL },
2266 { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
2267 NULL },
2268 { "connect", (PyCFunction)py_ldb_connect, METH_VARARGS|METH_KEYWORDS,
2269 "S.connect(url, flags=0, options=None) -> None\n"
2270 "Connect to a LDB URL." },
2271 { "modify", (PyCFunction)py_ldb_modify, METH_VARARGS|METH_KEYWORDS,
2272 "S.modify(message, controls=None, validate=False) -> None\n"
2273 "Modify an entry." },
2274 { "add", (PyCFunction)py_ldb_add, METH_VARARGS|METH_KEYWORDS,
2275 "S.add(message, controls=None) -> None\n"
2276 "Add an entry." },
2277 { "delete", (PyCFunction)py_ldb_delete, METH_VARARGS|METH_KEYWORDS,
2278 "S.delete(dn, controls=None) -> None\n"
2279 "Remove an entry." },
2280 { "rename", (PyCFunction)py_ldb_rename, METH_VARARGS|METH_KEYWORDS,
2281 "S.rename(old_dn, new_dn, controls=None) -> None\n"
2282 "Rename an entry." },
2283 { "search", (PyCFunction)py_ldb_search, METH_VARARGS|METH_KEYWORDS,
2284 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
2285 "Search in a database.\n"
2286 "\n"
2287 ":param base: Optional base DN to search\n"
2288 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2289 ":param expression: Optional search expression\n"
2290 ":param attrs: Attributes to return (defaults to all)\n"
2291 ":param controls: Optional list of controls\n"
2292 ":return: ldb.Result object\n"
2294 { "search_iterator", (PyCFunction)py_ldb_search_iterator, METH_VARARGS|METH_KEYWORDS,
2295 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
2296 "Search in a database.\n"
2297 "\n"
2298 ":param base: Optional base DN to search\n"
2299 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
2300 ":param expression: Optional search expression\n"
2301 ":param attrs: Attributes to return (defaults to all)\n"
2302 ":param controls: Optional list of controls\n"
2303 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
2304 ":return: ldb.SearchIterator object that provides results when they arrive\n"
2306 { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
2307 NULL },
2308 { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
2309 NULL },
2310 { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
2311 NULL },
2312 { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
2313 "S.parse_ldif(ldif) -> iter(messages)\n"
2314 "Parse a string formatted using LDIF." },
2315 { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
2316 "S.write_ldif(message, changetype) -> ldif\n"
2317 "Print the message as a string formatted using LDIF." },
2318 { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
2319 "S.msg_diff(Message) -> Message\n"
2320 "Return an LDB Message of the difference between two Message objects." },
2321 { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
2322 "S.get_opaque(name) -> value\n"
2323 "Get an opaque value set on this LDB connection. \n"
2324 ":note: The returned value may not be useful in Python."
2326 { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
2327 "S.set_opaque(name, value) -> None\n"
2328 "Set an opaque value on this LDB connection. \n"
2329 ":note: Passing incorrect values may cause crashes." },
2330 { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
2331 "S.modules() -> list\n"
2332 "Return the list of modules on this LDB connection " },
2333 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
2334 "S.sequence_number(type) -> value\n"
2335 "Return the value of the sequence according to the requested type" },
2336 { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
2337 "S._register_test_extensions() -> None\n"
2338 "Register internal extensions used in testing" },
2339 { NULL },
2342 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
2344 PyLdbModuleObject *ret;
2346 ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
2347 if (ret == NULL) {
2348 PyErr_NoMemory();
2349 return NULL;
2351 ret->mem_ctx = talloc_new(NULL);
2352 ret->mod = talloc_reference(ret->mem_ctx, mod);
2353 return (PyObject *)ret;
2356 static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
2358 struct ldb_module *mod = pyldb_Ldb_AsLdbContext(self)->modules;
2359 if (mod == NULL) {
2360 Py_RETURN_NONE;
2362 return PyLdbModule_FromModule(mod);
2365 static PyGetSetDef py_ldb_getset[] = {
2366 { discard_const_p(char, "firstmodule"), (getter)py_ldb_get_firstmodule, NULL, NULL },
2367 { NULL }
2370 static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
2372 struct ldb_context *ldb_ctx = pyldb_Ldb_AsLdbContext(self);
2373 struct ldb_dn *dn;
2374 struct ldb_result *result;
2375 unsigned int count;
2376 int ret;
2378 if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
2379 return -1;
2382 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
2383 NULL);
2384 if (ret != LDB_SUCCESS) {
2385 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
2386 return -1;
2389 count = result->count;
2391 talloc_free(result);
2393 if (count > 1) {
2394 PyErr_Format(PyExc_RuntimeError,
2395 "Searching for [%s] dn gave %u results!",
2396 ldb_dn_get_linearized(dn),
2397 count);
2398 return -1;
2401 return count;
2404 static PySequenceMethods py_ldb_seq = {
2405 .sq_contains = (objobjproc)py_ldb_contains,
2408 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
2410 PyLdbObject *ret;
2412 ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
2413 if (ret == NULL) {
2414 PyErr_NoMemory();
2415 return NULL;
2417 ret->mem_ctx = talloc_new(NULL);
2418 ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
2419 return (PyObject *)ret;
2422 static void py_ldb_dealloc(PyLdbObject *self)
2424 talloc_free(self->mem_ctx);
2425 Py_TYPE(self)->tp_free(self);
2428 static PyTypeObject PyLdb = {
2429 .tp_name = "ldb.Ldb",
2430 .tp_methods = py_ldb_methods,
2431 .tp_repr = (reprfunc)py_ldb_repr,
2432 .tp_new = py_ldb_new,
2433 .tp_init = (initproc)py_ldb_init,
2434 .tp_dealloc = (destructor)py_ldb_dealloc,
2435 .tp_getset = py_ldb_getset,
2436 .tp_getattro = PyObject_GenericGetAttr,
2437 .tp_basicsize = sizeof(PyLdbObject),
2438 .tp_doc = "Connection to a LDB database.",
2439 .tp_as_sequence = &py_ldb_seq,
2440 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2443 static void py_ldb_result_dealloc(PyLdbResultObject *self)
2445 talloc_free(self->mem_ctx);
2446 Py_DECREF(self->msgs);
2447 Py_DECREF(self->referals);
2448 Py_DECREF(self->controls);
2449 Py_TYPE(self)->tp_free(self);
2452 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
2454 Py_INCREF(self->msgs);
2455 return self->msgs;
2458 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
2460 Py_INCREF(self->controls);
2461 return self->controls;
2464 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
2466 Py_INCREF(self->referals);
2467 return self->referals;
2470 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
2472 Py_ssize_t size;
2473 if (self->msgs == NULL) {
2474 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
2475 return NULL;
2477 size = PyList_Size(self->msgs);
2478 return PyInt_FromLong(size);
2481 static PyGetSetDef py_ldb_result_getset[] = {
2482 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL },
2483 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL },
2484 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL },
2485 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL },
2486 { NULL }
2489 static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
2491 return PyObject_GetIter(self->msgs);
2494 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
2496 return PySequence_Size(self->msgs);
2499 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
2501 return PySequence_GetItem(self->msgs, idx);
2504 static PySequenceMethods py_ldb_result_seq = {
2505 .sq_length = (lenfunc)py_ldb_result_len,
2506 .sq_item = (ssizeargfunc)py_ldb_result_find,
2509 static PyObject *py_ldb_result_repr(PyLdbObject *self)
2511 return PyStr_FromString("<ldb result>");
2515 static PyTypeObject PyLdbResult = {
2516 .tp_name = "ldb.Result",
2517 .tp_repr = (reprfunc)py_ldb_result_repr,
2518 .tp_dealloc = (destructor)py_ldb_result_dealloc,
2519 .tp_iter = (getiterfunc)py_ldb_result_iter,
2520 .tp_getset = py_ldb_result_getset,
2521 .tp_getattro = PyObject_GenericGetAttr,
2522 .tp_basicsize = sizeof(PyLdbResultObject),
2523 .tp_as_sequence = &py_ldb_result_seq,
2524 .tp_doc = "LDB result.",
2525 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2528 static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
2530 Py_XDECREF(self->state.exception);
2531 TALLOC_FREE(self->mem_ctx);
2532 ZERO_STRUCT(self->state);
2533 Py_DECREF(self->ldb);
2534 Py_TYPE(self)->tp_free(self);
2537 static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
2539 PyObject *py_ret = NULL;
2541 if (self->state.req == NULL) {
2542 PyErr_SetString(PyExc_RuntimeError,
2543 "ldb.SearchIterator request already finished");
2544 return NULL;
2548 * TODO: do we want a non-blocking mode?
2549 * In future we may add an optional 'nonblocking'
2550 * argument to search_iterator().
2552 * For now we keep it simple and wait for at
2553 * least one reply.
2556 while (self->state.next == NULL) {
2557 int ret;
2559 if (self->state.result != NULL) {
2561 * We (already) got a final result from the server.
2563 * We stop the iteration and let
2564 * py_ldb_search_iterator_result() will deliver
2565 * the result details.
2567 TALLOC_FREE(self->state.req);
2568 PyErr_SetNone(PyExc_StopIteration);
2569 return NULL;
2572 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
2573 if (ret != LDB_SUCCESS) {
2574 struct ldb_context *ldb_ctx;
2575 TALLOC_FREE(self->state.req);
2576 ldb_ctx = pyldb_Ldb_AsLdbContext(self->ldb);
2578 * We stop the iteration and let
2579 * py_ldb_search_iterator_result() will deliver
2580 * the exception.
2582 self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
2583 ret, ldb_errstring(ldb_ctx));
2584 PyErr_SetNone(PyExc_StopIteration);
2585 return NULL;
2589 py_ret = self->state.next->obj;
2590 self->state.next->obj = NULL;
2591 /* no TALLOC_FREE() as self->state.next is a list */
2592 talloc_free(self->state.next);
2593 return py_ret;
2596 static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self)
2598 PyObject *py_ret = NULL;
2600 if (self->state.req != NULL) {
2601 PyErr_SetString(PyExc_RuntimeError,
2602 "ldb.SearchIterator request running");
2603 return NULL;
2606 if (self->state.next != NULL) {
2607 PyErr_SetString(PyExc_RuntimeError,
2608 "ldb.SearchIterator not fully consumed.");
2609 return NULL;
2612 if (self->state.exception != NULL) {
2613 PyErr_SetObject(PyExc_LdbError, self->state.exception);
2614 self->state.exception = NULL;
2615 return NULL;
2618 if (self->state.result == NULL) {
2619 PyErr_SetString(PyExc_RuntimeError,
2620 "ldb.SearchIterator result already consumed");
2621 return NULL;
2624 py_ret = self->state.result->obj;
2625 self->state.result->obj = NULL;
2626 TALLOC_FREE(self->state.result);
2627 return py_ret;
2630 static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self)
2632 if (self->state.req == NULL) {
2633 PyErr_SetString(PyExc_RuntimeError,
2634 "ldb.SearchIterator request already finished");
2635 return NULL;
2638 Py_XDECREF(self->state.exception);
2639 TALLOC_FREE(self->mem_ctx);
2640 ZERO_STRUCT(self->state);
2641 Py_RETURN_NONE;
2644 static PyMethodDef py_ldb_search_iterator_methods[] = {
2645 { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
2646 "S.result() -> ldb.Result (without msgs and referrals)\n" },
2647 { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
2648 "S.abandon()\n" },
2649 { NULL }
2652 static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
2654 return PyStr_FromString("<ldb search iterator>");
2657 static PyTypeObject PyLdbSearchIterator = {
2658 .tp_name = "ldb.SearchIterator",
2659 .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
2660 .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
2661 .tp_iter = PyObject_SelfIter,
2662 .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
2663 .tp_methods = py_ldb_search_iterator_methods,
2664 .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
2665 .tp_doc = "LDB search_iterator.",
2666 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
2669 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
2671 return PyStr_FromFormat("<ldb module '%s'>",
2672 pyldb_Module_AsModule(self)->ops->name);
2675 static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
2677 return PyStr_FromString(pyldb_Module_AsModule(self)->ops->name);
2680 static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self)
2682 pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
2683 Py_RETURN_NONE;
2686 static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self)
2688 pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
2689 Py_RETURN_NONE;
2692 static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
2694 pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
2695 Py_RETURN_NONE;
2698 static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
2700 PyObject *py_base, *py_tree, *py_attrs, *py_ret;
2701 int ret, scope;
2702 struct ldb_request *req;
2703 const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
2704 struct ldb_module *mod;
2705 const char * const*attrs;
2707 /* type "int" rather than "enum" for "scope" is intentional */
2708 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
2709 discard_const_p(char *, kwnames),
2710 &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
2711 return NULL;
2713 mod = self->mod;
2715 if (py_attrs == Py_None) {
2716 attrs = NULL;
2717 } else {
2718 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
2719 if (attrs == NULL)
2720 return NULL;
2723 ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AsDn(py_base),
2724 scope, NULL /* expr */, attrs,
2725 NULL /* controls */, NULL, NULL, NULL);
2727 talloc_steal(req, attrs);
2729 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2731 req->op.search.res = NULL;
2733 ret = mod->ops->search(mod, req);
2735 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2737 py_ret = PyLdbResult_FromResult(req->op.search.res);
2739 talloc_free(req);
2741 return py_ret;
2745 static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
2747 struct ldb_request *req;
2748 PyObject *py_message;
2749 int ret;
2750 struct ldb_module *mod;
2752 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2753 return NULL;
2755 req = talloc_zero(NULL, struct ldb_request);
2756 req->operation = LDB_ADD;
2757 req->op.add.message = pyldb_Message_AsMessage(py_message);
2759 mod = pyldb_Module_AsModule(self);
2760 ret = mod->ops->add(mod, req);
2762 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2764 Py_RETURN_NONE;
2767 static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
2769 int ret;
2770 struct ldb_request *req;
2771 PyObject *py_message;
2772 struct ldb_module *mod;
2774 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
2775 return NULL;
2777 req = talloc_zero(NULL, struct ldb_request);
2778 req->operation = LDB_MODIFY;
2779 req->op.mod.message = pyldb_Message_AsMessage(py_message);
2781 mod = pyldb_Module_AsModule(self);
2782 ret = mod->ops->modify(mod, req);
2784 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
2786 Py_RETURN_NONE;
2789 static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
2791 int ret;
2792 struct ldb_request *req;
2793 PyObject *py_dn;
2795 if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
2796 return NULL;
2798 req = talloc_zero(NULL, struct ldb_request);
2799 req->operation = LDB_DELETE;
2800 req->op.del.dn = pyldb_Dn_AsDn(py_dn);
2802 ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
2804 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2806 Py_RETURN_NONE;
2809 static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
2811 int ret;
2812 struct ldb_request *req;
2813 PyObject *py_dn1, *py_dn2;
2815 if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
2816 return NULL;
2818 req = talloc_zero(NULL, struct ldb_request);
2820 req->operation = LDB_RENAME;
2821 req->op.rename.olddn = pyldb_Dn_AsDn(py_dn1);
2822 req->op.rename.newdn = pyldb_Dn_AsDn(py_dn2);
2824 ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
2826 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
2828 Py_RETURN_NONE;
2831 static PyMethodDef py_ldb_module_methods[] = {
2832 { "search", (PyCFunction)py_ldb_module_search, METH_VARARGS|METH_KEYWORDS, NULL },
2833 { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
2834 { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
2835 { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
2836 { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
2837 { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
2838 { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
2839 { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
2840 { NULL },
2843 static void py_ldb_module_dealloc(PyLdbModuleObject *self)
2845 talloc_free(self->mem_ctx);
2846 PyObject_Del(self);
2849 static PyTypeObject PyLdbModule = {
2850 .tp_name = "ldb.LdbModule",
2851 .tp_methods = py_ldb_module_methods,
2852 .tp_repr = (reprfunc)py_ldb_module_repr,
2853 .tp_str = (reprfunc)py_ldb_module_str,
2854 .tp_basicsize = sizeof(PyLdbModuleObject),
2855 .tp_dealloc = (destructor)py_ldb_module_dealloc,
2856 .tp_flags = Py_TPFLAGS_DEFAULT,
2857 .tp_doc = "LDB module (extension)",
2862 * Create a ldb_message_element from a Python object.
2864 * This will accept any sequence objects that contains strings, or
2865 * a string object.
2867 * A reference to set_obj will be borrowed.
2869 * @param mem_ctx Memory context
2870 * @param set_obj Python object to convert
2871 * @param flags ldb_message_element flags to set
2872 * @param attr_name Name of the attribute
2873 * @return New ldb_message_element, allocated as child of mem_ctx
2875 static struct ldb_message_element *PyObject_AsMessageElement(
2876 TALLOC_CTX *mem_ctx,
2877 PyObject *set_obj,
2878 unsigned int flags,
2879 const char *attr_name)
2881 struct ldb_message_element *me;
2882 const char *msg = NULL;
2883 Py_ssize_t size;
2884 int result;
2886 if (pyldb_MessageElement_Check(set_obj)) {
2887 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
2888 /* We have to talloc_reference() the memory context, not the pointer
2889 * which may not actually be it's own context */
2890 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
2891 return pyldb_MessageElement_AsMessageElement(set_obj);
2893 return NULL;
2896 me = talloc(mem_ctx, struct ldb_message_element);
2897 if (me == NULL) {
2898 PyErr_NoMemory();
2899 return NULL;
2902 me->name = talloc_strdup(me, attr_name);
2903 me->flags = flags;
2904 if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
2905 me->num_values = 1;
2906 me->values = talloc_array(me, struct ldb_val, me->num_values);
2907 if (PyBytes_Check(set_obj)) {
2908 char *_msg = NULL;
2909 result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
2910 if (result != 0) {
2911 talloc_free(me);
2912 return NULL;
2914 msg = _msg;
2915 } else {
2916 msg = PyStr_AsUTF8AndSize(set_obj, &size);
2917 if (msg == NULL) {
2918 talloc_free(me);
2919 return NULL;
2922 me->values[0].data = talloc_memdup(me,
2923 (const uint8_t *)msg,
2924 size+1);
2925 me->values[0].length = size;
2926 } else if (PySequence_Check(set_obj)) {
2927 Py_ssize_t i;
2928 me->num_values = PySequence_Size(set_obj);
2929 me->values = talloc_array(me, struct ldb_val, me->num_values);
2930 for (i = 0; i < me->num_values; i++) {
2931 PyObject *obj = PySequence_GetItem(set_obj, i);
2932 if (PyBytes_Check(obj)) {
2933 char *_msg = NULL;
2934 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
2935 if (result != 0) {
2936 talloc_free(me);
2937 return NULL;
2939 msg = _msg;
2940 } else if (PyUnicode_Check(obj)) {
2941 msg = PyStr_AsUTF8AndSize(obj, &size);
2942 if (msg == NULL) {
2943 talloc_free(me);
2944 return NULL;
2946 } else {
2947 PyErr_Format(PyExc_TypeError,
2948 "Expected string as element %zd in list", i);
2949 talloc_free(me);
2950 return NULL;
2952 me->values[i].data = talloc_memdup(me,
2953 (const uint8_t *)msg,
2954 size+1);
2955 me->values[i].length = size;
2957 } else {
2958 PyErr_Format(PyExc_TypeError,
2959 "String or List type expected for '%s' attribute", attr_name);
2960 talloc_free(me);
2961 me = NULL;
2964 return me;
2968 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
2969 struct ldb_message_element *me)
2971 Py_ssize_t i;
2972 PyObject *result;
2974 /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
2975 result = PyList_New(me->num_values);
2977 for (i = 0; i < me->num_values; i++) {
2978 PyList_SetItem(result, i,
2979 PyObject_FromLdbValue(&me->values[i]));
2982 return result;
2985 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
2987 unsigned int i;
2988 if (!PyArg_ParseTuple(args, "I", &i))
2989 return NULL;
2990 if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
2991 Py_RETURN_NONE;
2993 return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
2996 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
2998 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
2999 return PyInt_FromLong(el->flags);
3002 static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
3004 unsigned int flags;
3005 struct ldb_message_element *el;
3006 if (!PyArg_ParseTuple(args, "I", &flags))
3007 return NULL;
3009 el = pyldb_MessageElement_AsMessageElement(self);
3010 el->flags = flags;
3011 Py_RETURN_NONE;
3014 static PyMethodDef py_ldb_msg_element_methods[] = {
3015 { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
3016 { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
3017 { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
3018 { NULL },
3021 static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
3023 return pyldb_MessageElement_AsMessageElement(self)->num_values;
3026 static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
3028 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3029 if (idx < 0 || idx >= el->num_values) {
3030 PyErr_SetString(PyExc_IndexError, "Out of range");
3031 return NULL;
3033 return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
3036 static PySequenceMethods py_ldb_msg_element_seq = {
3037 .sq_length = (lenfunc)py_ldb_msg_element_len,
3038 .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
3041 static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
3043 int ret;
3044 if (!pyldb_MessageElement_Check(other)) {
3045 Py_INCREF(Py_NotImplemented);
3046 return Py_NotImplemented;
3048 ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
3049 pyldb_MessageElement_AsMessageElement(other));
3050 return richcmp(ret, op);
3053 static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
3055 PyObject *el = ldb_msg_element_to_set(NULL,
3056 pyldb_MessageElement_AsMessageElement(self));
3057 PyObject *ret = PyObject_GetIter(el);
3058 Py_DECREF(el);
3059 return ret;
3062 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
3064 PyLdbMessageElementObject *ret;
3065 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
3066 if (ret == NULL) {
3067 PyErr_NoMemory();
3068 return NULL;
3070 ret->mem_ctx = talloc_new(NULL);
3071 if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
3072 PyErr_NoMemory();
3073 return NULL;
3075 ret->el = el;
3076 return (PyObject *)ret;
3079 static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3081 PyObject *py_elements = NULL;
3082 struct ldb_message_element *el;
3083 unsigned int flags = 0;
3084 char *name = NULL;
3085 const char * const kwnames[] = { "elements", "flags", "name", NULL };
3086 PyLdbMessageElementObject *ret;
3087 TALLOC_CTX *mem_ctx;
3088 const char *msg = NULL;
3089 Py_ssize_t size;
3090 int result;
3092 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
3093 discard_const_p(char *, kwnames),
3094 &py_elements, &flags, &name))
3095 return NULL;
3097 mem_ctx = talloc_new(NULL);
3098 if (mem_ctx == NULL) {
3099 PyErr_NoMemory();
3100 return NULL;
3103 el = talloc_zero(mem_ctx, struct ldb_message_element);
3104 if (el == NULL) {
3105 PyErr_NoMemory();
3106 talloc_free(mem_ctx);
3107 return NULL;
3110 if (py_elements != NULL) {
3111 Py_ssize_t i;
3112 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
3113 char *_msg = NULL;
3114 el->num_values = 1;
3115 el->values = talloc_array(el, struct ldb_val, 1);
3116 if (el->values == NULL) {
3117 talloc_free(mem_ctx);
3118 PyErr_NoMemory();
3119 return NULL;
3121 if (PyBytes_Check(py_elements)) {
3122 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
3123 msg = _msg;
3124 } else {
3125 msg = PyStr_AsUTF8AndSize(py_elements, &size);
3126 result = (msg == NULL) ? -1 : 0;
3128 if (result != 0) {
3129 talloc_free(mem_ctx);
3130 return NULL;
3132 el->values[0].data = talloc_memdup(el->values,
3133 (const uint8_t *)msg, size + 1);
3134 el->values[0].length = size;
3135 } else if (PySequence_Check(py_elements)) {
3136 el->num_values = PySequence_Size(py_elements);
3137 el->values = talloc_array(el, struct ldb_val, el->num_values);
3138 if (el->values == NULL) {
3139 talloc_free(mem_ctx);
3140 PyErr_NoMemory();
3141 return NULL;
3143 for (i = 0; i < el->num_values; i++) {
3144 PyObject *item = PySequence_GetItem(py_elements, i);
3145 if (item == NULL) {
3146 talloc_free(mem_ctx);
3147 return NULL;
3149 if (PyBytes_Check(item)) {
3150 char *_msg = NULL;
3151 result = PyBytes_AsStringAndSize(item, &_msg, &size);
3152 msg = _msg;
3153 } else if (PyUnicode_Check(item)) {
3154 msg = PyStr_AsUTF8AndSize(item, &size);
3155 result = (msg == NULL) ? -1 : 0;
3156 } else {
3157 PyErr_Format(PyExc_TypeError,
3158 "Expected string as element %zd in list", i);
3159 result = -1;
3161 if (result != 0) {
3162 talloc_free(mem_ctx);
3163 return NULL;
3165 el->values[i].data = talloc_memdup(el,
3166 (const uint8_t *)msg, size+1);
3167 el->values[i].length = size;
3169 } else {
3170 PyErr_SetString(PyExc_TypeError,
3171 "Expected string or list");
3172 talloc_free(mem_ctx);
3173 return NULL;
3177 el->flags = flags;
3178 el->name = talloc_strdup(el, name);
3180 ret = PyObject_New(PyLdbMessageElementObject, type);
3181 if (ret == NULL) {
3182 talloc_free(mem_ctx);
3183 return NULL;
3186 ret->mem_ctx = mem_ctx;
3187 ret->el = el;
3188 return (PyObject *)ret;
3191 static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
3193 char *element_str = NULL;
3194 Py_ssize_t i;
3195 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3196 PyObject *ret, *repr;
3198 for (i = 0; i < el->num_values; i++) {
3199 PyObject *o = py_ldb_msg_element_find(self, i);
3200 repr = PyObject_Repr(o);
3201 if (element_str == NULL)
3202 element_str = talloc_strdup(NULL, PyStr_AsUTF8(repr));
3203 else
3204 element_str = talloc_asprintf_append(element_str, ",%s", PyStr_AsUTF8(repr));
3205 Py_DECREF(repr);
3208 if (element_str != NULL) {
3209 ret = PyStr_FromFormat("MessageElement([%s])", element_str);
3210 talloc_free(element_str);
3211 } else {
3212 ret = PyStr_FromString("MessageElement([])");
3215 return ret;
3218 static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
3220 struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
3222 if (el->num_values == 1)
3223 return PyStr_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
3224 else
3225 Py_RETURN_NONE;
3228 static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
3230 talloc_free(self->mem_ctx);
3231 PyObject_Del(self);
3234 static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
3236 return wrap_text("MessageElementTextWrapper", self);
3239 static PyGetSetDef py_ldb_msg_element_getset[] = {
3240 { discard_const_p(char, "text"), (getter)py_ldb_msg_element_get_text, NULL, NULL },
3241 { NULL }
3244 static PyTypeObject PyLdbMessageElement = {
3245 .tp_name = "ldb.MessageElement",
3246 .tp_basicsize = sizeof(PyLdbMessageElementObject),
3247 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
3248 .tp_repr = (reprfunc)py_ldb_msg_element_repr,
3249 .tp_str = (reprfunc)py_ldb_msg_element_str,
3250 .tp_methods = py_ldb_msg_element_methods,
3251 .tp_getset = py_ldb_msg_element_getset,
3252 .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
3253 .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
3254 .tp_as_sequence = &py_ldb_msg_element_seq,
3255 .tp_new = py_ldb_msg_element_new,
3256 .tp_flags = Py_TPFLAGS_DEFAULT,
3257 .tp_doc = "An element of a Message",
3261 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
3263 PyObject *py_ldb;
3264 PyObject *py_dict;
3265 PyObject *py_ret;
3266 struct ldb_message *msg;
3267 struct ldb_context *ldb_ctx;
3268 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
3270 if (!PyArg_ParseTuple(args, "O!O!|I",
3271 &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
3272 &mod_flags)) {
3273 return NULL;
3276 if (!PyLdb_Check(py_ldb)) {
3277 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
3278 return NULL;
3281 /* mask only flags we are going to use */
3282 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
3283 if (!mod_flags) {
3284 PyErr_SetString(PyExc_ValueError,
3285 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
3286 " expected as mod_flag value");
3287 return NULL;
3290 ldb_ctx = pyldb_Ldb_AsLdbContext(py_ldb);
3292 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
3293 if (!msg) {
3294 return NULL;
3297 py_ret = PyLdbMessage_FromMessage(msg);
3299 talloc_unlink(ldb_ctx, msg);
3301 return py_ret;
3304 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
3306 char *name;
3307 if (!PyArg_ParseTuple(args, "s", &name))
3308 return NULL;
3310 ldb_msg_remove_attr(self->msg, name);
3312 Py_RETURN_NONE;
3315 static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
3317 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3318 Py_ssize_t i, j = 0;
3319 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
3320 if (msg->dn != NULL) {
3321 PyList_SetItem(obj, j, PyStr_FromString("dn"));
3322 j++;
3324 for (i = 0; i < msg->num_elements; i++) {
3325 PyList_SetItem(obj, j, PyStr_FromString(msg->elements[i].name));
3326 j++;
3328 return obj;
3331 static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
3333 struct ldb_message_element *el;
3334 const char *name;
3335 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3336 name = PyStr_AsUTF8(py_name);
3337 if (name == NULL) {
3338 PyErr_SetNone(PyExc_TypeError);
3339 return NULL;
3341 if (!ldb_attr_cmp(name, "dn"))
3342 return pyldb_Dn_FromDn(msg->dn);
3343 el = ldb_msg_find_element(msg, name);
3344 if (el == NULL) {
3345 return NULL;
3347 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3350 static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
3352 PyObject *ret = py_ldb_msg_getitem_helper(self, py_name);
3353 if (ret == NULL) {
3354 PyErr_SetString(PyExc_KeyError, "No such element");
3355 return NULL;
3357 return ret;
3360 static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
3362 PyObject *def = NULL;
3363 const char *kwnames[] = { "name", "default", "idx", NULL };
3364 const char *name = NULL;
3365 int idx = -1;
3366 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3367 struct ldb_message_element *el;
3369 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
3370 discard_const_p(char *, kwnames), &name, &def, &idx)) {
3371 return NULL;
3374 if (strcasecmp(name, "dn") == 0) {
3375 return pyldb_Dn_FromDn(msg->dn);
3378 el = ldb_msg_find_element(msg, name);
3380 if (el == NULL || (idx != -1 && el->num_values <= idx)) {
3381 if (def != NULL) {
3382 Py_INCREF(def);
3383 return def;
3385 Py_RETURN_NONE;
3388 if (idx == -1) {
3389 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
3392 return PyObject_FromLdbValue(&el->values[idx]);
3395 static PyObject *py_ldb_msg_items(PyLdbMessageObject *self)
3397 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3398 Py_ssize_t i, j = 0;
3399 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
3400 if (msg->dn != NULL) {
3401 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", pyldb_Dn_FromDn(msg->dn)));
3402 j++;
3404 for (i = 0; i < msg->num_elements; i++, j++) {
3405 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
3406 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
3407 PyList_SetItem(l, j, value);
3409 return l;
3412 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self)
3414 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3415 Py_ssize_t i = 0;
3416 PyObject *l = PyList_New(msg->num_elements);
3417 for (i = 0; i < msg->num_elements; i++) {
3418 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
3420 return l;
3423 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
3425 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3426 PyLdbMessageElementObject *py_element;
3427 int i, ret;
3428 struct ldb_message_element *el;
3429 struct ldb_message_element *el_new;
3431 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
3432 return NULL;
3434 el = py_element->el;
3435 if (el == NULL) {
3436 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
3437 return NULL;
3440 ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
3441 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
3443 /* now deep copy all attribute values */
3444 el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
3445 if (el_new->values == NULL) {
3446 PyErr_NoMemory();
3447 return NULL;
3449 el_new->num_values = el->num_values;
3451 for (i = 0; i < el->num_values; i++) {
3452 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
3453 if (el_new->values[i].data == NULL
3454 && el->values[i].length != 0) {
3455 PyErr_NoMemory();
3456 return NULL;
3460 Py_RETURN_NONE;
3463 static PyMethodDef py_ldb_msg_methods[] = {
3464 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
3465 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
3466 "Class method to create ldb.Message object from Dictionary.\n"
3467 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
3468 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
3469 "S.keys() -> list\n\n"
3470 "Return sequence of all attribute names." },
3471 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS,
3472 "S.remove(name)\n\n"
3473 "Remove all entries for attributes with the specified name."},
3474 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS | METH_KEYWORDS,
3475 "msg.get(name,default=None,idx=None) -> string\n"
3476 "idx is the index into the values array\n"
3477 "if idx is None, then a list is returned\n"
3478 "if idx is not None, then the element with that index is returned\n"
3479 "if you pass the special name 'dn' then the DN object is returned\n"},
3480 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
3481 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
3482 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
3483 "S.add(element)\n\n"
3484 "Add an element to this message." },
3485 { NULL },
3488 static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
3490 PyObject *list, *iter;
3492 list = py_ldb_msg_keys(self);
3493 iter = PyObject_GetIter(list);
3494 Py_DECREF(list);
3495 return iter;
3498 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
3500 const char *attr_name;
3502 attr_name = PyStr_AsUTF8(name);
3503 if (attr_name == NULL) {
3504 PyErr_SetNone(PyExc_TypeError);
3505 return -1;
3508 if (value == NULL) {
3509 /* delitem */
3510 ldb_msg_remove_attr(self->msg, attr_name);
3511 } else {
3512 int ret;
3513 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
3514 value, 0, attr_name);
3515 if (el == NULL) {
3516 return -1;
3518 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
3519 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
3520 if (ret != LDB_SUCCESS) {
3521 PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
3522 return -1;
3525 return 0;
3528 static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
3530 return pyldb_Message_AsMessage(self)->num_elements;
3533 static PyMappingMethods py_ldb_msg_mapping = {
3534 .mp_length = (lenfunc)py_ldb_msg_length,
3535 .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
3536 .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
3539 static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
3541 const char * const kwnames[] = { "dn", NULL };
3542 struct ldb_message *ret;
3543 TALLOC_CTX *mem_ctx;
3544 PyObject *pydn = NULL;
3545 PyLdbMessageObject *py_ret;
3547 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
3548 discard_const_p(char *, kwnames),
3549 &pydn))
3550 return NULL;
3552 mem_ctx = talloc_new(NULL);
3553 if (mem_ctx == NULL) {
3554 PyErr_NoMemory();
3555 return NULL;
3558 ret = ldb_msg_new(mem_ctx);
3559 if (ret == NULL) {
3560 talloc_free(mem_ctx);
3561 PyErr_NoMemory();
3562 return NULL;
3565 if (pydn != NULL) {
3566 struct ldb_dn *dn;
3567 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
3568 talloc_free(mem_ctx);
3569 return NULL;
3571 ret->dn = talloc_reference(ret, dn);
3574 py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
3575 if (py_ret == NULL) {
3576 PyErr_NoMemory();
3577 talloc_free(mem_ctx);
3578 return NULL;
3581 py_ret->mem_ctx = mem_ctx;
3582 py_ret->msg = ret;
3583 return (PyObject *)py_ret;
3586 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
3588 PyLdbMessageObject *ret;
3590 ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
3591 if (ret == NULL) {
3592 PyErr_NoMemory();
3593 return NULL;
3595 ret->mem_ctx = talloc_new(NULL);
3596 ret->msg = talloc_reference(ret->mem_ctx, msg);
3597 return (PyObject *)ret;
3600 static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
3602 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3603 return pyldb_Dn_FromDn(msg->dn);
3606 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
3608 struct ldb_message *msg = pyldb_Message_AsMessage(self);
3609 if (!pyldb_Dn_Check(value)) {
3610 PyErr_SetString(PyExc_TypeError, "expected dn");
3611 return -1;
3614 msg->dn = talloc_reference(msg, pyldb_Dn_AsDn(value));
3615 return 0;
3618 static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
3620 return wrap_text("MessageTextWrapper", self);
3623 static PyGetSetDef py_ldb_msg_getset[] = {
3624 { discard_const_p(char, "dn"), (getter)py_ldb_msg_get_dn, (setter)py_ldb_msg_set_dn, NULL },
3625 { discard_const_p(char, "text"), (getter)py_ldb_msg_get_text, NULL, NULL },
3626 { NULL }
3629 static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
3631 PyObject *dict = PyDict_New(), *ret, *repr;
3632 if (PyDict_Update(dict, (PyObject *)self) != 0)
3633 return NULL;
3634 repr = PyObject_Repr(dict);
3635 if (repr == NULL) {
3636 Py_DECREF(dict);
3637 return NULL;
3639 ret = PyStr_FromFormat("Message(%s)", PyStr_AsUTF8(repr));
3640 Py_DECREF(repr);
3641 Py_DECREF(dict);
3642 return ret;
3645 static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
3647 talloc_free(self->mem_ctx);
3648 PyObject_Del(self);
3651 static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
3652 PyLdbMessageObject *py_msg2, int op)
3654 struct ldb_message *msg1, *msg2;
3655 unsigned int i;
3656 int ret;
3658 if (!PyLdbMessage_Check(py_msg2)) {
3659 Py_INCREF(Py_NotImplemented);
3660 return Py_NotImplemented;
3663 msg1 = pyldb_Message_AsMessage(py_msg1),
3664 msg2 = pyldb_Message_AsMessage(py_msg2);
3666 if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
3667 ret = ldb_dn_compare(msg1->dn, msg2->dn);
3668 if (ret != 0) {
3669 return richcmp(ret, op);
3673 ret = msg1->num_elements - msg2->num_elements;
3674 if (ret != 0) {
3675 return richcmp(ret, op);
3678 for (i = 0; i < msg1->num_elements; i++) {
3679 ret = ldb_msg_element_compare_name(&msg1->elements[i],
3680 &msg2->elements[i]);
3681 if (ret != 0) {
3682 return richcmp(ret, op);
3685 ret = ldb_msg_element_compare(&msg1->elements[i],
3686 &msg2->elements[i]);
3687 if (ret != 0) {
3688 return richcmp(ret, op);
3692 return richcmp(0, op);
3695 static PyTypeObject PyLdbMessage = {
3696 .tp_name = "ldb.Message",
3697 .tp_methods = py_ldb_msg_methods,
3698 .tp_getset = py_ldb_msg_getset,
3699 .tp_as_mapping = &py_ldb_msg_mapping,
3700 .tp_basicsize = sizeof(PyLdbMessageObject),
3701 .tp_dealloc = (destructor)py_ldb_msg_dealloc,
3702 .tp_new = py_ldb_msg_new,
3703 .tp_repr = (reprfunc)py_ldb_msg_repr,
3704 .tp_flags = Py_TPFLAGS_DEFAULT,
3705 .tp_iter = (getiterfunc)py_ldb_msg_iter,
3706 .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
3707 .tp_doc = "A LDB Message",
3710 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
3712 PyLdbTreeObject *ret;
3714 ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
3715 if (ret == NULL) {
3716 PyErr_NoMemory();
3717 return NULL;
3720 ret->mem_ctx = talloc_new(NULL);
3721 ret->tree = talloc_reference(ret->mem_ctx, tree);
3722 return (PyObject *)ret;
3725 static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
3727 talloc_free(self->mem_ctx);
3728 PyObject_Del(self);
3731 static PyTypeObject PyLdbTree = {
3732 .tp_name = "ldb.Tree",
3733 .tp_basicsize = sizeof(PyLdbTreeObject),
3734 .tp_dealloc = (destructor)py_ldb_tree_dealloc,
3735 .tp_flags = Py_TPFLAGS_DEFAULT,
3736 .tp_doc = "A search tree",
3739 /* Ldb_module */
3740 static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
3742 PyObject *py_ldb = (PyObject *)mod->private_data;
3743 PyObject *py_result, *py_base, *py_attrs, *py_tree;
3745 py_base = pyldb_Dn_FromDn(req->op.search.base);
3747 if (py_base == NULL)
3748 return LDB_ERR_OPERATIONS_ERROR;
3750 py_tree = PyLdbTree_FromTree(req->op.search.tree);
3752 if (py_tree == NULL)
3753 return LDB_ERR_OPERATIONS_ERROR;
3755 if (req->op.search.attrs == NULL) {
3756 py_attrs = Py_None;
3757 } else {
3758 int i, len;
3759 for (len = 0; req->op.search.attrs[len]; len++);
3760 py_attrs = PyList_New(len);
3761 for (i = 0; i < len; i++)
3762 PyList_SetItem(py_attrs, i, PyStr_FromString(req->op.search.attrs[i]));
3765 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
3766 discard_const_p(char, "OiOO"),
3767 py_base, req->op.search.scope, py_tree, py_attrs);
3769 Py_DECREF(py_attrs);
3770 Py_DECREF(py_tree);
3771 Py_DECREF(py_base);
3773 if (py_result == NULL) {
3774 return LDB_ERR_PYTHON_EXCEPTION;
3777 req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
3778 if (req->op.search.res == NULL) {
3779 return LDB_ERR_PYTHON_EXCEPTION;
3782 Py_DECREF(py_result);
3784 return LDB_SUCCESS;
3787 static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
3789 PyObject *py_ldb = (PyObject *)mod->private_data;
3790 PyObject *py_result, *py_msg;
3792 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
3794 if (py_msg == NULL) {
3795 return LDB_ERR_OPERATIONS_ERROR;
3798 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
3799 discard_const_p(char, "O"),
3800 py_msg);
3802 Py_DECREF(py_msg);
3804 if (py_result == NULL) {
3805 return LDB_ERR_PYTHON_EXCEPTION;
3808 Py_DECREF(py_result);
3810 return LDB_SUCCESS;
3813 static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
3815 PyObject *py_ldb = (PyObject *)mod->private_data;
3816 PyObject *py_result, *py_msg;
3818 py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
3820 if (py_msg == NULL) {
3821 return LDB_ERR_OPERATIONS_ERROR;
3824 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
3825 discard_const_p(char, "O"),
3826 py_msg);
3828 Py_DECREF(py_msg);
3830 if (py_result == NULL) {
3831 return LDB_ERR_PYTHON_EXCEPTION;
3834 Py_DECREF(py_result);
3836 return LDB_SUCCESS;
3839 static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
3841 PyObject *py_ldb = (PyObject *)mod->private_data;
3842 PyObject *py_result, *py_dn;
3844 py_dn = pyldb_Dn_FromDn(req->op.del.dn);
3846 if (py_dn == NULL)
3847 return LDB_ERR_OPERATIONS_ERROR;
3849 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
3850 discard_const_p(char, "O"),
3851 py_dn);
3853 if (py_result == NULL) {
3854 return LDB_ERR_PYTHON_EXCEPTION;
3857 Py_DECREF(py_result);
3859 return LDB_SUCCESS;
3862 static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
3864 PyObject *py_ldb = (PyObject *)mod->private_data;
3865 PyObject *py_result, *py_olddn, *py_newdn;
3867 py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
3869 if (py_olddn == NULL)
3870 return LDB_ERR_OPERATIONS_ERROR;
3872 py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
3874 if (py_newdn == NULL)
3875 return LDB_ERR_OPERATIONS_ERROR;
3877 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
3878 discard_const_p(char, "OO"),
3879 py_olddn, py_newdn);
3881 Py_DECREF(py_olddn);
3882 Py_DECREF(py_newdn);
3884 if (py_result == NULL) {
3885 return LDB_ERR_PYTHON_EXCEPTION;
3888 Py_DECREF(py_result);
3890 return LDB_SUCCESS;
3893 static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
3895 PyObject *py_ldb = (PyObject *)mod->private_data;
3896 PyObject *py_result;
3898 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
3899 discard_const_p(char, ""));
3901 Py_XDECREF(py_result);
3903 return LDB_ERR_OPERATIONS_ERROR;
3906 static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
3908 PyObject *py_ldb = (PyObject *)mod->private_data;
3909 PyObject *py_result;
3911 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
3912 discard_const_p(char, ""));
3914 Py_XDECREF(py_result);
3916 return LDB_ERR_OPERATIONS_ERROR;
3919 static int py_module_start_transaction(struct ldb_module *mod)
3921 PyObject *py_ldb = (PyObject *)mod->private_data;
3922 PyObject *py_result;
3924 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
3925 discard_const_p(char, ""));
3927 if (py_result == NULL) {
3928 return LDB_ERR_PYTHON_EXCEPTION;
3931 Py_DECREF(py_result);
3933 return LDB_SUCCESS;
3936 static int py_module_end_transaction(struct ldb_module *mod)
3938 PyObject *py_ldb = (PyObject *)mod->private_data;
3939 PyObject *py_result;
3941 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
3942 discard_const_p(char, ""));
3944 if (py_result == NULL) {
3945 return LDB_ERR_PYTHON_EXCEPTION;
3948 Py_DECREF(py_result);
3950 return LDB_SUCCESS;
3953 static int py_module_del_transaction(struct ldb_module *mod)
3955 PyObject *py_ldb = (PyObject *)mod->private_data;
3956 PyObject *py_result;
3958 py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
3959 discard_const_p(char, ""));
3961 if (py_result == NULL) {
3962 return LDB_ERR_PYTHON_EXCEPTION;
3965 Py_DECREF(py_result);
3967 return LDB_SUCCESS;
3970 static int py_module_destructor(struct ldb_module *mod)
3972 Py_DECREF((PyObject *)mod->private_data);
3973 return 0;
3976 static int py_module_init(struct ldb_module *mod)
3978 PyObject *py_class = (PyObject *)mod->ops->private_data;
3979 PyObject *py_result, *py_next, *py_ldb;
3981 py_ldb = PyLdb_FromLdbContext(mod->ldb);
3983 if (py_ldb == NULL)
3984 return LDB_ERR_OPERATIONS_ERROR;
3986 py_next = PyLdbModule_FromModule(mod->next);
3988 if (py_next == NULL)
3989 return LDB_ERR_OPERATIONS_ERROR;
3991 py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
3992 py_ldb, py_next);
3994 if (py_result == NULL) {
3995 return LDB_ERR_PYTHON_EXCEPTION;
3998 mod->private_data = py_result;
4000 talloc_set_destructor(mod, py_module_destructor);
4002 return ldb_next_init(mod);
4005 static PyObject *py_register_module(PyObject *module, PyObject *args)
4007 int ret;
4008 struct ldb_module_ops *ops;
4009 PyObject *input;
4011 if (!PyArg_ParseTuple(args, "O", &input))
4012 return NULL;
4014 ops = talloc_zero(NULL, struct ldb_module_ops);
4015 if (ops == NULL) {
4016 PyErr_NoMemory();
4017 return NULL;
4020 ops->name = talloc_strdup(ops, PyStr_AsUTF8(PyObject_GetAttrString(input, discard_const_p(char, "name"))));
4022 Py_INCREF(input);
4023 ops->private_data = input;
4024 ops->init_context = py_module_init;
4025 ops->search = py_module_search;
4026 ops->add = py_module_add;
4027 ops->modify = py_module_modify;
4028 ops->del = py_module_del;
4029 ops->rename = py_module_rename;
4030 ops->request = py_module_request;
4031 ops->extended = py_module_extended;
4032 ops->start_transaction = py_module_start_transaction;
4033 ops->end_transaction = py_module_end_transaction;
4034 ops->del_transaction = py_module_del_transaction;
4036 ret = ldb_register_module(ops);
4037 if (ret != LDB_SUCCESS) {
4038 TALLOC_FREE(ops);
4041 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
4043 Py_RETURN_NONE;
4046 static PyObject *py_timestring(PyObject *module, PyObject *args)
4048 /* most times "time_t" is a signed integer type with 32 or 64 bit:
4049 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
4050 long int t_val;
4051 char *tresult;
4052 PyObject *ret;
4053 if (!PyArg_ParseTuple(args, "l", &t_val))
4054 return NULL;
4055 tresult = ldb_timestring(NULL, (time_t) t_val);
4056 ret = PyStr_FromString(tresult);
4057 talloc_free(tresult);
4058 return ret;
4061 static PyObject *py_string_to_time(PyObject *module, PyObject *args)
4063 char *str;
4064 if (!PyArg_ParseTuple(args, "s", &str))
4065 return NULL;
4067 return PyInt_FromLong(ldb_string_to_time(str));
4070 static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
4072 char *name;
4073 if (!PyArg_ParseTuple(args, "s", &name))
4074 return NULL;
4075 return PyBool_FromLong(ldb_valid_attr_name(name));
4079 encode a string using RFC2254 rules
4081 static PyObject *py_binary_encode(PyObject *self, PyObject *args)
4083 char *str, *encoded;
4084 Py_ssize_t size = 0;
4085 struct ldb_val val;
4086 PyObject *ret;
4088 if (!PyArg_ParseTuple(args, "s#", &str, &size))
4089 return NULL;
4090 val.data = (uint8_t *)str;
4091 val.length = size;
4093 encoded = ldb_binary_encode(NULL, val);
4094 if (encoded == NULL) {
4095 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
4096 return NULL;
4098 ret = PyStr_FromString(encoded);
4099 talloc_free(encoded);
4100 return ret;
4104 decode a string using RFC2254 rules
4106 static PyObject *py_binary_decode(PyObject *self, PyObject *args)
4108 char *str;
4109 struct ldb_val val;
4110 PyObject *ret;
4112 if (!PyArg_ParseTuple(args, "s", &str))
4113 return NULL;
4115 val = ldb_binary_decode(NULL, str);
4116 if (val.data == NULL) {
4117 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
4118 return NULL;
4120 ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
4121 talloc_free(val.data);
4122 return ret;
4125 static PyMethodDef py_ldb_global_methods[] = {
4126 { "register_module", py_register_module, METH_VARARGS,
4127 "S.register_module(module) -> None\n\n"
4128 "Register a LDB module."},
4129 { "timestring", py_timestring, METH_VARARGS,
4130 "S.timestring(int) -> string\n\n"
4131 "Generate a LDAP time string from a UNIX timestamp" },
4132 { "string_to_time", py_string_to_time, METH_VARARGS,
4133 "S.string_to_time(string) -> int\n\n"
4134 "Parse a LDAP time string into a UNIX timestamp." },
4135 { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
4136 "S.valid_attr_name(name) -> bool\n\nn"
4137 "Check whether the supplied name is a valid attribute name." },
4138 { "open", (PyCFunction)py_ldb_new, METH_VARARGS|METH_KEYWORDS,
4139 "S.open() -> Ldb\n\n"
4140 "Open a new LDB context." },
4141 { "binary_encode", py_binary_encode, METH_VARARGS,
4142 "S.binary_encode(string) -> string\n\n"
4143 "Perform a RFC2254 binary encoding on a string" },
4144 { "binary_decode", py_binary_decode, METH_VARARGS,
4145 "S.binary_decode(string) -> string\n\n"
4146 "Perform a RFC2254 binary decode on a string" },
4147 { NULL }
4150 #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."
4152 #if PY_MAJOR_VERSION >= 3
4153 static struct PyModuleDef moduledef = {
4154 PyModuleDef_HEAD_INIT,
4155 .m_name = "ldb",
4156 .m_doc = MODULE_DOC,
4157 .m_size = -1,
4158 .m_methods = py_ldb_global_methods,
4160 #endif
4162 static PyObject* module_init(void)
4164 PyObject *m;
4166 PyLdbBytesType.tp_base = &PyBytes_Type;
4167 if (PyType_Ready(&PyLdbBytesType) < 0) {
4168 return NULL;
4171 if (PyType_Ready(&PyLdbDn) < 0)
4172 return NULL;
4174 if (PyType_Ready(&PyLdbMessage) < 0)
4175 return NULL;
4177 if (PyType_Ready(&PyLdbMessageElement) < 0)
4178 return NULL;
4180 if (PyType_Ready(&PyLdb) < 0)
4181 return NULL;
4183 if (PyType_Ready(&PyLdbModule) < 0)
4184 return NULL;
4186 if (PyType_Ready(&PyLdbTree) < 0)
4187 return NULL;
4189 if (PyType_Ready(&PyLdbResult) < 0)
4190 return NULL;
4192 if (PyType_Ready(&PyLdbSearchIterator) < 0)
4193 return NULL;
4195 if (PyType_Ready(&PyLdbControl) < 0)
4196 return NULL;
4198 #if PY_MAJOR_VERSION >= 3
4199 m = PyModule_Create(&moduledef);
4200 #else
4201 m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
4202 #endif
4203 if (m == NULL)
4204 return NULL;
4206 #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
4208 ADD_LDB_INT(SEQ_HIGHEST_SEQ);
4209 ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
4210 ADD_LDB_INT(SEQ_NEXT);
4211 ADD_LDB_INT(SCOPE_DEFAULT);
4212 ADD_LDB_INT(SCOPE_BASE);
4213 ADD_LDB_INT(SCOPE_ONELEVEL);
4214 ADD_LDB_INT(SCOPE_SUBTREE);
4216 ADD_LDB_INT(CHANGETYPE_NONE);
4217 ADD_LDB_INT(CHANGETYPE_ADD);
4218 ADD_LDB_INT(CHANGETYPE_DELETE);
4219 ADD_LDB_INT(CHANGETYPE_MODIFY);
4221 ADD_LDB_INT(FLAG_MOD_ADD);
4222 ADD_LDB_INT(FLAG_MOD_REPLACE);
4223 ADD_LDB_INT(FLAG_MOD_DELETE);
4225 ADD_LDB_INT(ATTR_FLAG_HIDDEN);
4226 ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
4227 ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
4228 ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
4230 ADD_LDB_INT(SUCCESS);
4231 ADD_LDB_INT(ERR_OPERATIONS_ERROR);
4232 ADD_LDB_INT(ERR_PROTOCOL_ERROR);
4233 ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
4234 ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
4235 ADD_LDB_INT(ERR_COMPARE_FALSE);
4236 ADD_LDB_INT(ERR_COMPARE_TRUE);
4237 ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
4238 ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
4239 ADD_LDB_INT(ERR_REFERRAL);
4240 ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
4241 ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
4242 ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
4243 ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
4244 ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
4245 ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
4246 ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
4247 ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
4248 ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
4249 ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
4250 ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
4251 ADD_LDB_INT(ERR_ALIAS_PROBLEM);
4252 ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
4253 ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
4254 ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
4255 ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
4256 ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
4257 ADD_LDB_INT(ERR_BUSY);
4258 ADD_LDB_INT(ERR_UNAVAILABLE);
4259 ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
4260 ADD_LDB_INT(ERR_LOOP_DETECT);
4261 ADD_LDB_INT(ERR_NAMING_VIOLATION);
4262 ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
4263 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
4264 ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
4265 ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
4266 ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
4267 ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
4268 ADD_LDB_INT(ERR_OTHER);
4270 ADD_LDB_INT(FLG_RDONLY);
4271 ADD_LDB_INT(FLG_NOSYNC);
4272 ADD_LDB_INT(FLG_RECONNECT);
4273 ADD_LDB_INT(FLG_NOMMAP);
4274 ADD_LDB_INT(FLG_SHOW_BINARY);
4275 ADD_LDB_INT(FLG_ENABLE_TRACING);
4276 ADD_LDB_INT(FLG_DONT_CREATE_DB);
4279 /* Historical misspelling */
4280 PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
4282 PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
4284 PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
4285 PyModule_AddObject(m, "LdbError", PyExc_LdbError);
4287 Py_INCREF(&PyLdb);
4288 Py_INCREF(&PyLdbDn);
4289 Py_INCREF(&PyLdbModule);
4290 Py_INCREF(&PyLdbMessage);
4291 Py_INCREF(&PyLdbMessageElement);
4292 Py_INCREF(&PyLdbTree);
4293 Py_INCREF(&PyLdbResult);
4294 Py_INCREF(&PyLdbControl);
4296 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
4297 PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
4298 PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
4299 PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
4300 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
4301 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
4302 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
4304 PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
4306 #define ADD_LDB_STRING(val) PyModule_AddStringConstant(m, #val, LDB_## val)
4308 ADD_LDB_STRING(SYNTAX_DN);
4309 ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
4310 ADD_LDB_STRING(SYNTAX_INTEGER);
4311 ADD_LDB_STRING(SYNTAX_BOOLEAN);
4312 ADD_LDB_STRING(SYNTAX_OCTET_STRING);
4313 ADD_LDB_STRING(SYNTAX_UTC_TIME);
4314 ADD_LDB_STRING(OID_COMPARATOR_AND);
4315 ADD_LDB_STRING(OID_COMPARATOR_OR);
4317 return m;
4320 #if PY_MAJOR_VERSION >= 3
4321 PyMODINIT_FUNC PyInit_ldb(void);
4322 PyMODINIT_FUNC PyInit_ldb(void)
4324 return module_init();
4326 #else
4327 void initldb(void);
4328 void initldb(void)
4330 module_init();
4332 #endif