LCOV - code coverage report
Current view: top level - lib/ldb - pyldb.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 1525 2096 72.8 %
Date: 2024-06-13 04:01:37 Functions: 149 171 87.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    Python interface to ldb.
       5             : 
       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
      12             : 
      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
      16             : 
      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.
      21             : 
      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.
      26             : 
      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/>.
      29             : */
      30             : 
      31             : #include <Python.h>
      32             : #include "ldb_private.h"
      33             : #include "ldb_handlers.h"
      34             : #include "pyldb.h"
      35             : #include "dlinklist.h"
      36             : 
      37             : /* discard signature of 'func' in favour of 'target_sig' */
      38             : #define PY_DISCARD_FUNC_SIG(target_sig, func) (target_sig)(void(*)(void))func
      39             : 
      40             : struct py_ldb_search_iterator_reply;
      41             : 
      42             : typedef struct {
      43             :         PyObject_HEAD
      44             :         TALLOC_CTX *mem_ctx;
      45             :         PyLdbObject *ldb;
      46             :         struct {
      47             :                 struct ldb_request *req;
      48             :                 struct py_ldb_search_iterator_reply *next;
      49             :                 struct py_ldb_search_iterator_reply *result;
      50             :                 PyObject *exception;
      51             :         } state;
      52             : } PyLdbSearchIteratorObject;
      53             : 
      54             : struct py_ldb_search_iterator_reply {
      55             :         struct py_ldb_search_iterator_reply *prev, *next;
      56             :         PyLdbSearchIteratorObject *py_iter;
      57             :         PyObject *obj;
      58             : };
      59             : 
      60             : void initldb(void);
      61             : static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg);
      62             : static PyObject *PyExc_LdbError;
      63             : 
      64             : static PyTypeObject PyLdbControl;
      65             : static PyTypeObject PyLdbResult;
      66             : static PyTypeObject PyLdbSearchIterator;
      67             : static PyTypeObject PyLdbMessage;
      68             : #define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
      69             : static PyTypeObject PyLdbModule;
      70             : static PyTypeObject PyLdbDn;
      71             : #define pyldb_Dn_Check(ob) PyObject_TypeCheck(ob, &PyLdbDn)
      72             : static PyTypeObject PyLdb;
      73             : #define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
      74             : static PyTypeObject PyLdbMessageElement;
      75             : #define pyldb_MessageElement_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessageElement)
      76             : 
      77             : static PyTypeObject PyLdbTree;
      78             : static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
      79             : static PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
      80             : static struct ldb_message_element *PyObject_AsMessageElement(
      81             :                                                       TALLOC_CTX *mem_ctx,
      82             :                                                       PyObject *set_obj,
      83             :                                                       unsigned int flags,
      84             :                                                       const char *attr_name);
      85             : static PyTypeObject PyLdbBytesType;
      86             : 
      87             : #if PY_MAJOR_VERSION >= 3
      88             : 
      89             : #define PYARG_STR_UNI "es"
      90             : 
      91    33293035 : static PyObject *PyLdbBytes_FromStringAndSize(const char *msg, int size)
      92             : {
      93    33293035 :         PyObject* result = NULL;
      94    33293035 :         PyObject* args = NULL;
      95    33293035 :         args = Py_BuildValue("(y#)", msg, size);
      96    33293035 :         result = PyLdbBytesType.tp_new(&PyLdbBytesType, args, NULL);
      97    33293035 :         Py_DECREF(args);
      98    33293035 :         return result;
      99             : }
     100             : #else
     101             : #define PyLdbBytes_FromStringAndSize PyString_FromStringAndSize
     102             : 
     103             : #define PYARG_STR_UNI "et"
     104             : 
     105             : #endif
     106             : 
     107    12641586 : static PyObject *richcmp(int cmp_val, int op)
     108             : {
     109             :         int ret;
     110    12641586 :         switch (op) {
     111        4020 :                 case Py_LT: ret = cmp_val < 0;  break;
     112           0 :                 case Py_LE: ret = cmp_val <= 0; break;
     113    11541072 :                 case Py_EQ: ret = cmp_val == 0; break;
     114     1096494 :                 case Py_NE: ret = cmp_val != 0; break;
     115           0 :                 case Py_GT: ret = cmp_val > 0;  break;
     116           0 :                 case Py_GE: ret = cmp_val >= 0; break;
     117           0 :                 default:
     118           0 :                         Py_INCREF(Py_NotImplemented);
     119           0 :                         return Py_NotImplemented;
     120             :         }
     121    12641586 :         return PyBool_FromLong(ret);
     122             : }
     123             : 
     124             : 
     125       46557 : static PyObject *py_ldb_control_str(PyLdbControlObject *self)
     126             : {
     127       46557 :         if (self->data != NULL) {
     128       46557 :                 char* control = ldb_control_to_string(self->mem_ctx, self->data);
     129       46557 :                 if (control == NULL) {
     130           0 :                         PyErr_NoMemory();
     131           0 :                         return NULL;
     132             :                 }
     133       46557 :                 return PyUnicode_FromString(control);
     134             :         } else {
     135           0 :                 return PyUnicode_FromString("ldb control");
     136             :         }
     137             : }
     138             : 
     139      102898 : static void py_ldb_control_dealloc(PyLdbControlObject *self)
     140             : {
     141      102898 :         if (self->mem_ctx != NULL) {
     142      102898 :                 talloc_free(self->mem_ctx);
     143             :         }
     144      102898 :         self->data = NULL;
     145      102898 :         Py_TYPE(self)->tp_free(self);
     146      102898 : }
     147             : 
     148             : /* Create a text (rather than bytes) interface for a LDB result object */
     149          99 : static PyObject *wrap_text(const char *type, PyObject *wrapped)
     150             : {
     151             :         PyObject *mod, *cls, *constructor, *inst;
     152          99 :         mod = PyImport_ImportModule("_ldb_text");
     153          99 :         if (mod == NULL)
     154           0 :                 return NULL;
     155          99 :         cls = PyObject_GetAttrString(mod, type);
     156          99 :         Py_DECREF(mod);
     157          99 :         if (cls == NULL) {
     158           0 :                 Py_DECREF(mod);
     159           0 :                 return NULL;
     160             :         }
     161          99 :         constructor = PyObject_GetAttrString(cls, "_wrap");
     162          99 :         Py_DECREF(cls);
     163          99 :         if (constructor == NULL) {
     164           0 :                 return NULL;
     165             :         }
     166          99 :         inst = PyObject_CallFunction(constructor, discard_const_p(char, "O"), wrapped);
     167          99 :         Py_DECREF(constructor);
     168          99 :         return inst;
     169             : }
     170             : 
     171        1036 : static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self,
     172             :                 PyObject *Py_UNUSED(ignored))
     173             : {
     174        1036 :         return PyUnicode_FromString(self->data->oid);
     175             : }
     176             : 
     177           3 : static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self,
     178             :                 PyObject *Py_UNUSED(ignored))
     179             : {
     180           3 :         return PyBool_FromLong(self->data->critical);
     181             : }
     182             : 
     183          26 : static int py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure)
     184             : {
     185          26 :         if (value == NULL) {
     186           0 :                 PyErr_SetString(PyExc_AttributeError, "cannot delete critical flag");
     187           0 :                 return -1;
     188             :         }
     189          26 :         if (PyObject_IsTrue(value)) {
     190          26 :                 self->data->critical = true;
     191             :         } else {
     192           0 :                 self->data->critical = false;
     193             :         }
     194          26 :         return 0;
     195             : }
     196             : 
     197          10 : static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     198             : {
     199          10 :         char *data = NULL;
     200          10 :         const char * const kwnames[] = { "ldb", "data", NULL };
     201             :         struct ldb_control *parsed_controls;
     202             :         PyLdbControlObject *ret;
     203             :         PyObject *py_ldb;
     204             :         TALLOC_CTX *mem_ctx;
     205             :         struct ldb_context *ldb_ctx;
     206             : 
     207          10 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!s",
     208             :                                          discard_const_p(char *, kwnames),
     209             :                                          &PyLdb, &py_ldb, &data))
     210           4 :                 return NULL;
     211             : 
     212           6 :         mem_ctx = talloc_new(NULL);
     213           6 :         if (mem_ctx == NULL) {
     214           0 :                 PyErr_NoMemory();
     215           0 :                 return NULL;
     216             :         }
     217             : 
     218           6 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
     219           6 :         parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data);
     220             : 
     221           6 :         if (!parsed_controls) {
     222           3 :                 talloc_free(mem_ctx);
     223           3 :                 PyErr_SetString(PyExc_ValueError, "unable to parse control string");
     224           3 :                 return NULL;
     225             :         }
     226             : 
     227           3 :         ret = PyObject_New(PyLdbControlObject, type);
     228           3 :         if (ret == NULL) {
     229           0 :                 PyErr_NoMemory();
     230           0 :                 talloc_free(mem_ctx);
     231           0 :                 return NULL;
     232             :         }
     233             : 
     234           3 :         ret->mem_ctx = mem_ctx;
     235             : 
     236           3 :         ret->data = talloc_move(mem_ctx, &parsed_controls);
     237           3 :         if (ret->data == NULL) {
     238           0 :                 Py_DECREF(ret);
     239           0 :                 PyErr_NoMemory();
     240           0 :                 talloc_free(mem_ctx);
     241           0 :                 return NULL;
     242             :         }
     243             : 
     244           3 :         return (PyObject *)ret;
     245             : }
     246             : 
     247             : static PyGetSetDef py_ldb_control_getset[] = {
     248             :         {
     249             :                 .name = discard_const_p(char, "oid"),
     250             :                 .get  = (getter)py_ldb_control_get_oid,
     251             :         },
     252             :         {
     253             :                 .name = discard_const_p(char, "critical"),
     254             :                 .get  = (getter)py_ldb_control_get_critical,
     255             :                 .set  = (setter)py_ldb_control_set_critical,
     256             :         },
     257             :         { .name = NULL },
     258             : };
     259             : 
     260             : static PyTypeObject PyLdbControl = {
     261             :         .tp_name = "ldb.control",
     262             :         .tp_dealloc = (destructor)py_ldb_control_dealloc,
     263             :         .tp_getattro = PyObject_GenericGetAttr,
     264             :         .tp_basicsize = sizeof(PyLdbControlObject),
     265             :         .tp_getset = py_ldb_control_getset,
     266             :         .tp_doc = "LDB control.",
     267             :         .tp_str = (reprfunc)py_ldb_control_str,
     268             :         .tp_new = py_ldb_control_new,
     269             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     270             : };
     271             : 
     272      120869 : static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
     273             : {
     274      120869 :         if (ret == LDB_ERR_PYTHON_EXCEPTION)
     275           0 :                 return; /* Python exception should already be set, just keep that */
     276             : 
     277      139702 :         PyErr_SetObject(error, 
     278             :                         Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
     279       18833 :                                       ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
     280             : }
     281     2742696 : static PyObject *py_ldb_bytes_str(PyBytesObject *self)
     282             : {
     283     2742696 :         char *msg = NULL;
     284             :         Py_ssize_t size;
     285     2742696 :         int result = 0;
     286     2742696 :         if (!PyBytes_Check(self)) {
     287           0 :                 PyErr_Format(PyExc_TypeError,"Unexpected type");
     288           0 :                 return NULL;
     289             :         }
     290     2742696 :         result = PyBytes_AsStringAndSize((PyObject *)self, &msg, &size);
     291     2742696 :         if (result != 0) {
     292           0 :                 PyErr_Format(PyExc_TypeError, "Failed to extract bytes");
     293           0 :                 return NULL;
     294             :         }
     295     2742696 :         return PyUnicode_FromStringAndSize(msg, size);
     296             : }
     297             : 
     298             : static PyTypeObject PyLdbBytesType = {
     299             :         PyVarObject_HEAD_INIT(NULL, 0)
     300             :         .tp_name = "ldb.bytes",
     301             :         .tp_doc = "str/bytes (with custom str)",
     302             :         .tp_str = (reprfunc)py_ldb_bytes_str,
     303             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
     304             : };
     305             : 
     306    21104116 : static PyObject *PyObject_FromLdbValue(const struct ldb_val *val)
     307             : {
     308    21104116 :         return PyLdbBytes_FromStringAndSize((const char *)val->data, val->length);
     309             : }
     310             : 
     311      299348 : static PyObject *PyStr_FromLdbValue(const struct ldb_val *val)
     312             : {
     313      299348 :         return PyUnicode_FromStringAndSize((const char *)val->data, val->length);
     314             : }
     315             : 
     316             : /**
     317             :  * Create a Python object from a ldb_result.
     318             :  *
     319             :  * @param result LDB result to convert
     320             :  * @return Python object with converted result (a list object)
     321             :  */
     322      102895 : static PyObject *PyLdbControl_FromControl(struct ldb_control *control)
     323             : {
     324      102895 :         TALLOC_CTX *ctl_ctx = talloc_new(NULL);
     325             :         PyLdbControlObject *ctrl;
     326      102895 :         if (ctl_ctx == NULL) {
     327           0 :                 PyErr_NoMemory();
     328           0 :                 return NULL;
     329             :         }
     330             : 
     331      102895 :         ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0);
     332      102895 :         if (ctrl == NULL) {
     333           0 :                 talloc_free(ctl_ctx);
     334           0 :                 PyErr_NoMemory();
     335           0 :                 return NULL;
     336             :         }
     337      102895 :         ctrl->mem_ctx = ctl_ctx;
     338      102895 :         ctrl->data = talloc_steal(ctrl->mem_ctx, control);
     339      102895 :         if (ctrl->data == NULL) {
     340           0 :                 Py_DECREF(ctrl);
     341           0 :                 PyErr_NoMemory();
     342           0 :                 return NULL;
     343             :         }
     344      102895 :         return (PyObject*) ctrl;
     345             : }
     346             : 
     347             : /**
     348             :  * Create a Python object from a ldb_result.
     349             :  *
     350             :  * @param result LDB result to convert
     351             :  * @return Python object with converted result (a list object)
     352             :  */
     353     2053868 : static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
     354             : {
     355             :         PyLdbResultObject *ret;
     356             :         PyObject *list, *controls, *referals;
     357             :         Py_ssize_t i;
     358             : 
     359     2053868 :         if (result == NULL) {
     360           2 :                 Py_RETURN_NONE;
     361             :         }
     362             : 
     363     2053866 :         ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0);
     364     2053866 :         if (ret == NULL) {
     365           0 :                 PyErr_NoMemory();
     366           0 :                 return NULL;
     367             :         }
     368             : 
     369     2053866 :         list = PyList_New(result->count);
     370     2053866 :         if (list == NULL) {
     371           0 :                 PyErr_NoMemory();
     372           0 :                 Py_DECREF(ret);
     373           0 :                 return NULL;
     374             :         }
     375             : 
     376     5526890 :         for (i = 0; i < result->count; i++) {
     377     3473024 :                 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i]));
     378             :         }
     379             : 
     380     2053866 :         ret->mem_ctx = talloc_new(NULL);
     381     2053866 :         if (ret->mem_ctx == NULL) {
     382           0 :                 Py_DECREF(list);
     383           0 :                 Py_DECREF(ret);
     384           0 :                 PyErr_NoMemory();
     385           0 :                 return NULL;
     386             :         }
     387             : 
     388     2053866 :         ret->msgs = list;
     389             : 
     390     2053866 :         if (result->controls) {
     391      102893 :                 i = 0;
     392      300319 :                 while (result->controls[i]) {
     393      102895 :                         i++;
     394             :                 }
     395      102893 :                 controls = PyList_New(i);
     396      102893 :                 if (controls == NULL) {
     397           0 :                         Py_DECREF(ret);
     398           0 :                         PyErr_NoMemory();
     399           0 :                         return NULL;
     400             :                 }
     401      205788 :                 for (i=0; result->controls[i]; i++) {
     402      102895 :                         PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]);
     403      102895 :                         if (ctrl == NULL) {
     404           0 :                                 Py_DECREF(ret);
     405           0 :                                 Py_DECREF(controls);
     406           0 :                                 PyErr_NoMemory();
     407           0 :                                 return NULL;
     408             :                         }
     409      102895 :                         PyList_SetItem(controls, i, ctrl);
     410             :                 }
     411             :         } else {
     412             :                 /*
     413             :                  * No controls so we keep an empty list
     414             :                  */
     415     1950973 :                 controls = PyList_New(0);
     416     1950973 :                 if (controls == NULL) {
     417           0 :                         Py_DECREF(ret);
     418           0 :                         PyErr_NoMemory();
     419           0 :                         return NULL;
     420             :                 }
     421             :         }
     422             : 
     423     2053866 :         ret->controls = controls;
     424             : 
     425     2053866 :         i = 0;
     426             : 
     427     3984550 :         while (result->refs && result->refs[i]) {
     428       97724 :                 i++;
     429             :         }
     430             : 
     431     2053866 :         referals = PyList_New(i);
     432     2053866 :         if (referals == NULL) {
     433           0 :                 Py_DECREF(ret);
     434           0 :                 PyErr_NoMemory();
     435           0 :                 return NULL;
     436             :         }
     437             : 
     438     2151590 :         for (i = 0;result->refs && result->refs[i]; i++) {
     439       97724 :                 PyList_SetItem(referals, i, PyUnicode_FromString(result->refs[i]));
     440             :         }
     441     2053866 :         ret->referals = referals;
     442     2053866 :         return (PyObject *)ret;
     443             : }
     444             : 
     445             : /**
     446             :  * Create a LDB Result from a Python object.
     447             :  * If conversion fails, NULL will be returned and a Python exception set.
     448             :  *
     449             :  * Note: the result object only includes the messages at the moment; extended
     450             :  * result, controls and referrals are ignored.
     451             :  *
     452             :  * @param mem_ctx Memory context in which to allocate the LDB Result
     453             :  * @param obj Python object to convert
     454             :  * @return a ldb_result, or NULL if the conversion failed
     455             :  */
     456           2 : static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, 
     457             :                                                PyObject *obj)
     458             : {
     459             :         struct ldb_result *res;
     460             :         Py_ssize_t i;
     461             : 
     462           2 :         if (obj == Py_None)
     463           2 :                 return NULL;
     464             : 
     465           0 :         res = talloc_zero(mem_ctx, struct ldb_result);
     466           0 :         res->count = PyList_Size(obj);
     467           0 :         res->msgs = talloc_array(res, struct ldb_message *, res->count);
     468           0 :         for (i = 0; i < res->count; i++) {
     469           0 :                 PyObject *item = PyList_GetItem(obj, i);
     470           0 :                 res->msgs[i] = pyldb_Message_AsMessage(item);
     471             :         }
     472           0 :         return res;
     473             : }
     474             : 
     475           2 : static PyObject *py_ldb_dn_validate(PyLdbDnObject *self,
     476             :                 PyObject *Py_UNUSED(ignored))
     477             : {
     478           2 :         return PyBool_FromLong(ldb_dn_validate(self->dn));
     479             : }
     480             : 
     481           4 : static PyObject *py_ldb_dn_is_valid(PyLdbDnObject *self,
     482             :                 PyObject *Py_UNUSED(ignored))
     483             : {
     484           4 :         return PyBool_FromLong(ldb_dn_is_valid(self->dn));
     485             : }
     486             : 
     487           4 : static PyObject *py_ldb_dn_is_special(PyLdbDnObject *self,
     488             :                 PyObject *Py_UNUSED(ignored))
     489             : {
     490           4 :         return PyBool_FromLong(ldb_dn_is_special(self->dn));
     491             : }
     492             : 
     493           4 : static PyObject *py_ldb_dn_is_null(PyLdbDnObject *self,
     494             :                 PyObject *Py_UNUSED(ignored))
     495             : {
     496           4 :         return PyBool_FromLong(ldb_dn_is_null(self->dn));
     497             : }
     498             :  
     499        1938 : static PyObject *py_ldb_dn_get_casefold(PyLdbDnObject *self,
     500             :                 PyObject *Py_UNUSED(ignored))
     501             : {
     502        1938 :         return PyUnicode_FromString(ldb_dn_get_casefold(self->dn));
     503             : }
     504             : 
     505     5100723 : static PyObject *py_ldb_dn_get_linearized(PyLdbDnObject *self)
     506             : {
     507     5100723 :         return PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
     508             : }
     509             : 
     510       14814 : static PyObject *py_ldb_dn_canonical_str(PyLdbDnObject *self,
     511             :                 PyObject *Py_UNUSED(ignored))
     512             : {
     513       14814 :         return PyUnicode_FromString(ldb_dn_canonical_string(self->dn, self->dn));
     514             : }
     515             : 
     516         132 : static PyObject *py_ldb_dn_canonical_ex_str(PyLdbDnObject *self,
     517             :                 PyObject *Py_UNUSED(ignored))
     518             : {
     519         132 :         return PyUnicode_FromString(ldb_dn_canonical_ex_string(self->dn, self->dn));
     520             : }
     521             : 
     522      182369 : static PyObject *py_ldb_dn_extended_str(PyLdbDnObject *self, PyObject *args, PyObject *kwargs)
     523             : {
     524      182369 :         const char * const kwnames[] = { "mode", NULL };
     525      182369 :         int mode = 1;
     526      182369 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i",
     527             :                                          discard_const_p(char *, kwnames),
     528             :                                          &mode))
     529           0 :                 return NULL;
     530      182369 :         return PyUnicode_FromString(ldb_dn_get_extended_linearized(self->dn, self->dn, mode));
     531             : }
     532             : 
     533     2225867 : static PyObject *py_ldb_dn_get_extended_component(PyLdbDnObject *self, PyObject *args)
     534             : {
     535             :         char *name;
     536             :         const struct ldb_val *val;
     537             : 
     538     2225867 :         if (!PyArg_ParseTuple(args, "s", &name))
     539           0 :                 return NULL;
     540     2225867 :         val = ldb_dn_get_extended_component(self->dn, name);
     541     2225867 :         if (val == NULL) {
     542     1058655 :                 Py_RETURN_NONE;
     543             :         }
     544             : 
     545     1167212 :         return PyBytes_FromStringAndSize((const char *)val->data, val->length);
     546             : }
     547             : 
     548          17 : static PyObject *py_ldb_dn_set_extended_component(PyLdbDnObject *self, PyObject *args)
     549             : {
     550             :         char *name;
     551             :         int err;
     552          17 :         uint8_t *value = NULL;
     553          17 :         Py_ssize_t size = 0;
     554             : 
     555          17 :         if (!PyArg_ParseTuple(args, "sz#", &name, (char **)&value, &size))
     556           0 :                 return NULL;
     557             : 
     558          17 :         if (value == NULL) {
     559           0 :                 err = ldb_dn_set_extended_component(self->dn, name, NULL);
     560             :         } else {
     561             :                 struct ldb_val val;
     562          17 :                 val.data = (uint8_t *)value;
     563          17 :                 val.length = size;
     564          17 :                 err = ldb_dn_set_extended_component(self->dn, name, &val);
     565             :         }
     566             : 
     567          17 :         if (err != LDB_SUCCESS) {
     568           0 :                 PyErr_SetString(PyExc_TypeError, "Failed to set extended component");
     569           0 :                 return NULL;
     570             :         }
     571             : 
     572          17 :         Py_RETURN_NONE;
     573             : }
     574             : 
     575       64671 : static PyObject *py_ldb_dn_repr(PyLdbDnObject *self)
     576             : {
     577       64671 :         PyObject *str = PyUnicode_FromString(ldb_dn_get_linearized(self->dn));
     578             :         PyObject *repr, *result;
     579       64671 :         if (str == NULL)
     580           0 :                 return NULL;
     581       64671 :         repr = PyObject_Repr(str);
     582       64671 :         if (repr == NULL) {
     583           0 :                 Py_DECREF(str);
     584           0 :                 return NULL;
     585             :         }
     586       64671 :         result = PyUnicode_FromFormat("Dn(%s)", PyUnicode_AsUTF8(repr));
     587       64671 :         Py_DECREF(str);
     588       64671 :         Py_DECREF(repr);
     589       64671 :         return result;
     590             : }
     591             : 
     592           4 : static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
     593             : {
     594             :         char *name;
     595             : 
     596           4 :         if (!PyArg_ParseTuple(args, "s", &name))
     597           0 :                 return NULL;
     598             : 
     599           4 :         return PyBool_FromLong(ldb_dn_check_special(self->dn, name));
     600             : }
     601             : 
     602    13881928 : static PyObject *py_ldb_dn_richcmp(PyObject *dn1, PyObject *dn2, int op)
     603             : {
     604             :         int ret;
     605    13881928 :         if (!pyldb_Dn_Check(dn2)) {
     606     1241221 :                 Py_INCREF(Py_NotImplemented);
     607     1241221 :                 return Py_NotImplemented;
     608             :         }
     609    12640707 :         ret = ldb_dn_compare(pyldb_Dn_AS_DN(dn1), pyldb_Dn_AS_DN(dn2));
     610    12640707 :         return richcmp(ret, op);
     611             : }
     612             : 
     613     1412210 : static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self,
     614             :                 PyObject *Py_UNUSED(ignored))
     615             : {
     616     1412210 :         struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self);
     617             :         struct ldb_dn *parent;
     618             :         PyLdbDnObject *py_ret;
     619     1412210 :         TALLOC_CTX *mem_ctx = talloc_new(NULL);
     620             : 
     621     1412210 :         parent = ldb_dn_get_parent(mem_ctx, dn);
     622     1412210 :         if (parent == NULL) {
     623           2 :                 talloc_free(mem_ctx);
     624           2 :                 Py_RETURN_NONE;
     625             :         }
     626             : 
     627     1412208 :         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
     628     1412208 :         if (py_ret == NULL) {
     629           0 :                 PyErr_NoMemory();
     630           0 :                 talloc_free(mem_ctx);
     631           0 :                 return NULL;
     632             :         }
     633     1412208 :         py_ret->mem_ctx = mem_ctx;
     634     1412208 :         py_ret->dn = parent;
     635     1412208 :         return (PyObject *)py_ret;
     636             : }
     637             : 
     638        1843 : static PyObject *py_ldb_dn_add_child(PyLdbDnObject *self, PyObject *args)
     639             : {
     640             :         PyObject *py_other;
     641             :         struct ldb_dn *dn, *other;
     642        1843 :         if (!PyArg_ParseTuple(args, "O", &py_other))
     643           0 :                 return NULL;
     644             : 
     645        1843 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     646             : 
     647        1843 :         if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
     648           0 :                 return NULL;
     649             : 
     650        1843 :         return PyBool_FromLong(ldb_dn_add_child(dn, other));
     651             : }
     652             : 
     653        1597 : static PyObject *py_ldb_dn_add_base(PyLdbDnObject *self, PyObject *args)
     654             : {
     655             :         PyObject *py_other;
     656             :         struct ldb_dn *other, *dn;
     657        1597 :         if (!PyArg_ParseTuple(args, "O", &py_other))
     658           0 :                 return NULL;
     659             : 
     660        1597 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     661             : 
     662        1597 :         if (!pyldb_Object_AsDn(NULL, py_other, ldb_dn_get_ldb_context(dn), &other))
     663           0 :                 return NULL;
     664             : 
     665        1597 :         return PyBool_FromLong(ldb_dn_add_base(dn, other));
     666             : }
     667             : 
     668          91 : static PyObject *py_ldb_dn_remove_base_components(PyLdbDnObject *self, PyObject *args)
     669             : {
     670             :         struct ldb_dn *dn;
     671             :         int i;
     672          91 :         if (!PyArg_ParseTuple(args, "i", &i))
     673           0 :                 return NULL;
     674             : 
     675          91 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     676             : 
     677          91 :         return PyBool_FromLong(ldb_dn_remove_base_components(dn, i));
     678             : }
     679             : 
     680      577486 : static PyObject *py_ldb_dn_is_child_of(PyLdbDnObject *self, PyObject *args)
     681             : {
     682             :         PyObject *py_base;
     683             :         struct ldb_dn *dn, *base;
     684      577486 :         if (!PyArg_ParseTuple(args, "O", &py_base))
     685           0 :                 return NULL;
     686             : 
     687      577486 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     688             : 
     689      577486 :         if (!pyldb_Object_AsDn(NULL, py_base, ldb_dn_get_ldb_context(dn), &base))
     690           0 :                 return NULL;
     691             : 
     692      577486 :         return PyBool_FromLong(ldb_dn_compare_base(base, dn) == 0);
     693             : }
     694             : 
     695          12 : static PyObject *py_ldb_dn_get_component_name(PyLdbDnObject *self, PyObject *args)
     696             : {
     697             :         struct ldb_dn *dn;
     698             :         const char *name;
     699          12 :         unsigned int num = 0;
     700             : 
     701          12 :         if (!PyArg_ParseTuple(args, "I", &num))
     702           0 :                 return NULL;
     703             : 
     704          12 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     705             : 
     706          12 :         name = ldb_dn_get_component_name(dn, num);
     707          12 :         if (name == NULL) {
     708           8 :                 Py_RETURN_NONE;
     709             :         }
     710             : 
     711           4 :         return PyUnicode_FromString(name);
     712             : }
     713             : 
     714         282 : static PyObject *py_ldb_dn_get_component_value(PyLdbDnObject *self, PyObject *args)
     715             : {
     716             :         struct ldb_dn *dn;
     717             :         const struct ldb_val *val;
     718         282 :         unsigned int num = 0;
     719             : 
     720         282 :         if (!PyArg_ParseTuple(args, "I", &num))
     721           0 :                 return NULL;
     722             : 
     723         282 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     724             : 
     725         282 :         val = ldb_dn_get_component_val(dn, num);
     726         282 :         if (val == NULL) {
     727           0 :                 Py_RETURN_NONE;
     728             :         }
     729             : 
     730         282 :         return PyStr_FromLdbValue(val);
     731             : }
     732             : 
     733      298911 : static PyObject *py_ldb_dn_set_component(PyLdbDnObject *self, PyObject *args)
     734             : {
     735      298911 :         unsigned int num = 0;
     736      298911 :         char *name = NULL, *value = NULL;
     737      298911 :         struct ldb_val val = { 0 };
     738             :         int err;
     739      298911 :         Py_ssize_t size = 0;
     740             : 
     741      298911 :         if (!PyArg_ParseTuple(args, "Iss#", &num, &name, &value, &size))
     742           2 :                 return NULL;
     743             : 
     744      298909 :         val.data = (unsigned char*) value;
     745      298909 :         val.length = size;
     746             : 
     747      298909 :         err = ldb_dn_set_component(self->dn, num, name, val);
     748      298909 :         if (err != LDB_SUCCESS) {
     749           2 :                 PyErr_SetString(PyExc_TypeError, "Failed to set component");
     750           2 :                 return NULL;
     751             :         }
     752             : 
     753      298907 :         Py_RETURN_NONE;
     754             : }
     755             : 
     756     7852113 : static PyObject *py_ldb_dn_get_rdn_name(PyLdbDnObject *self,
     757             :                 PyObject *Py_UNUSED(ignored))
     758             : {
     759             :         struct ldb_dn *dn;
     760             :         const char *name;
     761             : 
     762     7852113 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     763             : 
     764     7852113 :         name = ldb_dn_get_rdn_name(dn);
     765     7852113 :         if (name == NULL) {
     766           0 :                 Py_RETURN_NONE;
     767             :         }
     768             : 
     769     7852113 :         return PyUnicode_FromString(name);
     770             : }
     771             : 
     772      299066 : static PyObject *py_ldb_dn_get_rdn_value(PyLdbDnObject *self,
     773             :                 PyObject *Py_UNUSED(ignored))
     774             : {
     775             :         struct ldb_dn *dn;
     776             :         const struct ldb_val *val;
     777             : 
     778      299066 :         dn = pyldb_Dn_AS_DN((PyObject *)self);
     779             : 
     780      299066 :         val = ldb_dn_get_rdn_val(dn);
     781      299066 :         if (val == NULL) {
     782           0 :                 Py_RETURN_NONE;
     783             :         }
     784             : 
     785      299066 :         return PyStr_FromLdbValue(val);
     786             : }
     787             : 
     788             : static PyMethodDef py_ldb_dn_methods[] = {
     789             :         { "validate", (PyCFunction)py_ldb_dn_validate, METH_NOARGS, 
     790             :                 "S.validate() -> bool\n"
     791             :                 "Validate DN is correct." },
     792             :         { "is_valid", (PyCFunction)py_ldb_dn_is_valid, METH_NOARGS,
     793             :                 "S.is_valid() -> bool\n" },
     794             :         { "is_special", (PyCFunction)py_ldb_dn_is_special, METH_NOARGS,
     795             :                 "S.is_special() -> bool\n"
     796             :                 "Check whether this is a special LDB DN." },
     797             :         { "is_null", (PyCFunction)py_ldb_dn_is_null, METH_NOARGS,
     798             :                 "Check whether this is a null DN." },
     799             :         { "get_casefold", (PyCFunction)py_ldb_dn_get_casefold, METH_NOARGS,
     800             :                 NULL },
     801             :         { "get_linearized", PY_DISCARD_FUNC_SIG(PyCFunction,
     802             :                                                 py_ldb_dn_get_linearized),
     803             :                 METH_NOARGS,
     804             :                 NULL },
     805             :         { "canonical_str", (PyCFunction)py_ldb_dn_canonical_str, METH_NOARGS,
     806             :                 "S.canonical_str() -> string\n"
     807             :                 "Canonical version of this DN (like a posix path)." },
     808             :         { "is_child_of", (PyCFunction)py_ldb_dn_is_child_of, METH_VARARGS,
     809             :                 "S.is_child_of(basedn) -> int\nReturns True if this DN is a child of basedn\n"},
     810             :         { "canonical_ex_str", (PyCFunction)py_ldb_dn_canonical_ex_str, METH_NOARGS,
     811             :                 "S.canonical_ex_str() -> string\n"
     812             :                 "Canonical version of this DN (like a posix path, with terminating newline)." },
     813             :         { "extended_str", PY_DISCARD_FUNC_SIG(PyCFunction,
     814             :                                               py_ldb_dn_extended_str),
     815             :                 METH_VARARGS | METH_KEYWORDS,
     816             :                 "S.extended_str(mode=1) -> string\n"
     817             :                 "Extended version of this DN" },
     818             :         { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS,
     819             :                 "S.parent() -> dn\n"
     820             :                 "Get the parent for this DN." },
     821             :         { "add_child", (PyCFunction)py_ldb_dn_add_child, METH_VARARGS, 
     822             :                 "S.add_child(dn) -> None\n"
     823             :                 "Add a child DN to this DN." },
     824             :         { "add_base", (PyCFunction)py_ldb_dn_add_base, METH_VARARGS,
     825             :                 "S.add_base(dn) -> None\n"
     826             :                 "Add a base DN to this DN." },
     827             :         { "remove_base_components", (PyCFunction)py_ldb_dn_remove_base_components, METH_VARARGS,
     828             :                 "S.remove_base_components(int) -> bool\n"
     829             :                 "Remove a number of DN components from the base of this DN." },
     830             :         { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS,
     831             :                 "S.check_special(name) -> bool\n\n"
     832             :                 "Check if name is a special DN name"},
     833             :         { "get_extended_component", (PyCFunction)py_ldb_dn_get_extended_component, METH_VARARGS,
     834             :                 "S.get_extended_component(name) -> string\n\n"
     835             :                 "returns a DN extended component as a binary string"},
     836             :         { "set_extended_component", (PyCFunction)py_ldb_dn_set_extended_component, METH_VARARGS,
     837             :                 "S.set_extended_component(name, value) -> None\n\n"
     838             :                 "set a DN extended component as a binary string"},
     839             :         { "get_component_name", (PyCFunction)py_ldb_dn_get_component_name, METH_VARARGS,
     840             :                 "S.get_component_name(num) -> string\n"
     841             :                 "get the attribute name of the specified component" },
     842             :         { "get_component_value", (PyCFunction)py_ldb_dn_get_component_value, METH_VARARGS,
     843             :                 "S.get_component_value(num) -> string\n"
     844             :                 "get the attribute value of the specified component as a binary string" },
     845             :         { "set_component", (PyCFunction)py_ldb_dn_set_component, METH_VARARGS,
     846             :                 "S.set_component(num, name, value) -> None\n"
     847             :                 "set the attribute name and value of the specified component" },
     848             :         { "get_rdn_name", (PyCFunction)py_ldb_dn_get_rdn_name, METH_NOARGS,
     849             :                 "S.get_rdn_name() -> string\n"
     850             :                 "get the RDN attribute name" },
     851             :         { "get_rdn_value", (PyCFunction)py_ldb_dn_get_rdn_value, METH_NOARGS,
     852             :                 "S.get_rdn_value() -> string\n"
     853             :                 "get the RDN attribute value as a binary string" },
     854             :         {0}
     855             : };
     856             : 
     857          99 : static Py_ssize_t py_ldb_dn_len(PyLdbDnObject *self)
     858             : {
     859          99 :         return ldb_dn_get_comp_num(pyldb_Dn_AS_DN((PyObject *)self));
     860             : }
     861             : 
     862             : /*
     863             :   copy a DN as a python object
     864             :  */
     865      928618 : static PyObject *py_ldb_dn_copy(struct ldb_dn *dn)
     866             : {
     867             :         PyLdbDnObject *py_ret;
     868             : 
     869      928618 :         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
     870      928618 :         if (py_ret == NULL) {
     871           0 :                 PyErr_NoMemory();
     872           0 :                 return NULL;
     873             :         }
     874      928618 :         py_ret->mem_ctx = talloc_new(NULL);
     875      928618 :         py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
     876      928618 :         return (PyObject *)py_ret;
     877             : }
     878             : 
     879          79 : static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
     880             : {
     881          79 :         struct ldb_dn *dn = pyldb_Dn_AS_DN((PyObject *)self),
     882             :                                   *other;
     883             :         PyLdbDnObject *py_ret;
     884             : 
     885          79 :         if (!pyldb_Object_AsDn(NULL, py_other, NULL, &other))
     886           0 :                 return NULL;
     887             : 
     888          79 :         py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
     889          79 :         if (py_ret == NULL) {
     890           0 :                 PyErr_NoMemory();
     891           0 :                 return NULL;
     892             :         }
     893          79 :         py_ret->mem_ctx = talloc_new(NULL);
     894          79 :         py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
     895          79 :         ldb_dn_add_base(py_ret->dn, other);
     896          79 :         return (PyObject *)py_ret;
     897             : }
     898             : 
     899             : static PySequenceMethods py_ldb_dn_seq = {
     900             :         .sq_length = (lenfunc)py_ldb_dn_len,
     901             :         .sq_concat = (binaryfunc)py_ldb_dn_concat,
     902             : };
     903             : 
     904      825822 : static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
     905             : {
     906      825822 :         struct ldb_dn *ret = NULL;
     907      825822 :         char *str = NULL;
     908      825822 :         PyObject *py_ldb = NULL;
     909      825822 :         struct ldb_context *ldb_ctx = NULL;
     910      825822 :         TALLOC_CTX *mem_ctx = NULL;
     911      825822 :         PyLdbDnObject *py_ret = NULL;
     912      825822 :         const char * const kwnames[] = { "ldb", "dn", NULL };
     913             : 
     914      825822 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O"PYARG_STR_UNI,
     915             :                                          discard_const_p(char *, kwnames),
     916             :                                          &py_ldb, "utf8", &str))
     917           3 :                 goto out;
     918             : 
     919      825819 :         if (!PyLdb_Check(py_ldb)) {
     920           0 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
     921           0 :                 goto out;
     922             :         }
     923      825819 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
     924             : 
     925      825819 :         mem_ctx = talloc_new(NULL);
     926      825819 :         if (mem_ctx == NULL) {
     927           0 :                 PyErr_NoMemory();
     928           0 :                 goto out;
     929             :         }
     930             : 
     931      825819 :         ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
     932      825819 :         if (!ldb_dn_validate(ret)) {
     933        5864 :                 talloc_free(mem_ctx);
     934        5864 :                 PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
     935        5864 :                 goto out;
     936             :         }
     937             : 
     938      819955 :         py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
     939      819955 :         if (py_ret == NULL) {
     940           0 :                 talloc_free(mem_ctx);
     941           0 :                 PyErr_NoMemory();
     942           0 :                 goto out;
     943             :         }
     944      819955 :         py_ret->mem_ctx = mem_ctx;
     945      819955 :         py_ret->dn = ret;
     946      825822 : out:
     947      825822 :         if (str != NULL) {
     948      825819 :                 PyMem_Free(discard_const_p(char, str));
     949             :         }
     950      825822 :         return (PyObject *)py_ret;
     951             : }
     952             : 
     953    17383501 : static void py_ldb_dn_dealloc(PyLdbDnObject *self)
     954             : {
     955    17383501 :         talloc_free(self->mem_ctx);
     956    17383501 :         PyObject_Del(self);
     957    17383501 : }
     958             : 
     959             : static PyTypeObject PyLdbDn = {
     960             :         .tp_name = "ldb.Dn",
     961             :         .tp_methods = py_ldb_dn_methods,
     962             :         .tp_str = (reprfunc)py_ldb_dn_get_linearized,
     963             :         .tp_repr = (reprfunc)py_ldb_dn_repr,
     964             :         .tp_richcompare = (richcmpfunc)py_ldb_dn_richcmp,
     965             :         .tp_as_sequence = &py_ldb_dn_seq,
     966             :         .tp_doc = "A LDB distinguished name.",
     967             :         .tp_new = py_ldb_dn_new,
     968             :         .tp_dealloc = (destructor)py_ldb_dn_dealloc,
     969             :         .tp_basicsize = sizeof(PyLdbDnObject),
     970             :         .tp_flags = Py_TPFLAGS_DEFAULT,
     971             : };
     972             : 
     973             : /* Debug */
     974             : static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3, 0);
     975           0 : static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *fmt, va_list ap)
     976             : {
     977           0 :         PyObject *fn = (PyObject *)context;
     978           0 :         PyObject_CallFunction(fn, discard_const_p(char, "(i,O)"), level, PyUnicode_FromFormatV(fmt, ap));
     979           0 : }
     980             : 
     981             : static PyObject *py_ldb_debug_func;
     982             : 
     983           3 : static PyObject *py_ldb_set_debug(PyObject *self, PyObject *args)
     984             : {
     985             :         PyObject *cb;
     986             :         struct ldb_context *ldb_ctx;
     987             : 
     988           3 :         if (!PyArg_ParseTuple(args, "O", &cb))
     989           0 :                 return NULL;
     990             : 
     991           3 :         if (py_ldb_debug_func != NULL) {
     992           1 :                 Py_DECREF(py_ldb_debug_func);
     993             :         }
     994             : 
     995           3 :         Py_INCREF(cb);
     996             :         /* FIXME: DECREF cb when exiting program */
     997           3 :         py_ldb_debug_func = cb;
     998           3 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
     999           3 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError,
    1000             :                 ldb_set_debug(ldb_ctx, py_ldb_debug, cb),
    1001             :                 ldb_ctx);
    1002             : 
    1003           3 :         Py_RETURN_NONE;
    1004             : }
    1005             : 
    1006       23804 : static PyObject *py_ldb_set_create_perms(PyTypeObject *self, PyObject *args)
    1007             : {
    1008             :         unsigned int perms;
    1009       23804 :         if (!PyArg_ParseTuple(args, "I", &perms))
    1010           0 :                 return NULL;
    1011             : 
    1012       23804 :         ldb_set_create_perms(pyldb_Ldb_AS_LDBCONTEXT(self), perms);
    1013             : 
    1014       23804 :         Py_RETURN_NONE;
    1015             : }
    1016             : 
    1017       23801 : static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
    1018             : {
    1019             :         char *modules_dir;
    1020       23801 :         if (!PyArg_ParseTuple(args, "s", &modules_dir))
    1021           0 :                 return NULL;
    1022             : 
    1023       23801 :         ldb_set_modules_dir(pyldb_Ldb_AS_LDBCONTEXT(self), modules_dir);
    1024             : 
    1025       23801 :         Py_RETURN_NONE;
    1026             : }
    1027             : 
    1028       24631 : static PyObject *py_ldb_transaction_start(PyLdbObject *self,
    1029             :                 PyObject *Py_UNUSED(ignored))
    1030             : {
    1031       24631 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1032             :         int ldb_err;
    1033       24631 :         ldb_err = ldb_transaction_start(ldb_ctx);
    1034       24631 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
    1035       24631 :         Py_RETURN_NONE;
    1036             : }
    1037             : 
    1038       24483 : static PyObject *py_ldb_transaction_commit(PyLdbObject *self,
    1039             :                 PyObject *Py_UNUSED(ignored))
    1040             : {
    1041       24483 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1042             :         int ldb_err;
    1043       24483 :         ldb_err = ldb_transaction_commit(ldb_ctx);
    1044       24483 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
    1045       24475 :         Py_RETURN_NONE;
    1046             : }
    1047             : 
    1048         108 : static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self,
    1049             :                 PyObject *Py_UNUSED(ignored))
    1050             : {
    1051         108 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1052             :         int ldb_err;
    1053         108 :         ldb_err = ldb_transaction_prepare_commit(ldb_ctx);
    1054         108 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
    1055         108 :         Py_RETURN_NONE;
    1056             : }
    1057             : 
    1058         145 : static PyObject *py_ldb_transaction_cancel(PyLdbObject *self,
    1059             :                 PyObject *Py_UNUSED(ignored))
    1060             : {
    1061         145 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1062             :         int ldb_err;
    1063         145 :         ldb_err = ldb_transaction_cancel(ldb_ctx);
    1064         145 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
    1065         145 :         Py_RETURN_NONE;
    1066             : }
    1067             : 
    1068           0 : static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self,
    1069             :                 PyObject *Py_UNUSED(ignored))
    1070             : {
    1071           0 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1072             :         int ldb_err;
    1073           0 :         ldb_err = ldb_setup_wellknown_attributes(ldb_ctx);
    1074           0 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_err, ldb_ctx);
    1075           0 :         Py_RETURN_NONE;
    1076             : }
    1077             : 
    1078           3 : static PyObject *py_ldb_repr(PyLdbObject *self)
    1079             : {
    1080           3 :         return PyUnicode_FromString("<ldb connection>");
    1081             : }
    1082             : 
    1083      801657 : static PyObject *py_ldb_get_root_basedn(PyLdbObject *self,
    1084             :                 PyObject *Py_UNUSED(ignored))
    1085             : {
    1086      801657 :         struct ldb_dn *dn = ldb_get_root_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
    1087      801657 :         if (dn == NULL)
    1088           3 :                 Py_RETURN_NONE;
    1089      801654 :         return py_ldb_dn_copy(dn);
    1090             : }
    1091             : 
    1092             : 
    1093       16684 : static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self,
    1094             :                 PyObject *Py_UNUSED(ignored))
    1095             : {
    1096       16684 :         struct ldb_dn *dn = ldb_get_schema_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
    1097       16684 :         if (dn == NULL)
    1098           3 :                 Py_RETURN_NONE;
    1099       16681 :         return py_ldb_dn_copy(dn);
    1100             : }
    1101             : 
    1102       32051 : static PyObject *py_ldb_get_config_basedn(PyLdbObject *self,
    1103             :                 PyObject *Py_UNUSED(ignored))
    1104             : {
    1105       32051 :         struct ldb_dn *dn = ldb_get_config_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
    1106       32051 :         if (dn == NULL)
    1107           3 :                 Py_RETURN_NONE;
    1108       32048 :         return py_ldb_dn_copy(dn);
    1109             : }
    1110             : 
    1111       78240 : static PyObject *py_ldb_get_default_basedn(PyLdbObject *self,
    1112             :                 PyObject *Py_UNUSED(ignored))
    1113             : {
    1114       78240 :         struct ldb_dn *dn = ldb_get_default_basedn(pyldb_Ldb_AS_LDBCONTEXT(self));
    1115       78240 :         if (dn == NULL)
    1116           5 :                 Py_RETURN_NONE;
    1117       78235 :         return py_ldb_dn_copy(dn);
    1118             : }
    1119             : 
    1120     3664424 : static const char **PyList_AsStrList(TALLOC_CTX *mem_ctx, PyObject *list,
    1121             :                     const char *paramname)
    1122             : {
    1123             :         const char **ret;
    1124             :         Py_ssize_t i;
    1125     3664424 :         if (!PyList_Check(list)) {
    1126          20 :                 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
    1127          20 :                 return NULL;
    1128             :         }
    1129     3664404 :         ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
    1130     3664404 :         if (ret == NULL) {
    1131           0 :                 PyErr_NoMemory();
    1132           0 :                 return NULL;
    1133             :         }
    1134             : 
    1135    28079592 :         for (i = 0; i < PyList_Size(list); i++) {
    1136    11234869 :                 const char *str = NULL;
    1137             :                 Py_ssize_t size;
    1138    11234869 :                 PyObject *item = PyList_GetItem(list, i);
    1139    11234869 :                 if (!PyUnicode_Check(item)) {
    1140           0 :                         PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
    1141           0 :                         talloc_free(ret);
    1142           0 :                         return NULL;
    1143             :                 }
    1144    11234869 :                 str = PyUnicode_AsUTF8AndSize(item, &size);
    1145    11234869 :                 if (str == NULL) {
    1146           0 :                         talloc_free(ret);
    1147           0 :                         return NULL;
    1148             :                 }
    1149    11234869 :                 ret[i] = talloc_strndup(ret, str, size);
    1150             :         }
    1151     3664404 :         ret[i] = NULL;
    1152     3664404 :         return ret;
    1153             : }
    1154             : 
    1155        3053 : static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1156             : {
    1157        3053 :         const char * const kwnames[] = { "url", "flags", "options", NULL };
    1158        3053 :         char *url = NULL;
    1159        3053 :         PyObject *py_options = Py_None;
    1160             :         const char **options;
    1161        3053 :         unsigned int flags = 0;
    1162             :         int ret;
    1163             :         struct ldb_context *ldb;
    1164             : 
    1165        3053 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|zIO:Ldb.__init__",
    1166             :                                          discard_const_p(char *, kwnames),
    1167             :                                          &url, &flags, &py_options))
    1168           0 :                 return -1;
    1169             : 
    1170        3053 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
    1171             : 
    1172        3053 :         if (py_options == Py_None) {
    1173         523 :                 options = NULL;
    1174             :         } else {
    1175        2530 :                 options = PyList_AsStrList(ldb, py_options, "options");
    1176        2530 :                 if (options == NULL)
    1177           0 :                         return -1;
    1178             :         }
    1179             : 
    1180        3053 :         if (url != NULL) {
    1181        2905 :                 ret = ldb_connect(ldb, url, flags, options);
    1182        2905 :                 if (ret != LDB_SUCCESS) {
    1183           1 :                         PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
    1184           1 :                         return -1;
    1185             :                 }
    1186             :         } else {
    1187         148 :                 ldb_set_flags(ldb, flags);
    1188             :         }
    1189             : 
    1190        3052 :         talloc_free(options);
    1191        3052 :         return 0;
    1192             : }
    1193             : 
    1194       26854 : static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    1195             : {
    1196             :         PyLdbObject *ret;
    1197             :         struct ldb_context *ldb;
    1198       26854 :         ret = (PyLdbObject *)type->tp_alloc(type, 0);
    1199       26854 :         if (ret == NULL) {
    1200           0 :                 PyErr_NoMemory();
    1201           0 :                 return NULL;
    1202             :         }
    1203       26854 :         ret->mem_ctx = talloc_new(NULL);
    1204       26854 :         ldb = ldb_init(ret->mem_ctx, NULL);
    1205             : 
    1206       26854 :         if (ldb == NULL) {
    1207           0 :                 PyErr_NoMemory();
    1208           0 :                 return NULL;
    1209             :         }
    1210             : 
    1211       26854 :         ret->ldb_ctx = ldb;
    1212       26854 :         return (PyObject *)ret;
    1213             : }
    1214             : 
    1215       23395 : static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1216             : {
    1217       23395 :         char *url = NULL;
    1218       23395 :         unsigned int flags = 0;
    1219       23395 :         PyObject *py_options = Py_None;
    1220             :         int ret;
    1221             :         const char **options;
    1222       23395 :         const char * const kwnames[] = { "url", "flags", "options", NULL };
    1223             :         struct ldb_context *ldb_ctx;
    1224             : 
    1225       23395 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "z|IO",
    1226             :                                          discard_const_p(char *, kwnames),
    1227             :                                          &url, &flags, &py_options))
    1228           0 :                 return NULL;
    1229             : 
    1230       23395 :         if (py_options == Py_None) {
    1231       21154 :                 options = NULL;
    1232             :         } else {
    1233        2241 :                 options = PyList_AsStrList(NULL, py_options, "options");
    1234        2241 :                 if (options == NULL)
    1235           0 :                         return NULL;
    1236             :         }
    1237             : 
    1238       23395 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1239       23395 :         ret = ldb_connect(ldb_ctx, url, flags, options);
    1240       23396 :         talloc_free(options);
    1241             : 
    1242       23396 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1243             : 
    1244       22968 :         Py_RETURN_NONE;
    1245             : }
    1246             : 
    1247      195025 : static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1248             : {
    1249             :         PyObject *py_msg;
    1250      195025 :         PyObject *py_controls = Py_None;
    1251             :         struct ldb_context *ldb_ctx;
    1252             :         struct ldb_request *req;
    1253             :         struct ldb_control **parsed_controls;
    1254             :         struct ldb_message *msg;
    1255             :         int ret;
    1256             :         TALLOC_CTX *mem_ctx;
    1257      195025 :         bool validate=true;
    1258      195025 :         const char * const kwnames[] = { "message", "controls", "validate", NULL };
    1259             : 
    1260      195025 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|Ob",
    1261             :                                          discard_const_p(char *, kwnames),
    1262             :                                          &py_msg, &py_controls, &validate))
    1263           0 :                 return NULL;
    1264             : 
    1265      195025 :         mem_ctx = talloc_new(NULL);
    1266      195025 :         if (mem_ctx == NULL) {
    1267           0 :                 PyErr_NoMemory();
    1268           0 :                 return NULL;
    1269             :         }
    1270      195025 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1271             : 
    1272      195025 :         if (py_controls == Py_None) {
    1273       49392 :                 parsed_controls = NULL;
    1274             :         } else {
    1275      145633 :                 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
    1276      145633 :                 if (controls == NULL) {
    1277           2 :                         talloc_free(mem_ctx);
    1278           2 :                         return NULL;
    1279             :                 }
    1280      145631 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    1281      145631 :                 talloc_free(controls);
    1282             :         }
    1283             : 
    1284      195023 :         if (!PyLdbMessage_Check(py_msg)) {
    1285           2 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message");
    1286           2 :                 talloc_free(mem_ctx);
    1287           2 :                 return NULL;
    1288             :         }
    1289      195021 :         msg = pyldb_Message_AsMessage(py_msg);
    1290             : 
    1291      195021 :         if (validate) {
    1292      194974 :                 ret = ldb_msg_sanity_check(ldb_ctx, msg);
    1293      194974 :                 if (ret != LDB_SUCCESS) {
    1294           1 :                         PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1295           1 :                         talloc_free(mem_ctx);
    1296           1 :                         return NULL;
    1297             :                 }
    1298             :         }
    1299             : 
    1300      195020 :         ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
    1301             :                                 NULL, ldb_op_default_callback, NULL);
    1302      195020 :         if (ret != LDB_SUCCESS) {
    1303           0 :                 PyErr_SetString(PyExc_TypeError, "failed to build request");
    1304           0 :                 talloc_free(mem_ctx);
    1305           0 :                 return NULL;
    1306             :         }
    1307             : 
    1308             :         /* do request and autostart a transaction */
    1309             :         /* Then let's LDB handle the message error in case of pb as they are meaningful */
    1310             : 
    1311      195020 :         ret = ldb_transaction_start(ldb_ctx);
    1312      195020 :         if (ret != LDB_SUCCESS) {
    1313           0 :                 talloc_free(mem_ctx);
    1314           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1315           0 :                 return NULL;
    1316             :         }
    1317             : 
    1318      195020 :         ret = ldb_request(ldb_ctx, req);
    1319      195020 :         if (ret == LDB_SUCCESS) {
    1320      194964 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1321             :         }
    1322             : 
    1323      195020 :         if (ret == LDB_SUCCESS) {
    1324      191236 :                 ret = ldb_transaction_commit(ldb_ctx);
    1325             :         } else {
    1326        3784 :                 ldb_transaction_cancel(ldb_ctx);
    1327             :         }
    1328             : 
    1329      195020 :         talloc_free(mem_ctx);
    1330      195020 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1331             : 
    1332      191236 :         Py_RETURN_NONE;
    1333             : }
    1334             : 
    1335             : 
    1336             : /**
    1337             :  * Obtain a ldb message from a Python Dictionary object.
    1338             :  *
    1339             :  * @param mem_ctx Memory context
    1340             :  * @param py_obj Python Dictionary object
    1341             :  * @param ldb_ctx LDB context
    1342             :  * @param mod_flags Flags to be set on every message element
    1343             :  * @return ldb_message on success or NULL on failure
    1344             :  */
    1345      141049 : static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx,
    1346             :                                             PyObject *py_obj,
    1347             :                                             struct ldb_context *ldb_ctx,
    1348             :                                             unsigned int mod_flags)
    1349             : {
    1350             :         struct ldb_message *msg;
    1351      141049 :         unsigned int msg_pos = 0;
    1352      141049 :         Py_ssize_t dict_pos = 0;
    1353             :         PyObject *key, *value;
    1354             :         struct ldb_message_element *msg_el;
    1355      141049 :         PyObject *dn_value = PyDict_GetItemString(py_obj, "dn");
    1356             : 
    1357      141049 :         msg = ldb_msg_new(mem_ctx);
    1358      141049 :         if (msg == NULL) {
    1359           0 :                 PyErr_NoMemory();
    1360           0 :                 return NULL;
    1361             :         }
    1362      141049 :         msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj));
    1363             : 
    1364      141049 :         if (dn_value) {
    1365      141045 :                 if (!pyldb_Object_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
    1366           0 :                         PyErr_SetString(PyExc_TypeError, "unable to import dn object");
    1367           0 :                         return NULL;
    1368             :                 }
    1369      141045 :                 if (msg->dn == NULL) {
    1370           0 :                         PyErr_SetString(PyExc_TypeError, "dn set but not found");
    1371           0 :                         return NULL;
    1372             :                 }
    1373             :         } else {
    1374           4 :                 PyErr_SetString(PyExc_TypeError, "no dn set");
    1375           4 :                 return NULL;
    1376             :         }
    1377             : 
    1378      871572 :         while (PyDict_Next(py_obj, &dict_pos, &key, &value)) {
    1379      589482 :                 const char *key_str = PyUnicode_AsUTF8(key);
    1380      589482 :                 if (ldb_attr_cmp(key_str, "dn") != 0) {
    1381      448437 :                         msg_el = PyObject_AsMessageElement(msg->elements, value,
    1382             :                                                            mod_flags, key_str);
    1383      448437 :                         if (msg_el == NULL) {
    1384           0 :                                 PyErr_Format(PyExc_TypeError, "unable to import element '%s'", key_str);
    1385           0 :                                 return NULL;
    1386             :                         }
    1387      448437 :                         memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el));
    1388      448437 :                         msg_pos++;
    1389             :                 }
    1390             :         }
    1391             : 
    1392      141045 :         msg->num_elements = msg_pos;
    1393             : 
    1394      141045 :         return msg;
    1395             : }
    1396             : 
    1397      420767 : static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1398             : {
    1399             :         PyObject *py_obj;
    1400             :         int ret;
    1401             :         struct ldb_context *ldb_ctx;
    1402             :         struct ldb_request *req;
    1403      420767 :         struct ldb_message *msg = NULL;
    1404      420767 :         PyObject *py_controls = Py_None;
    1405             :         TALLOC_CTX *mem_ctx;
    1406             :         struct ldb_control **parsed_controls;
    1407      420767 :         const char * const kwnames[] = { "message", "controls", NULL };
    1408             : 
    1409      420767 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
    1410             :                                          discard_const_p(char *, kwnames),
    1411             :                                          &py_obj, &py_controls))
    1412           2 :                 return NULL;
    1413             : 
    1414      420765 :         mem_ctx = talloc_new(NULL);
    1415      420765 :         if (mem_ctx == NULL) {
    1416           0 :                 PyErr_NoMemory();
    1417           0 :                 return NULL;
    1418             :         }
    1419      420765 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1420             : 
    1421      420765 :         if (py_controls == Py_None) {
    1422      260173 :                 parsed_controls = NULL;
    1423             :         } else {
    1424      160592 :                 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
    1425      160592 :                 if (controls == NULL) {
    1426           8 :                         talloc_free(mem_ctx);
    1427           8 :                         return NULL;
    1428             :                 }
    1429      160584 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    1430      160584 :                 talloc_free(controls);
    1431             :         }
    1432             : 
    1433      420757 :         if (PyLdbMessage_Check(py_obj)) {
    1434      281687 :                 msg = pyldb_Message_AsMessage(py_obj);
    1435      139070 :         } else if (PyDict_Check(py_obj)) {
    1436      139066 :                 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD);
    1437             :         } else {
    1438           4 :                 PyErr_SetString(PyExc_TypeError,
    1439             :                                 "Dictionary or LdbMessage object expected!");
    1440             :         }
    1441             : 
    1442      420757 :         if (!msg) {
    1443             :                 /* we should have a PyErr already set */
    1444           4 :                 talloc_free(mem_ctx);
    1445           4 :                 return NULL;
    1446             :         }
    1447             : 
    1448      420753 :         ret = ldb_msg_sanity_check(ldb_ctx, msg);
    1449      420753 :         if (ret != LDB_SUCCESS) {
    1450           1 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1451           1 :                 talloc_free(mem_ctx);
    1452           1 :                 return NULL;
    1453             :         }
    1454             : 
    1455      420752 :         ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls,
    1456             :                                 NULL, ldb_op_default_callback, NULL);
    1457      420752 :         if (ret != LDB_SUCCESS) {
    1458           0 :                 PyErr_SetString(PyExc_TypeError, "failed to build request");
    1459           0 :                 talloc_free(mem_ctx);
    1460           0 :                 return NULL;
    1461             :         }
    1462             : 
    1463             :         /* do request and autostart a transaction */
    1464             :         /* Then let's LDB handle the message error in case of pb as they are meaningful */
    1465             : 
    1466      420752 :         ret = ldb_transaction_start(ldb_ctx);
    1467      420752 :         if (ret != LDB_SUCCESS) {
    1468           0 :                 talloc_free(mem_ctx);
    1469           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1470           0 :                 return NULL;
    1471             :         }
    1472             : 
    1473      420752 :         ret = ldb_request(ldb_ctx, req);
    1474      420752 :         if (ret == LDB_SUCCESS) {
    1475      420734 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1476             :         }
    1477             : 
    1478      420752 :         if (ret == LDB_SUCCESS) {
    1479      419951 :                 ret = ldb_transaction_commit(ldb_ctx);
    1480             :         } else {
    1481         801 :                 ldb_transaction_cancel(ldb_ctx);
    1482             :         }
    1483             : 
    1484      420752 :         talloc_free(mem_ctx);
    1485      420752 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1486             : 
    1487      419951 :         Py_RETURN_NONE;
    1488             : }
    1489             : 
    1490       55562 : static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1491             : {
    1492             :         PyObject *py_dn;
    1493             :         struct ldb_dn *dn;
    1494             :         int ret;
    1495             :         struct ldb_context *ldb_ctx;
    1496             :         struct ldb_request *req;
    1497       55562 :         PyObject *py_controls = Py_None;
    1498             :         TALLOC_CTX *mem_ctx;
    1499             :         struct ldb_control **parsed_controls;
    1500       55562 :         const char * const kwnames[] = { "dn", "controls", NULL };
    1501             : 
    1502       55562 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O|O",
    1503             :                                          discard_const_p(char *, kwnames),
    1504             :                                          &py_dn, &py_controls))
    1505           0 :                 return NULL;
    1506             : 
    1507       55562 :         mem_ctx = talloc_new(NULL);
    1508       55562 :         if (mem_ctx == NULL) {
    1509           0 :                 PyErr_NoMemory();
    1510           0 :                 return NULL;
    1511             :         }
    1512       55562 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1513             : 
    1514       55562 :         if (py_controls == Py_None) {
    1515       49434 :                 parsed_controls = NULL;
    1516             :         } else {
    1517        6128 :                 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
    1518        6128 :                 if (controls == NULL) {
    1519           0 :                         talloc_free(mem_ctx);
    1520           0 :                         return NULL;
    1521             :                 }
    1522        6128 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    1523        6128 :                 talloc_free(controls);
    1524             :         }
    1525             : 
    1526       55562 :         if (!pyldb_Object_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) {
    1527           0 :                 talloc_free(mem_ctx);
    1528           0 :                 return NULL;
    1529             :         }
    1530             : 
    1531       55562 :         ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls,
    1532             :                                 NULL, ldb_op_default_callback, NULL);
    1533       55562 :         if (ret != LDB_SUCCESS) {
    1534           0 :                 PyErr_SetString(PyExc_TypeError, "failed to build request");
    1535           0 :                 talloc_free(mem_ctx);
    1536           0 :                 return NULL;
    1537             :         }
    1538             : 
    1539             :         /* do request and autostart a transaction */
    1540             :         /* Then let's LDB handle the message error in case of pb as they are meaningful */
    1541             : 
    1542       55562 :         ret = ldb_transaction_start(ldb_ctx);
    1543       55562 :         if (ret != LDB_SUCCESS) {
    1544           0 :                 talloc_free(mem_ctx);
    1545           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1546           0 :                 return NULL;
    1547             :         }
    1548             : 
    1549       55562 :         ret = ldb_request(ldb_ctx, req);
    1550       55562 :         if (ret == LDB_SUCCESS) {
    1551       55559 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1552             :         }
    1553             : 
    1554       55562 :         if (ret == LDB_SUCCESS) {
    1555       26586 :                 ret = ldb_transaction_commit(ldb_ctx);
    1556             :         } else {
    1557       28976 :                 ldb_transaction_cancel(ldb_ctx);
    1558             :         }
    1559             : 
    1560       55562 :         talloc_free(mem_ctx);
    1561       55562 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1562             : 
    1563       26586 :         Py_RETURN_NONE;
    1564             : }
    1565             : 
    1566         822 : static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1567             : {
    1568             :         PyObject *py_dn1, *py_dn2;
    1569             :         struct ldb_dn *dn1, *dn2;
    1570             :         int ret;
    1571             :         TALLOC_CTX *mem_ctx;
    1572         822 :         PyObject *py_controls = Py_None;
    1573             :         struct ldb_control **parsed_controls;
    1574             :         struct ldb_context *ldb_ctx;
    1575             :         struct ldb_request *req;
    1576         822 :         const char * const kwnames[] = { "dn1", "dn2", "controls", NULL };
    1577             : 
    1578         822 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1579             : 
    1580         822 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|O",
    1581             :                                          discard_const_p(char *, kwnames),
    1582             :                                          &py_dn1, &py_dn2, &py_controls))
    1583           0 :                 return NULL;
    1584             : 
    1585             : 
    1586         822 :         mem_ctx = talloc_new(NULL);
    1587         822 :         if (mem_ctx == NULL) {
    1588           0 :                 PyErr_NoMemory();
    1589           0 :                 return NULL;
    1590             :         }
    1591             : 
    1592         822 :         if (py_controls == Py_None) {
    1593         800 :                 parsed_controls = NULL;
    1594             :         } else {
    1595          22 :                 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
    1596          22 :                 if (controls == NULL) {
    1597           0 :                         talloc_free(mem_ctx);
    1598           0 :                         return NULL;
    1599             :                 }
    1600          22 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    1601          22 :                 talloc_free(controls);
    1602             :         }
    1603             : 
    1604             : 
    1605         822 :         if (!pyldb_Object_AsDn(mem_ctx, py_dn1, ldb_ctx, &dn1)) {
    1606           0 :                 talloc_free(mem_ctx);
    1607           0 :                 return NULL;
    1608             :         }
    1609             : 
    1610         822 :         if (!pyldb_Object_AsDn(mem_ctx, py_dn2, ldb_ctx, &dn2)) {
    1611           0 :                 talloc_free(mem_ctx);
    1612           0 :                 return NULL;
    1613             :         }
    1614             : 
    1615         822 :         ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls,
    1616             :                                 NULL, ldb_op_default_callback, NULL);
    1617         822 :         if (ret != LDB_SUCCESS) {
    1618           0 :                 PyErr_SetString(PyExc_TypeError, "failed to build request");
    1619           0 :                 talloc_free(mem_ctx);
    1620           0 :                 return NULL;
    1621             :         }
    1622             : 
    1623             :         /* do request and autostart a transaction */
    1624             :         /* Then let's LDB handle the message error in case of pb as they are meaningful */
    1625             : 
    1626         822 :         ret = ldb_transaction_start(ldb_ctx);
    1627         822 :         if (ret != LDB_SUCCESS) {
    1628           0 :                 talloc_free(mem_ctx);
    1629           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1630           0 :                 return NULL;
    1631             :         }
    1632             : 
    1633         822 :         ret = ldb_request(ldb_ctx, req);
    1634         822 :         if (ret == LDB_SUCCESS) {
    1635         787 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1636             :         }
    1637             : 
    1638         822 :         if (ret == LDB_SUCCESS) {
    1639         683 :                 ret = ldb_transaction_commit(ldb_ctx);
    1640             :         } else {
    1641         139 :                 ldb_transaction_cancel(ldb_ctx);
    1642             :         }
    1643             : 
    1644         822 :         talloc_free(mem_ctx);
    1645         822 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1646             : 
    1647         683 :         Py_RETURN_NONE;
    1648             : }
    1649             : 
    1650           0 : static PyObject *py_ldb_schema_attribute_remove(PyLdbObject *self, PyObject *args)
    1651             : {
    1652             :         char *name;
    1653           0 :         if (!PyArg_ParseTuple(args, "s", &name))
    1654           0 :                 return NULL;
    1655             : 
    1656           0 :         ldb_schema_attribute_remove(pyldb_Ldb_AS_LDBCONTEXT(self), name);
    1657             : 
    1658           0 :         Py_RETURN_NONE;
    1659             : }
    1660             : 
    1661        4212 : static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
    1662             : {
    1663             :         char *attribute, *syntax;
    1664             :         unsigned int flags;
    1665             :         int ret;
    1666             :         struct ldb_context *ldb_ctx;
    1667             : 
    1668        4212 :         if (!PyArg_ParseTuple(args, "sIs", &attribute, &flags, &syntax))
    1669           0 :                 return NULL;
    1670             : 
    1671        4212 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1672        4212 :         ret = ldb_schema_attribute_add(ldb_ctx, attribute, flags, syntax);
    1673             : 
    1674        4212 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
    1675             : 
    1676        4212 :         Py_RETURN_NONE;
    1677             : }
    1678             : 
    1679      306877 : static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
    1680             : {
    1681      306877 :         if (ldif == NULL) {
    1682           0 :                 Py_RETURN_NONE;
    1683             :         } else {
    1684             :         /* We don't want this attached to the 'ldb' any more */
    1685      306877 :                 PyObject *obj = PyLdbMessage_FromMessage(ldif->msg);
    1686      243463 :                 PyObject *result =
    1687       63414 :                         Py_BuildValue(discard_const_p(char, "(iO)"),
    1688      306877 :                                       ldif->changetype,
    1689             :                                       obj);
    1690      306877 :                 Py_CLEAR(obj);
    1691      306877 :                 return result;
    1692             :         }
    1693             : }
    1694             : 
    1695             : 
    1696        6127 : static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args)
    1697             : {
    1698             :         int changetype;
    1699             :         PyObject *py_msg;
    1700             :         struct ldb_ldif ldif;
    1701             :         PyObject *ret;
    1702             :         char *string;
    1703             :         TALLOC_CTX *mem_ctx;
    1704             : 
    1705        6127 :         if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
    1706           0 :                 return NULL;
    1707             : 
    1708        6127 :         if (!PyLdbMessage_Check(py_msg)) {
    1709           0 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
    1710           0 :                 return NULL;
    1711             :         }
    1712             : 
    1713        6127 :         ldif.msg = pyldb_Message_AsMessage(py_msg);
    1714        6127 :         ldif.changetype = changetype;
    1715             : 
    1716        6127 :         mem_ctx = talloc_new(NULL);
    1717             : 
    1718        6127 :         string = ldb_ldif_write_string(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &ldif);
    1719        6127 :         if (!string) {
    1720           0 :                 PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
    1721           0 :                 return NULL;
    1722             :         }
    1723             : 
    1724        6127 :         ret = PyUnicode_FromString(string);
    1725             : 
    1726        6127 :         talloc_free(mem_ctx);
    1727             : 
    1728        6127 :         return ret;
    1729             : }
    1730             : 
    1731       32887 : static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
    1732             : {
    1733             :         PyObject *list, *ret;
    1734             :         struct ldb_ldif *ldif;
    1735             :         const char *s;
    1736       32887 :         struct ldb_dn *last_dn = NULL;
    1737             : 
    1738             :         TALLOC_CTX *mem_ctx;
    1739             : 
    1740       32887 :         if (!PyArg_ParseTuple(args, "s", &s))
    1741           0 :                 return NULL;
    1742             : 
    1743       32887 :         mem_ctx = talloc_new(NULL);
    1744       32887 :         if (!mem_ctx) {
    1745           0 :                 Py_RETURN_NONE;
    1746             :         }
    1747             : 
    1748       32887 :         list = PyList_New(0);
    1749       96301 :         while (s && *s != '\0') {
    1750      306877 :                 ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
    1751      306877 :                 talloc_steal(mem_ctx, ldif);
    1752      306877 :                 if (ldif) {
    1753      306877 :                         int res = 0;
    1754      306877 :                         PyObject *py_ldif = ldb_ldif_to_pyobject(ldif);
    1755      306877 :                         if (py_ldif == NULL) {
    1756           0 :                                 Py_CLEAR(list);
    1757           0 :                                 PyErr_BadArgument();
    1758           0 :                                 talloc_free(mem_ctx);
    1759           0 :                                 return NULL;
    1760             :                         }
    1761      306877 :                         res = PyList_Append(list, py_ldif);
    1762      306877 :                         Py_CLEAR(py_ldif);
    1763      306877 :                         if (res == -1) {
    1764           0 :                                 Py_CLEAR(list);
    1765           0 :                                 talloc_free(mem_ctx);
    1766           0 :                                 return NULL;
    1767             :                         }
    1768      306877 :                         last_dn = ldif->msg->dn;
    1769             :                 } else {
    1770           0 :                         const char *last_dn_str = NULL;
    1771           0 :                         const char *err_string = NULL;
    1772           0 :                         if (last_dn == NULL) {
    1773           0 :                                 PyErr_SetString(PyExc_ValueError,
    1774             :                                                 "unable to parse LDIF "
    1775             :                                                 "string at first chunk");
    1776           0 :                                 Py_CLEAR(list);
    1777           0 :                                 talloc_free(mem_ctx);
    1778           0 :                                 return NULL;
    1779             :                         }
    1780             : 
    1781             :                         last_dn_str
    1782           0 :                                 = ldb_dn_get_linearized(last_dn);
    1783             : 
    1784             :                         err_string
    1785           0 :                                 = talloc_asprintf(mem_ctx,
    1786             :                                                   "unable to parse ldif "
    1787             :                                                   "string AFTER %s",
    1788             :                                                   last_dn_str);
    1789             : 
    1790           0 :                         PyErr_SetString(PyExc_ValueError,
    1791             :                                         err_string);
    1792           0 :                         talloc_free(mem_ctx);
    1793           0 :                         Py_CLEAR(list);
    1794           0 :                         return NULL;
    1795             :                 }
    1796             :         }
    1797       32887 :         talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
    1798       32887 :         ret = PyObject_GetIter(list);
    1799       32887 :         Py_DECREF(list);
    1800       32887 :         return ret;
    1801             : }
    1802             : 
    1803       10468 : static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
    1804             : {
    1805             :         int ldb_ret;
    1806             :         PyObject *py_msg_old;
    1807             :         PyObject *py_msg_new;
    1808             :         struct ldb_message *diff;
    1809             :         struct ldb_context *ldb;
    1810             :         PyObject *py_ret;
    1811       10468 :         TALLOC_CTX *mem_ctx = NULL;
    1812             : 
    1813       10468 :         if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
    1814           0 :                 return NULL;
    1815             : 
    1816       10468 :         if (!PyLdbMessage_Check(py_msg_old)) {
    1817           0 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
    1818           0 :                 return NULL;
    1819             :         }
    1820             : 
    1821       10468 :         if (!PyLdbMessage_Check(py_msg_new)) {
    1822           0 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
    1823           0 :                 return NULL;
    1824             :         }
    1825             : 
    1826       10468 :         mem_ctx = talloc_new(NULL);
    1827       10468 :         if (mem_ctx == NULL) {
    1828           0 :                 PyErr_NoMemory();
    1829           0 :                 return NULL;
    1830             :         }
    1831             : 
    1832       10468 :         ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
    1833       20844 :         ldb_ret = ldb_msg_difference(ldb, mem_ctx,
    1834       10468 :                                      pyldb_Message_AsMessage(py_msg_old),
    1835       10468 :                                      pyldb_Message_AsMessage(py_msg_new),
    1836             :                                      &diff);
    1837       10468 :         if (ldb_ret != LDB_SUCCESS) {
    1838           0 :                 talloc_free(mem_ctx);
    1839           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff");
    1840           0 :                 return NULL;
    1841             :         }
    1842             : 
    1843       10468 :         diff = ldb_msg_copy(mem_ctx, diff);
    1844       10468 :         if (diff == NULL) {
    1845           0 :                 PyErr_NoMemory();
    1846           0 :                 return NULL;
    1847             :         }
    1848             : 
    1849       10468 :         py_ret = PyLdbMessage_FromMessage(diff);
    1850             : 
    1851       10468 :         talloc_free(mem_ctx);
    1852             : 
    1853       10468 :         return py_ret;
    1854             : }
    1855             : 
    1856       18605 : static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
    1857             : {
    1858             :         const struct ldb_schema_attribute *a;
    1859             :         struct ldb_val old_val;
    1860             :         struct ldb_val new_val;
    1861             :         TALLOC_CTX *mem_ctx;
    1862             :         PyObject *ret;
    1863             :         char *element_name;
    1864             :         PyObject *val;
    1865             :         Py_ssize_t size;
    1866             :         int result;
    1867             : 
    1868       18605 :         if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
    1869           0 :                 return NULL;
    1870             : 
    1871       18605 :         result = PyBytes_AsStringAndSize(val, (char **)&old_val.data, &size);
    1872       18605 :         old_val.length = size;
    1873             : 
    1874       18605 :         if (result != 0) {
    1875           0 :                 PyErr_SetString(PyExc_RuntimeError, "Failed to convert passed value to String");
    1876           0 :                 return NULL;
    1877             :         }
    1878             : 
    1879       18605 :         a = ldb_schema_attribute_by_name(pyldb_Ldb_AS_LDBCONTEXT(self), element_name);
    1880             : 
    1881       18605 :         if (a == NULL) {
    1882           0 :                 Py_RETURN_NONE;
    1883             :         }
    1884             : 
    1885       18605 :         mem_ctx = talloc_new(NULL);
    1886       18605 :         if (mem_ctx == NULL) {
    1887           0 :                 PyErr_NoMemory();
    1888           0 :                 return NULL;
    1889             :         }
    1890             : 
    1891       18605 :         if (a->syntax->ldif_write_fn(pyldb_Ldb_AS_LDBCONTEXT(self), mem_ctx, &old_val, &new_val) != 0) {
    1892           0 :                 talloc_free(mem_ctx);
    1893           0 :                 Py_RETURN_NONE;
    1894             :         }
    1895             : 
    1896       18605 :         ret = PyBytes_FromStringAndSize((const char *)new_val.data, new_val.length);
    1897             : 
    1898       18605 :         talloc_free(mem_ctx);
    1899             : 
    1900       18605 :         return ret;
    1901             : }
    1902             : 
    1903     2140577 : static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    1904             : {
    1905     2140577 :         PyObject *py_base = Py_None;
    1906     2140577 :         int scope = LDB_SCOPE_DEFAULT;
    1907     2140577 :         char *expr = NULL;
    1908     2140577 :         PyObject *py_attrs = Py_None;
    1909     2140577 :         PyObject *py_controls = Py_None;
    1910     2140577 :         const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", NULL };
    1911             :         int ret;
    1912             :         struct ldb_result *res;
    1913             :         struct ldb_request *req;
    1914             :         const char **attrs;
    1915             :         struct ldb_context *ldb_ctx;
    1916             :         struct ldb_control **parsed_controls;
    1917             :         struct ldb_dn *base;
    1918             :         PyObject *py_ret;
    1919             :         TALLOC_CTX *mem_ctx;
    1920             : 
    1921             :         /* type "int" rather than "enum" for "scope" is intentional */
    1922     2140577 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
    1923             :                                          discard_const_p(char *, kwnames),
    1924             :                                          &py_base, &scope, &expr, &py_attrs, &py_controls))
    1925           7 :                 return NULL;
    1926             : 
    1927             : 
    1928     2140570 :         mem_ctx = talloc_new(NULL);
    1929     2140570 :         if (mem_ctx == NULL) {
    1930           0 :                 PyErr_NoMemory();
    1931           0 :                 return NULL;
    1932             :         }
    1933     2140570 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    1934             : 
    1935     2140570 :         if (py_attrs == Py_None) {
    1936      406752 :                 attrs = NULL;
    1937             :         } else {
    1938     1733818 :                 attrs = PyList_AsStrList(mem_ctx, py_attrs, "attrs");
    1939     1733818 :                 if (attrs == NULL) {
    1940           8 :                         talloc_free(mem_ctx);
    1941           8 :                         return NULL;
    1942             :                 }
    1943             :         }
    1944             : 
    1945     2140562 :         if (py_base == Py_None) {
    1946        1441 :                 base = ldb_get_default_basedn(ldb_ctx);
    1947             :         } else {
    1948     2139121 :                 if (!pyldb_Object_AsDn(mem_ctx, py_base, ldb_ctx, &base)) {
    1949           2 :                         talloc_free(mem_ctx);
    1950           2 :                         return NULL;
    1951             :                 }
    1952             :         }
    1953             : 
    1954     2140560 :         if (py_controls == Py_None) {
    1955      530187 :                 parsed_controls = NULL;
    1956             :         } else {
    1957     1610373 :                 const char **controls = PyList_AsStrList(mem_ctx, py_controls, "controls");
    1958     1610373 :                 if (controls == NULL) {
    1959           2 :                         talloc_free(mem_ctx);
    1960           2 :                         return NULL;
    1961             :                 }
    1962     1610371 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls);
    1963     1610371 :                 talloc_free(controls);
    1964             :         }
    1965             : 
    1966     2140558 :         res = talloc_zero(mem_ctx, struct ldb_result);
    1967     2140558 :         if (res == NULL) {
    1968           0 :                 PyErr_NoMemory();
    1969           0 :                 talloc_free(mem_ctx);
    1970           0 :                 return NULL;
    1971             :         }
    1972             : 
    1973     2140558 :         ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx,
    1974             :                                    base,
    1975             :                                    scope,
    1976             :                                    expr,
    1977             :                                    attrs,
    1978             :                                    parsed_controls,
    1979             :                                    res,
    1980             :                                    ldb_search_default_callback,
    1981             :                                    NULL);
    1982             : 
    1983     2140558 :         if (ret != LDB_SUCCESS) {
    1984           5 :                 talloc_free(mem_ctx);
    1985           5 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    1986           5 :                 return NULL;
    1987             :         }
    1988             : 
    1989     2140553 :         talloc_steal(req, attrs);
    1990             : 
    1991     2140553 :         ret = ldb_request(ldb_ctx, req);
    1992             : 
    1993     2140553 :         if (ret == LDB_SUCCESS) {
    1994     2140437 :                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
    1995             :         }
    1996             : 
    1997     2140553 :         if (ret != LDB_SUCCESS) {
    1998       86725 :                 talloc_free(mem_ctx);
    1999       86725 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    2000       86725 :                 return NULL;
    2001             :         }
    2002             : 
    2003     2053828 :         py_ret = PyLdbResult_FromResult(res);
    2004             : 
    2005     2053828 :         talloc_free(mem_ctx);
    2006             : 
    2007     2053828 :         return py_ret;
    2008             : }
    2009             : 
    2010        4778 : static int py_ldb_search_iterator_reply_destructor(struct py_ldb_search_iterator_reply *reply)
    2011             : {
    2012        4778 :         if (reply->py_iter != NULL) {
    2013        4778 :                 DLIST_REMOVE(reply->py_iter->state.next, reply);
    2014        4778 :                 if (reply->py_iter->state.result == reply) {
    2015          38 :                         reply->py_iter->state.result = NULL;
    2016             :                 }
    2017        4778 :                 reply->py_iter = NULL;
    2018             :         }
    2019             : 
    2020        4778 :         if (reply->obj != NULL) {
    2021          14 :                 Py_DECREF(reply->obj);
    2022          14 :                 reply->obj = NULL;
    2023             :         }
    2024             : 
    2025        4778 :         return 0;
    2026             : }
    2027             : 
    2028        6304 : static int py_ldb_search_iterator_callback(struct ldb_request *req,
    2029             :                                            struct ldb_reply *ares)
    2030             : {
    2031        6304 :         PyLdbSearchIteratorObject *py_iter = (PyLdbSearchIteratorObject *)req->context;
    2032        6304 :         struct ldb_result result = { .msgs = NULL };
    2033        6304 :         struct py_ldb_search_iterator_reply *reply = NULL;
    2034             : 
    2035        6304 :         if (ares == NULL) {
    2036           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2037             :         }
    2038             : 
    2039        6304 :         if (ares->error != LDB_SUCCESS) {
    2040        1526 :                 int ret = ares->error;
    2041        1526 :                 TALLOC_FREE(ares);
    2042        1526 :                 return ldb_request_done(req, ret);
    2043             :         }
    2044             : 
    2045        4778 :         reply = talloc_zero(py_iter->mem_ctx,
    2046             :                             struct py_ldb_search_iterator_reply);
    2047        4778 :         if (reply == NULL) {
    2048           0 :                 TALLOC_FREE(ares);
    2049           0 :                 return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2050             :         }
    2051        4778 :         reply->py_iter = py_iter;
    2052        4778 :         talloc_set_destructor(reply, py_ldb_search_iterator_reply_destructor);
    2053             : 
    2054        4778 :         switch (ares->type) {
    2055        4728 :         case LDB_REPLY_ENTRY:
    2056        4728 :                 reply->obj = PyLdbMessage_FromMessage(ares->message);
    2057        4728 :                 if (reply->obj == NULL) {
    2058           0 :                         TALLOC_FREE(ares);
    2059           0 :                         return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2060             :                 }
    2061        4728 :                 DLIST_ADD_END(py_iter->state.next, reply);
    2062        4728 :                 TALLOC_FREE(ares);
    2063        4728 :                 return LDB_SUCCESS;
    2064             : 
    2065          12 :         case LDB_REPLY_REFERRAL:
    2066          12 :                 reply->obj = PyUnicode_FromString(ares->referral);
    2067          12 :                 if (reply->obj == NULL) {
    2068           0 :                         TALLOC_FREE(ares);
    2069           0 :                         return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2070             :                 }
    2071          12 :                 DLIST_ADD_END(py_iter->state.next, reply);
    2072          12 :                 TALLOC_FREE(ares);
    2073          12 :                 return LDB_SUCCESS;
    2074             : 
    2075          38 :         case LDB_REPLY_DONE:
    2076          38 :                 result = (struct ldb_result) { .controls = ares->controls };
    2077          38 :                 reply->obj = PyLdbResult_FromResult(&result);
    2078          38 :                 if (reply->obj == NULL) {
    2079           0 :                         TALLOC_FREE(ares);
    2080           0 :                         return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2081             :                 }
    2082          38 :                 py_iter->state.result = reply;
    2083          38 :                 TALLOC_FREE(ares);
    2084          38 :                 return ldb_request_done(req, LDB_SUCCESS);
    2085             :         }
    2086             : 
    2087           0 :         TALLOC_FREE(ares);
    2088           0 :         return ldb_request_done(req, LDB_ERR_OPERATIONS_ERROR);
    2089             : }
    2090             : 
    2091        1585 : static PyObject *py_ldb_search_iterator(PyLdbObject *self, PyObject *args, PyObject *kwargs)
    2092             : {
    2093        1585 :         PyObject *py_base = Py_None;
    2094        1585 :         int scope = LDB_SCOPE_DEFAULT;
    2095        1585 :         int timeout = 0;
    2096        1585 :         char *expr = NULL;
    2097        1585 :         PyObject *py_attrs = Py_None;
    2098        1585 :         PyObject *py_controls = Py_None;
    2099        1585 :         const char * const kwnames[] = { "base", "scope", "expression", "attrs", "controls", "timeout", NULL };
    2100             :         int ret;
    2101             :         const char **attrs;
    2102             :         struct ldb_context *ldb_ctx;
    2103             :         struct ldb_control **parsed_controls;
    2104             :         struct ldb_dn *base;
    2105             :         PyLdbSearchIteratorObject *py_iter;
    2106             : 
    2107             :         /* type "int" rather than "enum" for "scope" is intentional */
    2108        1585 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOOi",
    2109             :                                          discard_const_p(char *, kwnames),
    2110             :                                          &py_base, &scope, &expr, &py_attrs, &py_controls, &timeout))
    2111           0 :                 return NULL;
    2112             : 
    2113        1585 :         py_iter = (PyLdbSearchIteratorObject *)PyLdbSearchIterator.tp_alloc(&PyLdbSearchIterator, 0);
    2114        1585 :         if (py_iter == NULL) {
    2115           0 :                 PyErr_NoMemory();
    2116           0 :                 return NULL;
    2117             :         }
    2118        1585 :         py_iter->ldb = self;
    2119        1585 :         Py_INCREF(self);
    2120        1585 :         ZERO_STRUCT(py_iter->state);
    2121        1585 :         py_iter->mem_ctx = talloc_new(NULL);
    2122        1585 :         if (py_iter->mem_ctx == NULL) {
    2123           0 :                 Py_DECREF(py_iter);
    2124           0 :                 PyErr_NoMemory();
    2125           0 :                 return NULL;
    2126             :         }
    2127             : 
    2128        1585 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    2129             : 
    2130        1585 :         if (py_attrs == Py_None) {
    2131          29 :                 attrs = NULL;
    2132             :         } else {
    2133        1556 :                 attrs = PyList_AsStrList(py_iter->mem_ctx, py_attrs, "attrs");
    2134        1556 :                 if (attrs == NULL) {
    2135           0 :                         Py_DECREF(py_iter);
    2136           0 :                         PyErr_NoMemory();
    2137           0 :                         return NULL;
    2138             :                 }
    2139             :         }
    2140             : 
    2141        1585 :         if (py_base == Py_None) {
    2142          42 :                 base = ldb_get_default_basedn(ldb_ctx);
    2143             :         } else {
    2144        1543 :                 if (!pyldb_Object_AsDn(py_iter->mem_ctx, py_base, ldb_ctx, &base)) {
    2145           0 :                         Py_DECREF(py_iter);
    2146           0 :                         PyErr_NoMemory();
    2147           0 :                         return NULL;
    2148             :                 }
    2149             :         }
    2150             : 
    2151        1585 :         if (py_controls == Py_None) {
    2152          56 :                 parsed_controls = NULL;
    2153             :         } else {
    2154        1529 :                 const char **controls = NULL;
    2155             : 
    2156        1529 :                 controls = PyList_AsStrList(py_iter->mem_ctx,
    2157             :                                             py_controls, "controls");
    2158        1529 :                 if (controls == NULL) {
    2159           0 :                         Py_DECREF(py_iter);
    2160           0 :                         PyErr_NoMemory();
    2161           0 :                         return NULL;
    2162             :                 }
    2163             : 
    2164        1529 :                 parsed_controls = ldb_parse_control_strings(ldb_ctx,
    2165             :                                                             py_iter->mem_ctx,
    2166             :                                                             controls);
    2167        1529 :                 if (controls[0] != NULL && parsed_controls == NULL) {
    2168           0 :                         Py_DECREF(py_iter);
    2169           0 :                         PyErr_NoMemory();
    2170           0 :                         return NULL;
    2171             :                 }
    2172        1529 :                 talloc_free(controls);
    2173             :         }
    2174             : 
    2175        1585 :         ret = ldb_build_search_req(&py_iter->state.req,
    2176             :                                    ldb_ctx,
    2177             :                                    py_iter->mem_ctx,
    2178             :                                    base,
    2179             :                                    scope,
    2180             :                                    expr,
    2181             :                                    attrs,
    2182             :                                    parsed_controls,
    2183             :                                    py_iter,
    2184             :                                    py_ldb_search_iterator_callback,
    2185             :                                    NULL);
    2186        1585 :         if (ret != LDB_SUCCESS) {
    2187           0 :                 Py_DECREF(py_iter);
    2188           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    2189           0 :                 return NULL;
    2190             :         }
    2191             : 
    2192        1585 :         ldb_set_timeout(ldb_ctx, py_iter->state.req, timeout);
    2193             : 
    2194        1585 :         ret = ldb_request(ldb_ctx, py_iter->state.req);
    2195        1585 :         if (ret != LDB_SUCCESS) {
    2196           0 :                 Py_DECREF(py_iter);
    2197           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    2198           0 :                 return NULL;
    2199             :         }
    2200             : 
    2201        1585 :         return (PyObject *)py_iter;
    2202             : }
    2203             : 
    2204           6 : static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
    2205             : {
    2206             :         char *name;
    2207             :         void *data;
    2208             : 
    2209           6 :         if (!PyArg_ParseTuple(args, "s", &name))
    2210           0 :                 return NULL;
    2211             : 
    2212           6 :         data = ldb_get_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name);
    2213             : 
    2214           6 :         if (data == NULL)
    2215           3 :                 Py_RETURN_NONE;
    2216             : 
    2217             :         /* FIXME: More interpretation */
    2218             : 
    2219           3 :         Py_RETURN_TRUE;
    2220             : }
    2221             : 
    2222           3 : static PyObject *py_ldb_set_opaque(PyLdbObject *self, PyObject *args)
    2223             : {
    2224             :         char *name;
    2225             :         PyObject *data;
    2226             : 
    2227           3 :         if (!PyArg_ParseTuple(args, "sO", &name, &data))
    2228           0 :                 return NULL;
    2229             : 
    2230             :         /* FIXME: More interpretation */
    2231             : 
    2232           3 :         ldb_set_opaque(pyldb_Ldb_AS_LDBCONTEXT(self), name, data);
    2233             : 
    2234           3 :         Py_RETURN_NONE;
    2235             : }
    2236             : 
    2237           6 : static PyObject *py_ldb_modules(PyLdbObject *self,
    2238             :                 PyObject *Py_UNUSED(ignored))
    2239             : {
    2240           6 :         struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
    2241           6 :         PyObject *ret = PyList_New(0);
    2242             :         struct ldb_module *mod;
    2243             : 
    2244           6 :         if (ret == NULL) {
    2245           0 :                 return PyErr_NoMemory();
    2246             :         }
    2247           9 :         for (mod = ldb->modules; mod; mod = mod->next) {
    2248           3 :                 PyObject *item = PyLdbModule_FromModule(mod);
    2249           3 :                 int res = 0;
    2250           3 :                 if (item == NULL) {
    2251           0 :                         PyErr_SetString(PyExc_RuntimeError,
    2252             :                                 "Failed to load LdbModule");
    2253           0 :                         Py_CLEAR(ret);
    2254           0 :                         return NULL;
    2255             :                 }
    2256           3 :                 res = PyList_Append(ret, item);
    2257           3 :                 Py_CLEAR(item);
    2258           3 :                 if (res == -1) {
    2259           0 :                         Py_CLEAR(ret);
    2260           0 :                         return NULL;
    2261             :                 }
    2262             :         }
    2263             : 
    2264           6 :         return ret;
    2265             : }
    2266             : 
    2267          47 : static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args)
    2268             : {
    2269          47 :         struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
    2270             :         int type, ret;
    2271             :         uint64_t value;
    2272             : 
    2273          47 :         if (!PyArg_ParseTuple(args, "i", &type))
    2274           0 :                 return NULL;
    2275             : 
    2276             :         /* FIXME: More interpretation */
    2277             : 
    2278          47 :         ret = ldb_sequence_number(ldb, type, &value);
    2279             : 
    2280          47 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
    2281             : 
    2282          47 :         return PyLong_FromLongLong(value);
    2283             : }
    2284             : 
    2285             : 
    2286             : static const struct ldb_dn_extended_syntax test_dn_syntax = {
    2287             :         .name             = "TEST",
    2288             :         .read_fn          = ldb_handler_copy,
    2289             :         .write_clear_fn   = ldb_handler_copy,
    2290             :         .write_hex_fn     = ldb_handler_copy,
    2291             : };
    2292             : 
    2293           6 : static PyObject *py_ldb_register_test_extensions(PyLdbObject *self,
    2294             :                 PyObject *Py_UNUSED(ignored))
    2295             : {
    2296           6 :         struct ldb_context *ldb = pyldb_Ldb_AS_LDBCONTEXT(self);
    2297             :         int ret;
    2298             : 
    2299           6 :         ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &test_dn_syntax);
    2300             : 
    2301           6 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
    2302             : 
    2303           6 :         Py_RETURN_NONE;
    2304             : }
    2305             : 
    2306             : 
    2307             : static PyMethodDef py_ldb_methods[] = {
    2308             :         { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, 
    2309             :                 "S.set_debug(callback) -> None\n"
    2310             :                 "Set callback for LDB debug messages.\n"
    2311             :                 "The callback should accept a debug level and debug text." },
    2312             :         { "set_create_perms", (PyCFunction)py_ldb_set_create_perms, METH_VARARGS, 
    2313             :                 "S.set_create_perms(mode) -> None\n"
    2314             :                 "Set mode to use when creating new LDB files." },
    2315             :         { "set_modules_dir", (PyCFunction)py_ldb_set_modules_dir, METH_VARARGS,
    2316             :                 "S.set_modules_dir(path) -> None\n"
    2317             :                 "Set path LDB should search for modules" },
    2318             :         { "transaction_start", (PyCFunction)py_ldb_transaction_start, METH_NOARGS, 
    2319             :                 "S.transaction_start() -> None\n"
    2320             :                 "Start a new transaction." },
    2321             :         { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS,
    2322             :                 "S.transaction_prepare_commit() -> None\n"
    2323             :                 "prepare to commit a new transaction (2-stage commit)." },
    2324             :         { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 
    2325             :                 "S.transaction_commit() -> None\n"
    2326             :                 "commit a new transaction." },
    2327             :         { "transaction_cancel", (PyCFunction)py_ldb_transaction_cancel, METH_NOARGS, 
    2328             :                 "S.transaction_cancel() -> None\n"
    2329             :                 "cancel a new transaction." },
    2330             :         { "setup_wellknown_attributes", (PyCFunction)py_ldb_setup_wellknown_attributes, METH_NOARGS, 
    2331             :                 NULL },
    2332             :         { "get_root_basedn", (PyCFunction)py_ldb_get_root_basedn, METH_NOARGS,
    2333             :                 NULL },
    2334             :         { "get_schema_basedn", (PyCFunction)py_ldb_get_schema_basedn, METH_NOARGS,
    2335             :                 NULL },
    2336             :         { "get_default_basedn", (PyCFunction)py_ldb_get_default_basedn, METH_NOARGS,
    2337             :                 NULL },
    2338             :         { "get_config_basedn", (PyCFunction)py_ldb_get_config_basedn, METH_NOARGS,
    2339             :                 NULL },
    2340             :         { "connect", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_connect),
    2341             :                 METH_VARARGS|METH_KEYWORDS,
    2342             :                 "S.connect(url, flags=0, options=None) -> None\n"
    2343             :                 "Connect to a LDB URL." },
    2344             :         { "modify", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_modify),
    2345             :                 METH_VARARGS|METH_KEYWORDS,
    2346             :                 "S.modify(message, controls=None, validate=False) -> None\n"
    2347             :                 "Modify an entry." },
    2348             :         { "add", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_add),
    2349             :                 METH_VARARGS|METH_KEYWORDS,
    2350             :                 "S.add(message, controls=None) -> None\n"
    2351             :                 "Add an entry." },
    2352             :         { "delete", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_delete),
    2353             :                 METH_VARARGS|METH_KEYWORDS,
    2354             :                 "S.delete(dn, controls=None) -> None\n"
    2355             :                 "Remove an entry." },
    2356             :         { "rename", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_rename),
    2357             :                 METH_VARARGS|METH_KEYWORDS,
    2358             :                 "S.rename(old_dn, new_dn, controls=None) -> None\n"
    2359             :                 "Rename an entry." },
    2360             :         { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_search),
    2361             :                 METH_VARARGS|METH_KEYWORDS,
    2362             :                 "S.search(base=None, scope=None, expression=None, attrs=None, controls=None) -> result\n"
    2363             :                 "Search in a database.\n"
    2364             :                 "\n"
    2365             :                 ":param base: Optional base DN to search\n"
    2366             :                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
    2367             :                 ":param expression: Optional search expression\n"
    2368             :                 ":param attrs: Attributes to return (defaults to all)\n"
    2369             :                 ":param controls: Optional list of controls\n"
    2370             :                 ":return: ldb.Result object\n"
    2371             :         },
    2372             :         { "search_iterator", PY_DISCARD_FUNC_SIG(PyCFunction,
    2373             :                                                  py_ldb_search_iterator),
    2374             :                 METH_VARARGS|METH_KEYWORDS,
    2375             :                 "S.search_iterator(base=None, scope=None, expression=None, attrs=None, controls=None, timeout=None) -> iterator\n"
    2376             :                 "Search in a database.\n"
    2377             :                 "\n"
    2378             :                 ":param base: Optional base DN to search\n"
    2379             :                 ":param scope: Search scope (SCOPE_BASE, SCOPE_ONELEVEL or SCOPE_SUBTREE)\n"
    2380             :                 ":param expression: Optional search expression\n"
    2381             :                 ":param attrs: Attributes to return (defaults to all)\n"
    2382             :                 ":param controls: Optional list of controls\n"
    2383             :                 ":param timeout: Optional timeout in seconds (defaults to 300), 0 means the default, -1 no timeout\n"
    2384             :                 ":return: ldb.SearchIterator object that provides results when they arrive\n"
    2385             :         },
    2386             :         { "schema_attribute_remove", (PyCFunction)py_ldb_schema_attribute_remove, METH_VARARGS,
    2387             :                 NULL },
    2388             :         { "schema_attribute_add", (PyCFunction)py_ldb_schema_attribute_add, METH_VARARGS,
    2389             :                 NULL },
    2390             :         { "schema_format_value", (PyCFunction)py_ldb_schema_format_value, METH_VARARGS,
    2391             :                 NULL },
    2392             :         { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
    2393             :                 "S.parse_ldif(ldif) -> iter(messages)\n"
    2394             :                 "Parse a string formatted using LDIF." },
    2395             :         { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
    2396             :                 "S.write_ldif(message, changetype) -> ldif\n"
    2397             :                 "Print the message as a string formatted using LDIF." },
    2398             :         { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
    2399             :                 "S.msg_diff(Message) -> Message\n"
    2400             :                 "Return an LDB Message of the difference between two Message objects." },
    2401             :         { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
    2402             :                 "S.get_opaque(name) -> value\n"
    2403             :                 "Get an opaque value set on this LDB connection. \n"
    2404             :                 ":note: The returned value may not be useful in Python."
    2405             :         },
    2406             :         { "set_opaque", (PyCFunction)py_ldb_set_opaque, METH_VARARGS,
    2407             :                 "S.set_opaque(name, value) -> None\n"
    2408             :                 "Set an opaque value on this LDB connection. \n"
    2409             :                 ":note: Passing incorrect values may cause crashes." },
    2410             :         { "modules", (PyCFunction)py_ldb_modules, METH_NOARGS,
    2411             :                 "S.modules() -> list\n"
    2412             :                 "Return the list of modules on this LDB connection " },
    2413             :         { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS,
    2414             :                 "S.sequence_number(type) -> value\n"
    2415             :                 "Return the value of the sequence according to the requested type" },
    2416             :         { "_register_test_extensions", (PyCFunction)py_ldb_register_test_extensions, METH_NOARGS,
    2417             :                 "S._register_test_extensions() -> None\n"
    2418             :                 "Register internal extensions used in testing" },
    2419             :         {0},
    2420             : };
    2421             : 
    2422           8 : static PyObject *PyLdbModule_FromModule(struct ldb_module *mod)
    2423             : {
    2424             :         PyLdbModuleObject *ret;
    2425             : 
    2426           8 :         ret = (PyLdbModuleObject *)PyLdbModule.tp_alloc(&PyLdbModule, 0);
    2427           8 :         if (ret == NULL) {
    2428           0 :                 PyErr_NoMemory();
    2429           0 :                 return NULL;
    2430             :         }
    2431           8 :         ret->mem_ctx = talloc_new(NULL);
    2432           8 :         ret->mod = talloc_reference(ret->mem_ctx, mod);
    2433           8 :         return (PyObject *)ret;
    2434             : }
    2435             : 
    2436           6 : static PyObject *py_ldb_get_firstmodule(PyLdbObject *self, void *closure)
    2437             : {
    2438           6 :         struct ldb_module *mod = pyldb_Ldb_AS_LDBCONTEXT(self)->modules;
    2439           6 :         if (mod == NULL) {
    2440           3 :                 Py_RETURN_NONE;
    2441             :         }
    2442           3 :         return PyLdbModule_FromModule(mod);
    2443             : }
    2444             : 
    2445             : static PyGetSetDef py_ldb_getset[] = {
    2446             :         {
    2447             :                 .name = discard_const_p(char, "firstmodule"),
    2448             :                 .get  = (getter)py_ldb_get_firstmodule,
    2449             :         },
    2450             :         { .name = NULL },
    2451             : };
    2452             : 
    2453           9 : static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
    2454             : {
    2455           9 :         struct ldb_context *ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self);
    2456             :         struct ldb_dn *dn;
    2457             :         struct ldb_result *result;
    2458             :         unsigned int count;
    2459             :         int ret;
    2460             : 
    2461           9 :         if (!pyldb_Object_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) {
    2462           0 :                 return -1;
    2463             :         }
    2464             : 
    2465           9 :         ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL,
    2466             :                          NULL);
    2467           9 :         if (ret != LDB_SUCCESS) {
    2468           0 :                 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
    2469           0 :                 return -1;
    2470             :         }
    2471             : 
    2472           9 :         count = result->count;
    2473             : 
    2474           9 :         talloc_free(result);
    2475             : 
    2476           9 :         if (count > 1) {
    2477           0 :                 PyErr_Format(PyExc_RuntimeError,
    2478             :                              "Searching for [%s] dn gave %u results!",
    2479             :                              ldb_dn_get_linearized(dn),
    2480             :                              count);
    2481           0 :                 return -1;
    2482             :         }
    2483             : 
    2484           9 :         return count;
    2485             : }
    2486             : 
    2487             : static PySequenceMethods py_ldb_seq = {
    2488             :         .sq_contains = (objobjproc)py_ldb_contains,
    2489             : };
    2490             : 
    2491           2 : static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)
    2492             : {
    2493             :         PyLdbObject *ret;
    2494             : 
    2495           2 :         ret = (PyLdbObject *)PyLdb.tp_alloc(&PyLdb, 0);
    2496           2 :         if (ret == NULL) {
    2497           0 :                 PyErr_NoMemory();
    2498           0 :                 return NULL;
    2499             :         }
    2500           2 :         ret->mem_ctx = talloc_new(NULL);
    2501           2 :         ret->ldb_ctx = talloc_reference(ret->mem_ctx, ldb_ctx);
    2502           2 :         return (PyObject *)ret;
    2503             : }
    2504             : 
    2505       26858 : static void py_ldb_dealloc(PyLdbObject *self)
    2506             : {
    2507       26858 :         talloc_free(self->mem_ctx);
    2508       26858 :         Py_TYPE(self)->tp_free(self);
    2509       26858 : }
    2510             : 
    2511             : static PyTypeObject PyLdb = {
    2512             :         .tp_name = "ldb.Ldb",
    2513             :         .tp_methods = py_ldb_methods,
    2514             :         .tp_repr = (reprfunc)py_ldb_repr,
    2515             :         .tp_new = py_ldb_new,
    2516             :         .tp_init = (initproc)py_ldb_init,
    2517             :         .tp_dealloc = (destructor)py_ldb_dealloc,
    2518             :         .tp_getset = py_ldb_getset,
    2519             :         .tp_getattro = PyObject_GenericGetAttr,
    2520             :         .tp_basicsize = sizeof(PyLdbObject),
    2521             :         .tp_doc = "Connection to a LDB database.",
    2522             :         .tp_as_sequence = &py_ldb_seq,
    2523             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    2524             : };
    2525             : 
    2526     2053866 : static void py_ldb_result_dealloc(PyLdbResultObject *self)
    2527             : {
    2528     2053866 :         talloc_free(self->mem_ctx);
    2529     2053866 :         Py_DECREF(self->msgs);
    2530     2053866 :         Py_DECREF(self->referals);
    2531     2053866 :         Py_DECREF(self->controls);
    2532     2053866 :         Py_TYPE(self)->tp_free(self);
    2533     2053866 : }
    2534             : 
    2535          44 : static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure)
    2536             : {
    2537          44 :         Py_INCREF(self->msgs);
    2538          44 :         return self->msgs;
    2539             : }
    2540             : 
    2541       46470 : static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure)
    2542             : {
    2543       46470 :         Py_INCREF(self->controls);
    2544       46470 :         return self->controls;
    2545             : }
    2546             : 
    2547          57 : static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure)
    2548             : {
    2549          57 :         Py_INCREF(self->referals);
    2550          57 :         return self->referals;
    2551             : }
    2552             : 
    2553         166 : static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure)
    2554             : {
    2555             :         Py_ssize_t size;
    2556         166 :         if (self->msgs == NULL) {
    2557           0 :                 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context");
    2558           0 :                 return NULL;
    2559             :         }
    2560         166 :         size = PyList_Size(self->msgs);
    2561         166 :         return PyLong_FromLong(size);
    2562             : }
    2563             : 
    2564             : static PyGetSetDef py_ldb_result_getset[] = {
    2565             :         {
    2566             :                 .name = discard_const_p(char, "controls"),
    2567             :                 .get  = (getter)py_ldb_result_get_controls,
    2568             :         },
    2569             :         {
    2570             :                 .name = discard_const_p(char, "msgs"),
    2571             :                 .get  = (getter)py_ldb_result_get_msgs,
    2572             :         },
    2573             :         {
    2574             :                 .name = discard_const_p(char, "referals"),
    2575             :                 .get  = (getter)py_ldb_result_get_referals,
    2576             :         },
    2577             :         {
    2578             :                 .name = discard_const_p(char, "count"),
    2579             :                 .get  = (getter)py_ldb_result_get_count,
    2580             :         },
    2581             :         { .name = NULL },
    2582             : };
    2583             : 
    2584      162776 : static PyObject *py_ldb_result_iter(PyLdbResultObject *self)
    2585             : {
    2586      162776 :         return PyObject_GetIter(self->msgs);
    2587             : }
    2588             : 
    2589     1226671 : static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self)
    2590             : {
    2591     1226671 :         return PySequence_Size(self->msgs);
    2592             : }
    2593             : 
    2594     2932472 : static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx)
    2595             : {
    2596     2932472 :         return PySequence_GetItem(self->msgs, idx);
    2597             : }
    2598             : 
    2599             : static PySequenceMethods py_ldb_result_seq = {
    2600             :         .sq_length = (lenfunc)py_ldb_result_len,
    2601             :         .sq_item = (ssizeargfunc)py_ldb_result_find,
    2602             : };
    2603             : 
    2604           3 : static PyObject *py_ldb_result_repr(PyLdbObject *self)
    2605             : {
    2606           3 :         return PyUnicode_FromString("<ldb result>");
    2607             : }
    2608             : 
    2609             : 
    2610             : static PyTypeObject PyLdbResult = {
    2611             :         .tp_name = "ldb.Result",
    2612             :         .tp_repr = (reprfunc)py_ldb_result_repr,
    2613             :         .tp_dealloc = (destructor)py_ldb_result_dealloc,
    2614             :         .tp_iter = (getiterfunc)py_ldb_result_iter,
    2615             :         .tp_getset = py_ldb_result_getset,
    2616             :         .tp_getattro = PyObject_GenericGetAttr,
    2617             :         .tp_basicsize = sizeof(PyLdbResultObject),
    2618             :         .tp_as_sequence = &py_ldb_result_seq,
    2619             :         .tp_doc = "LDB result.",
    2620             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    2621             : };
    2622             : 
    2623        1585 : static void py_ldb_search_iterator_dealloc(PyLdbSearchIteratorObject *self)
    2624             : {
    2625        1585 :         Py_XDECREF(self->state.exception);
    2626        1585 :         TALLOC_FREE(self->mem_ctx);
    2627        1585 :         ZERO_STRUCT(self->state);
    2628        1585 :         Py_DECREF(self->ldb);
    2629        1585 :         Py_TYPE(self)->tp_free(self);
    2630        1585 : }
    2631             : 
    2632        6307 : static PyObject *py_ldb_search_iterator_next(PyLdbSearchIteratorObject *self)
    2633             : {
    2634        6307 :         PyObject *py_ret = NULL;
    2635             : 
    2636        6307 :         if (self->state.req == NULL) {
    2637           3 :                 PyErr_SetString(PyExc_RuntimeError,
    2638             :                                 "ldb.SearchIterator request already finished");
    2639           3 :                 return NULL;
    2640             :         }
    2641             : 
    2642             :         /*
    2643             :          * TODO: do we want a non-blocking mode?
    2644             :          * In future we may add an optional 'nonblocking'
    2645             :          * argument to search_iterator().
    2646             :          *
    2647             :          * For now we keep it simple and wait for at
    2648             :          * least one reply.
    2649             :          */
    2650             : 
    2651     3461513 :         while (self->state.next == NULL) {
    2652             :                 int ret;
    2653             : 
    2654     3451228 :                 if (self->state.result != NULL) {
    2655             :                         /*
    2656             :                          * We (already) got a final result from the server.
    2657             :                          *
    2658             :                          * We stop the iteration and let
    2659             :                          * py_ldb_search_iterator_result() will deliver
    2660             :                          * the result details.
    2661             :                          */
    2662          38 :                         TALLOC_FREE(self->state.req);
    2663          38 :                         PyErr_SetNone(PyExc_StopIteration);
    2664          38 :                         return NULL;
    2665             :                 }
    2666             : 
    2667     3451190 :                 ret = ldb_wait(self->state.req->handle, LDB_WAIT_NONE);
    2668     3451190 :                 if (ret != LDB_SUCCESS) {
    2669             :                         struct ldb_context *ldb_ctx;
    2670        1526 :                         TALLOC_FREE(self->state.req);
    2671        1526 :                         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(self->ldb);
    2672             :                         /*
    2673             :                          * We stop the iteration and let
    2674             :                          * py_ldb_search_iterator_result() will deliver
    2675             :                          * the exception.
    2676             :                          */
    2677        1526 :                         self->state.exception = Py_BuildValue(discard_const_p(char, "(i,s)"),
    2678             :                                                 ret, ldb_errstring(ldb_ctx));
    2679        1526 :                         PyErr_SetNone(PyExc_StopIteration);
    2680        1526 :                         return NULL;
    2681             :                 }
    2682             :         }
    2683             : 
    2684        4740 :         py_ret = self->state.next->obj;
    2685        4740 :         self->state.next->obj = NULL;
    2686             :         /* no TALLOC_FREE() as self->state.next is a list */
    2687        4740 :         talloc_free(self->state.next);
    2688        4740 :         return py_ret;
    2689             : }
    2690             : 
    2691        1546 : static PyObject *py_ldb_search_iterator_result(PyLdbSearchIteratorObject *self,
    2692             :                 PyObject *Py_UNUSED(ignored))
    2693             : {
    2694        1546 :         PyObject *py_ret = NULL;
    2695             : 
    2696        1546 :         if (self->state.req != NULL) {
    2697           3 :                 PyErr_SetString(PyExc_RuntimeError,
    2698             :                                 "ldb.SearchIterator request running");
    2699           3 :                 return NULL;
    2700             :         }
    2701             : 
    2702        1543 :         if (self->state.next != NULL) {
    2703           0 :                 PyErr_SetString(PyExc_RuntimeError,
    2704             :                                 "ldb.SearchIterator not fully consumed.");
    2705           0 :                 return NULL;
    2706             :         }
    2707             : 
    2708        1543 :         if (self->state.exception != NULL) {
    2709        1516 :                 PyErr_SetObject(PyExc_LdbError, self->state.exception);
    2710        1516 :                 self->state.exception = NULL;
    2711        1516 :                 return NULL;
    2712             :         }
    2713             : 
    2714          27 :         if (self->state.result == NULL) {
    2715           3 :                 PyErr_SetString(PyExc_RuntimeError,
    2716             :                                 "ldb.SearchIterator result already consumed");
    2717           3 :                 return NULL;
    2718             :         }
    2719             : 
    2720          24 :         py_ret = self->state.result->obj;
    2721          24 :         self->state.result->obj = NULL;
    2722          24 :         TALLOC_FREE(self->state.result);
    2723          24 :         return py_ret;
    2724             : }
    2725             : 
    2726           6 : static PyObject *py_ldb_search_iterator_abandon(PyLdbSearchIteratorObject *self,
    2727             :                 PyObject *Py_UNUSED(ignored))
    2728             : {
    2729           6 :         if (self->state.req == NULL) {
    2730           3 :                 PyErr_SetString(PyExc_RuntimeError,
    2731             :                                 "ldb.SearchIterator request already finished");
    2732           3 :                 return NULL;
    2733             :         }
    2734             : 
    2735           3 :         Py_XDECREF(self->state.exception);
    2736           3 :         TALLOC_FREE(self->mem_ctx);
    2737           3 :         ZERO_STRUCT(self->state);
    2738           3 :         Py_RETURN_NONE;
    2739             : }
    2740             : 
    2741             : static PyMethodDef py_ldb_search_iterator_methods[] = {
    2742             :         { "result", (PyCFunction)py_ldb_search_iterator_result, METH_NOARGS,
    2743             :                 "S.result() -> ldb.Result (without msgs and referrals)\n" },
    2744             :         { "abandon", (PyCFunction)py_ldb_search_iterator_abandon, METH_NOARGS,
    2745             :                 "S.abandon()\n" },
    2746             :         {0}
    2747             : };
    2748             : 
    2749           0 : static PyObject *py_ldb_search_iterator_repr(PyLdbSearchIteratorObject *self)
    2750             : {
    2751           0 :         return PyUnicode_FromString("<ldb search iterator>");
    2752             : }
    2753             : 
    2754             : static PyTypeObject PyLdbSearchIterator = {
    2755             :         .tp_name = "ldb.SearchIterator",
    2756             :         .tp_repr = (reprfunc)py_ldb_search_iterator_repr,
    2757             :         .tp_dealloc = (destructor)py_ldb_search_iterator_dealloc,
    2758             :         .tp_iter = PyObject_SelfIter,
    2759             :         .tp_iternext = (iternextfunc)py_ldb_search_iterator_next,
    2760             :         .tp_methods = py_ldb_search_iterator_methods,
    2761             :         .tp_basicsize = sizeof(PyLdbSearchIteratorObject),
    2762             :         .tp_doc = "LDB search_iterator.",
    2763             :         .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE,
    2764             : };
    2765             : 
    2766           6 : static PyObject *py_ldb_module_repr(PyLdbModuleObject *self)
    2767             : {
    2768           6 :         return PyUnicode_FromFormat("<ldb module '%s'>",
    2769           6 :                 pyldb_Module_AsModule(self)->ops->name);
    2770             : }
    2771             : 
    2772           0 : static PyObject *py_ldb_module_str(PyLdbModuleObject *self)
    2773             : {
    2774           0 :         return PyUnicode_FromString(pyldb_Module_AsModule(self)->ops->name);
    2775             : }
    2776             : 
    2777           0 : static PyObject *py_ldb_module_start_transaction(PyLdbModuleObject *self,
    2778             :                 PyObject *Py_UNUSED(ignored))
    2779             : {
    2780           0 :         pyldb_Module_AsModule(self)->ops->start_transaction(pyldb_Module_AsModule(self));
    2781           0 :         Py_RETURN_NONE;
    2782             : }
    2783             : 
    2784           0 : static PyObject *py_ldb_module_end_transaction(PyLdbModuleObject *self,
    2785             :                 PyObject *Py_UNUSED(ignored))
    2786             : {
    2787           0 :         pyldb_Module_AsModule(self)->ops->end_transaction(pyldb_Module_AsModule(self));
    2788           0 :         Py_RETURN_NONE;
    2789             : }
    2790             : 
    2791           0 : static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self,
    2792             :                 PyObject *Py_UNUSED(ignored))
    2793             : {
    2794           0 :         pyldb_Module_AsModule(self)->ops->del_transaction(pyldb_Module_AsModule(self));
    2795           0 :         Py_RETURN_NONE;
    2796             : }
    2797             : 
    2798           2 : static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
    2799             : {
    2800             :         PyObject *py_base, *py_tree, *py_attrs, *py_ret;
    2801             :         int ret, scope;
    2802             :         struct ldb_request *req;
    2803           2 :         const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
    2804             :         struct ldb_module *mod;
    2805             :         const char * const*attrs;
    2806             : 
    2807             :         /* type "int" rather than "enum" for "scope" is intentional */
    2808           2 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O!iOO",
    2809             :                                          discard_const_p(char *, kwnames),
    2810             :                                          &PyLdbDn, &py_base, &scope, &py_tree, &py_attrs))
    2811           0 :                 return NULL;
    2812             : 
    2813           2 :         mod = self->mod;
    2814             : 
    2815           2 :         if (py_attrs == Py_None) {
    2816           0 :                 attrs = NULL;
    2817             :         } else {
    2818           2 :                 attrs = PyList_AsStrList(NULL, py_attrs, "attrs");
    2819           2 :                 if (attrs == NULL)
    2820           0 :                         return NULL;
    2821             :         }
    2822             : 
    2823           2 :         ret = ldb_build_search_req(&req, mod->ldb, NULL, pyldb_Dn_AS_DN(py_base),
    2824             :                              scope, NULL /* expr */, attrs,
    2825             :                              NULL /* controls */, NULL, NULL, NULL);
    2826             : 
    2827           2 :         talloc_steal(req, attrs);
    2828             : 
    2829           2 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
    2830             : 
    2831           2 :         req->op.search.res = NULL;
    2832             : 
    2833           2 :         ret = mod->ops->search(mod, req);
    2834             : 
    2835           2 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
    2836             : 
    2837           2 :         py_ret = PyLdbResult_FromResult(req->op.search.res);
    2838             : 
    2839           2 :         talloc_free(req);
    2840             : 
    2841           2 :         return py_ret;
    2842             : }
    2843             : 
    2844             : 
    2845           0 : static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
    2846             : {
    2847             :         struct ldb_request *req;
    2848             :         PyObject *py_message;
    2849             :         int ret;
    2850             :         struct ldb_module *mod;
    2851             : 
    2852           0 :         if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
    2853           0 :                 return NULL;
    2854             : 
    2855           0 :         req = talloc_zero(NULL, struct ldb_request);
    2856           0 :         req->operation = LDB_ADD;
    2857           0 :         req->op.add.message = pyldb_Message_AsMessage(py_message);
    2858             : 
    2859           0 :         mod = pyldb_Module_AsModule(self);
    2860           0 :         ret = mod->ops->add(mod, req);
    2861             : 
    2862           0 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
    2863             : 
    2864           0 :         Py_RETURN_NONE;
    2865             : }
    2866             : 
    2867           0 : static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args) 
    2868             : {
    2869             :         int ret;
    2870             :         struct ldb_request *req;
    2871             :         PyObject *py_message;
    2872             :         struct ldb_module *mod;
    2873             : 
    2874           0 :         if (!PyArg_ParseTuple(args, "O!", &PyLdbMessage, &py_message))
    2875           0 :                 return NULL;
    2876             : 
    2877           0 :         req = talloc_zero(NULL, struct ldb_request);
    2878           0 :         req->operation = LDB_MODIFY;
    2879           0 :         req->op.mod.message = pyldb_Message_AsMessage(py_message);
    2880             : 
    2881           0 :         mod = pyldb_Module_AsModule(self);
    2882           0 :         ret = mod->ops->modify(mod, req);
    2883             : 
    2884           0 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
    2885             : 
    2886           0 :         Py_RETURN_NONE;
    2887             : }
    2888             : 
    2889           0 : static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args) 
    2890             : {
    2891             :         int ret;
    2892             :         struct ldb_request *req;
    2893             :         PyObject *py_dn;
    2894             : 
    2895           0 :         if (!PyArg_ParseTuple(args, "O!", &PyLdbDn, &py_dn))
    2896           0 :                 return NULL;
    2897             : 
    2898           0 :         req = talloc_zero(NULL, struct ldb_request);
    2899           0 :         req->operation = LDB_DELETE;
    2900           0 :         req->op.del.dn = pyldb_Dn_AS_DN(py_dn);
    2901             : 
    2902           0 :         ret = pyldb_Module_AsModule(self)->ops->del(pyldb_Module_AsModule(self), req);
    2903             : 
    2904           0 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
    2905             : 
    2906           0 :         Py_RETURN_NONE;
    2907             : }
    2908             : 
    2909           0 : static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
    2910             : {
    2911             :         int ret;
    2912             :         struct ldb_request *req;
    2913             :         PyObject *py_dn1, *py_dn2;
    2914             : 
    2915           0 :         if (!PyArg_ParseTuple(args, "O!O!", &PyLdbDn, &py_dn1, &PyLdbDn, &py_dn2))
    2916           0 :                 return NULL;
    2917             : 
    2918           0 :         req = talloc_zero(NULL, struct ldb_request);
    2919             : 
    2920           0 :         req->operation = LDB_RENAME;
    2921           0 :         req->op.rename.olddn = pyldb_Dn_AS_DN(py_dn1);
    2922           0 :         req->op.rename.newdn = pyldb_Dn_AS_DN(py_dn2);
    2923             : 
    2924           0 :         ret = pyldb_Module_AsModule(self)->ops->rename(pyldb_Module_AsModule(self), req);
    2925             : 
    2926           0 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
    2927             : 
    2928           0 :         Py_RETURN_NONE;
    2929             : }
    2930             : 
    2931             : static PyMethodDef py_ldb_module_methods[] = {
    2932             :         { "search", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_module_search),
    2933             :                 METH_VARARGS|METH_KEYWORDS, NULL },
    2934             :         { "add", (PyCFunction)py_ldb_module_add, METH_VARARGS, NULL },
    2935             :         { "modify", (PyCFunction)py_ldb_module_modify, METH_VARARGS, NULL },
    2936             :         { "rename", (PyCFunction)py_ldb_module_rename, METH_VARARGS, NULL },
    2937             :         { "delete", (PyCFunction)py_ldb_module_delete, METH_VARARGS, NULL },
    2938             :         { "start_transaction", (PyCFunction)py_ldb_module_start_transaction, METH_NOARGS, NULL },
    2939             :         { "end_transaction", (PyCFunction)py_ldb_module_end_transaction, METH_NOARGS, NULL },
    2940             :         { "del_transaction", (PyCFunction)py_ldb_module_del_transaction, METH_NOARGS, NULL },
    2941             :         {0},
    2942             : };
    2943             : 
    2944           6 : static void py_ldb_module_dealloc(PyLdbModuleObject *self)
    2945             : {
    2946           6 :         talloc_free(self->mem_ctx);
    2947           6 :         PyObject_Del(self);
    2948           6 : }
    2949             : 
    2950             : static PyTypeObject PyLdbModule = {
    2951             :         .tp_name = "ldb.LdbModule",
    2952             :         .tp_methods = py_ldb_module_methods,
    2953             :         .tp_repr = (reprfunc)py_ldb_module_repr,
    2954             :         .tp_str = (reprfunc)py_ldb_module_str,
    2955             :         .tp_basicsize = sizeof(PyLdbModuleObject),
    2956             :         .tp_dealloc = (destructor)py_ldb_module_dealloc,
    2957             :         .tp_flags = Py_TPFLAGS_DEFAULT,
    2958             :         .tp_doc = "LDB module (extension)",
    2959             : };
    2960             : 
    2961             : 
    2962             : /**
    2963             :  * Create a ldb_message_element from a Python object.
    2964             :  *
    2965             :  * This will accept any sequence objects that contains strings, or 
    2966             :  * a string object.
    2967             :  *
    2968             :  * A reference to set_obj will be borrowed. 
    2969             :  *
    2970             :  * @param mem_ctx Memory context
    2971             :  * @param set_obj Python object to convert
    2972             :  * @param flags ldb_message_element flags to set
    2973             :  * @param attr_name Name of the attribute
    2974             :  * @return New ldb_message_element, allocated as child of mem_ctx
    2975             :  */
    2976      724199 : static struct ldb_message_element *PyObject_AsMessageElement(
    2977             :                                                       TALLOC_CTX *mem_ctx,
    2978             :                                                       PyObject *set_obj,
    2979             :                                                       unsigned int flags,
    2980             :                                                       const char *attr_name)
    2981             : {
    2982             :         struct ldb_message_element *me;
    2983      724199 :         const char *msg = NULL;
    2984             :         Py_ssize_t size;
    2985             :         int result;
    2986             : 
    2987      724199 :         if (pyldb_MessageElement_Check(set_obj)) {
    2988      268132 :                 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj;
    2989             :                 /* We have to talloc_reference() the memory context, not the pointer
    2990             :                  * which may not actually be it's own context */
    2991      268132 :                 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) {
    2992      268132 :                         return pyldb_MessageElement_AsMessageElement(set_obj);
    2993             :                 }
    2994           0 :                 return NULL;
    2995             :         }
    2996             : 
    2997      456067 :         me = talloc(mem_ctx, struct ldb_message_element);
    2998      456067 :         if (me == NULL) {
    2999           0 :                 PyErr_NoMemory();
    3000           0 :                 return NULL;
    3001             :         }
    3002             : 
    3003      456067 :         me->name = talloc_strdup(me, attr_name);
    3004      456067 :         me->flags = flags;
    3005      456067 :         if (PyBytes_Check(set_obj) || PyUnicode_Check(set_obj)) {
    3006      442153 :                 me->num_values = 1;
    3007      442153 :                 me->values = talloc_array(me, struct ldb_val, me->num_values);
    3008      442153 :                 if (PyBytes_Check(set_obj)) {
    3009      184220 :                         char *_msg = NULL;
    3010      184220 :                         result = PyBytes_AsStringAndSize(set_obj, &_msg, &size);
    3011      184220 :                         if (result != 0) {
    3012           0 :                                 talloc_free(me);
    3013           0 :                                 return NULL;
    3014             :                         }
    3015      184220 :                         msg = _msg;
    3016             :                 } else {
    3017      257933 :                         msg = PyUnicode_AsUTF8AndSize(set_obj, &size);
    3018      257933 :                         if (msg == NULL) {
    3019           0 :                                 talloc_free(me);
    3020           0 :                                 return NULL;
    3021             :                         }
    3022             :                 }
    3023      442153 :                 me->values[0].data = talloc_memdup(me,
    3024             :                                                    (const uint8_t *)msg,
    3025             :                                                    size+1);
    3026      442153 :                 me->values[0].length = size;
    3027       13914 :         } else if (PySequence_Check(set_obj)) {
    3028             :                 Py_ssize_t i;
    3029       13914 :                 me->num_values = PySequence_Size(set_obj);
    3030       13914 :                 me->values = talloc_array(me, struct ldb_val, me->num_values);
    3031       42538 :                 for (i = 0; i < me->num_values; i++) {
    3032       28624 :                         PyObject *obj = PySequence_GetItem(set_obj, i);
    3033       28624 :                         if (PyBytes_Check(obj)) {
    3034       12587 :                                 char *_msg = NULL;
    3035       12587 :                                 result = PyBytes_AsStringAndSize(obj, &_msg, &size);
    3036       12587 :                                 if (result != 0) {
    3037           0 :                                         talloc_free(me);
    3038           0 :                                         return NULL;
    3039             :                                 }
    3040       12587 :                                 msg = _msg;
    3041       16037 :                         } else if (PyUnicode_Check(obj)) {
    3042       16037 :                                 msg = PyUnicode_AsUTF8AndSize(obj, &size);
    3043       16037 :                                 if (msg == NULL) {
    3044           0 :                                         talloc_free(me);
    3045           0 :                                         return NULL;
    3046             :                                 }
    3047             :                         } else {
    3048           0 :                                 PyErr_Format(PyExc_TypeError,
    3049             :                                              "Expected string as element %zd in list", i);
    3050           0 :                                 talloc_free(me);
    3051           0 :                                 return NULL;
    3052             :                         }
    3053       28624 :                         me->values[i].data = talloc_memdup(me,
    3054             :                                                            (const uint8_t *)msg,
    3055             :                                                            size+1);
    3056       28624 :                         me->values[i].length = size;
    3057             :                 }
    3058             :         } else {
    3059           0 :                 PyErr_Format(PyExc_TypeError,
    3060             :                              "String or List type expected for '%s' attribute", attr_name);
    3061           0 :                 talloc_free(me);
    3062           0 :                 me = NULL;
    3063             :         }
    3064             : 
    3065      456067 :         return me;
    3066             : }
    3067             : 
    3068             : 
    3069    16355070 : static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx,
    3070             :                                         struct ldb_message_element *me)
    3071             : {
    3072             :         Py_ssize_t i;
    3073             :         PyObject *result;
    3074             : 
    3075             :         /* Python << 2.5 doesn't have PySet_New and PySet_Add. */
    3076    16355070 :         result = PyList_New(me->num_values);
    3077             : 
    3078    37457885 :         for (i = 0; i < me->num_values; i++) {
    3079    21102815 :                 PyList_SetItem(result, i,
    3080    21102815 :                         PyObject_FromLdbValue(&me->values[i]));
    3081             :         }
    3082             : 
    3083    16355070 :         return result;
    3084             : }
    3085             : 
    3086           0 : static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args)
    3087             : {
    3088             :         unsigned int i;
    3089           0 :         if (!PyArg_ParseTuple(args, "I", &i))
    3090           0 :                 return NULL;
    3091           0 :         if (i >= pyldb_MessageElement_AsMessageElement(self)->num_values)
    3092           0 :                 Py_RETURN_NONE;
    3093             : 
    3094           0 :         return PyObject_FromLdbValue(&(pyldb_MessageElement_AsMessageElement(self)->values[i]));
    3095             : }
    3096             : 
    3097          38 : static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
    3098             : {
    3099          38 :         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
    3100          38 :         return PyLong_FromLong(el->flags);
    3101             : }
    3102             : 
    3103        4059 : static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
    3104             : {
    3105             :         unsigned int flags;
    3106             :         struct ldb_message_element *el;
    3107        4059 :         if (!PyArg_ParseTuple(args, "I", &flags))
    3108           0 :                 return NULL;
    3109             : 
    3110        4059 :         el = pyldb_MessageElement_AsMessageElement(self);
    3111        4059 :         el->flags = flags;
    3112        4059 :         Py_RETURN_NONE;
    3113             : }
    3114             : 
    3115             : static PyMethodDef py_ldb_msg_element_methods[] = {
    3116             :         { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
    3117             :         { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
    3118             :         { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
    3119             :         {0},
    3120             : };
    3121             : 
    3122    17801943 : static Py_ssize_t py_ldb_msg_element_len(PyLdbMessageElementObject *self)
    3123             : {
    3124    17801943 :         return pyldb_MessageElement_AsMessageElement(self)->num_values;
    3125             : }
    3126             : 
    3127    12188923 : static PyObject *py_ldb_msg_element_find(PyLdbMessageElementObject *self, Py_ssize_t idx)
    3128             : {
    3129    12188923 :         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
    3130    12188923 :         if (idx < 0 || idx >= el->num_values) {
    3131           4 :                 PyErr_SetString(PyExc_IndexError, "Out of range");
    3132           4 :                 return NULL;
    3133             :         }
    3134    12188919 :         return PyLdbBytes_FromStringAndSize((char *)el->values[idx].data, el->values[idx].length);
    3135             : }
    3136             : 
    3137             : static PySequenceMethods py_ldb_msg_element_seq = {
    3138             :         .sq_length = (lenfunc)py_ldb_msg_element_len,
    3139             :         .sq_item = (ssizeargfunc)py_ldb_msg_element_find,
    3140             : };
    3141             : 
    3142         200 : static PyObject *py_ldb_msg_element_richcmp(PyObject *self, PyObject *other, int op)
    3143             : {
    3144             :         int ret;
    3145         200 :         if (!pyldb_MessageElement_Check(other)) {
    3146          63 :                 Py_INCREF(Py_NotImplemented);
    3147          63 :                 return Py_NotImplemented;
    3148             :         }
    3149         137 :         ret = ldb_msg_element_compare(pyldb_MessageElement_AsMessageElement(self),
    3150             :                                                                           pyldb_MessageElement_AsMessageElement(other));
    3151         137 :         return richcmp(ret, op);
    3152             : }
    3153             : 
    3154    16355070 : static PyObject *py_ldb_msg_element_iter(PyLdbMessageElementObject *self)
    3155             : {
    3156    16355070 :         PyObject *el = ldb_msg_element_to_set(NULL,
    3157             :                                               pyldb_MessageElement_AsMessageElement(self));
    3158    16355070 :         PyObject *ret = PyObject_GetIter(el);
    3159    16355070 :         Py_DECREF(el);
    3160    16355070 :         return ret;
    3161             : }
    3162             : 
    3163    27723301 : static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)
    3164             : {
    3165             :         PyLdbMessageElementObject *ret;
    3166    27723301 :         ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement);
    3167    27723301 :         if (ret == NULL) {
    3168           0 :                 PyErr_NoMemory();
    3169           0 :                 return NULL;
    3170             :         }
    3171    27723301 :         ret->mem_ctx = talloc_new(NULL);
    3172    27723301 :         if (talloc_reference(ret->mem_ctx, mem_ctx) == NULL) {
    3173           0 :                 PyErr_NoMemory();
    3174           0 :                 return NULL;
    3175             :         }
    3176    27723301 :         ret->el = el;
    3177    27723301 :         return (PyObject *)ret;
    3178             : }
    3179             : 
    3180      264514 : static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    3181             : {
    3182      264514 :         PyObject *py_elements = NULL;
    3183             :         struct ldb_message_element *el;
    3184      264514 :         unsigned int flags = 0;
    3185      264514 :         char *name = NULL;
    3186      264514 :         const char * const kwnames[] = { "elements", "flags", "name", NULL };
    3187             :         PyLdbMessageElementObject *ret;
    3188             :         TALLOC_CTX *mem_ctx;
    3189      264514 :         const char *msg = NULL;
    3190             :         Py_ssize_t size;
    3191             :         int result;
    3192             : 
    3193      264514 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OIs",
    3194             :                                          discard_const_p(char *, kwnames),
    3195             :                                          &py_elements, &flags, &name))
    3196           0 :                 return NULL;
    3197             : 
    3198      264514 :         mem_ctx = talloc_new(NULL);
    3199      264514 :         if (mem_ctx == NULL) {
    3200           0 :                 PyErr_NoMemory();
    3201           0 :                 return NULL;
    3202             :         }
    3203             : 
    3204      264514 :         el = talloc_zero(mem_ctx, struct ldb_message_element);
    3205      264514 :         if (el == NULL) {
    3206           0 :                 PyErr_NoMemory();
    3207           0 :                 talloc_free(mem_ctx);
    3208           0 :                 return NULL;
    3209             :         }
    3210             : 
    3211      264514 :         if (py_elements != NULL) {
    3212             :                 Py_ssize_t i;
    3213      503615 :                 if (PyBytes_Check(py_elements) || PyUnicode_Check(py_elements)) {
    3214      256140 :                         char *_msg = NULL;
    3215      256140 :                         el->num_values = 1;
    3216      256140 :                         el->values = talloc_array(el, struct ldb_val, 1);
    3217      256140 :                         if (el->values == NULL) {
    3218           0 :                                 talloc_free(mem_ctx);
    3219           0 :                                 PyErr_NoMemory();
    3220           0 :                                 return NULL;
    3221             :                         }
    3222      256140 :                         if (PyBytes_Check(py_elements)) {
    3223       61919 :                                 result = PyBytes_AsStringAndSize(py_elements, &_msg, &size);
    3224       61919 :                                 msg = _msg;
    3225             :                         } else {
    3226      194221 :                                 msg = PyUnicode_AsUTF8AndSize(py_elements, &size);
    3227      194221 :                                 result = (msg == NULL) ? -1 : 0;
    3228             :                         }
    3229      256140 :                         if (result != 0) {
    3230           0 :                                 talloc_free(mem_ctx);
    3231           0 :                                 return NULL;
    3232             :                         }
    3233      256140 :                         el->values[0].data = talloc_memdup(el->values, 
    3234             :                                 (const uint8_t *)msg, size + 1);
    3235      256140 :                         el->values[0].length = size;
    3236        8374 :                 } else if (PySequence_Check(py_elements)) {
    3237        8374 :                         el->num_values = PySequence_Size(py_elements);
    3238        8374 :                         el->values = talloc_array(el, struct ldb_val, el->num_values);
    3239        8374 :                         if (el->values == NULL) {
    3240           0 :                                 talloc_free(mem_ctx);
    3241           0 :                                 PyErr_NoMemory();
    3242           0 :                                 return NULL;
    3243             :                         }
    3244       22869 :                         for (i = 0; i < el->num_values; i++) {
    3245       14495 :                                 PyObject *item = PySequence_GetItem(py_elements, i);
    3246       14495 :                                 if (item == NULL) {
    3247           0 :                                         talloc_free(mem_ctx);
    3248           0 :                                         return NULL;
    3249             :                                 }
    3250       14495 :                                 if (PyBytes_Check(item)) {
    3251        6325 :                                         char *_msg = NULL;
    3252        6325 :                                         result = PyBytes_AsStringAndSize(item, &_msg, &size);
    3253        6325 :                                         msg = _msg;
    3254        8170 :                                 } else if (PyUnicode_Check(item)) {
    3255        8170 :                                         msg = PyUnicode_AsUTF8AndSize(item, &size);
    3256        8170 :                                         result = (msg == NULL) ? -1 : 0;
    3257             :                                 } else {
    3258           0 :                                         PyErr_Format(PyExc_TypeError, 
    3259             :                                                      "Expected string as element %zd in list", i);
    3260           0 :                                         result = -1;
    3261             :                                 }
    3262       14495 :                                 if (result != 0) {
    3263           0 :                                         talloc_free(mem_ctx);
    3264           0 :                                         return NULL;
    3265             :                                 }
    3266       14495 :                                 el->values[i].data = talloc_memdup(el,
    3267             :                                         (const uint8_t *)msg, size+1);
    3268       14495 :                                 el->values[i].length = size;
    3269             :                         }
    3270             :                 } else {
    3271           0 :                         PyErr_SetString(PyExc_TypeError, 
    3272             :                                         "Expected string or list");
    3273           0 :                         talloc_free(mem_ctx);
    3274           0 :                         return NULL;
    3275             :                 }
    3276             :         }
    3277             : 
    3278      264514 :         el->flags = flags;
    3279      264514 :         el->name = talloc_strdup(el, name);
    3280             : 
    3281      264514 :         ret = PyObject_New(PyLdbMessageElementObject, type);
    3282      264514 :         if (ret == NULL) {
    3283           0 :                 talloc_free(mem_ctx);
    3284           0 :                 return NULL;
    3285             :         }
    3286             : 
    3287      264514 :         ret->mem_ctx = mem_ctx;
    3288      264514 :         ret->el = el;
    3289      264514 :         return (PyObject *)ret;
    3290             : }
    3291             : 
    3292       57171 : static PyObject *py_ldb_msg_element_repr(PyLdbMessageElementObject *self)
    3293             : {
    3294       57171 :         char *element_str = NULL;
    3295             :         Py_ssize_t i;
    3296       57171 :         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
    3297             :         PyObject *ret, *repr;
    3298             : 
    3299      114364 :         for (i = 0; i < el->num_values; i++) {
    3300       57193 :                 PyObject *o = py_ldb_msg_element_find(self, i);
    3301       57193 :                 repr = PyObject_Repr(o);
    3302       57193 :                 if (element_str == NULL)
    3303       57171 :                         element_str = talloc_strdup(NULL, PyUnicode_AsUTF8(repr));
    3304             :                 else
    3305          22 :                         element_str = talloc_asprintf_append(element_str, ",%s", PyUnicode_AsUTF8(repr));
    3306       57193 :                 Py_DECREF(repr);
    3307             :         }
    3308             : 
    3309       57171 :         if (element_str != NULL) {
    3310       57171 :                 ret = PyUnicode_FromFormat("MessageElement([%s])", element_str);
    3311       57171 :                 talloc_free(element_str);
    3312             :         } else {
    3313           0 :                 ret = PyUnicode_FromString("MessageElement([])");
    3314             :         }
    3315             : 
    3316       57171 :         return ret;
    3317             : }
    3318             : 
    3319       52498 : static PyObject *py_ldb_msg_element_str(PyLdbMessageElementObject *self)
    3320             : {
    3321       52498 :         struct ldb_message_element *el = pyldb_MessageElement_AsMessageElement(self);
    3322             : 
    3323       52498 :         if (el->num_values == 1)
    3324       52498 :                 return PyUnicode_FromStringAndSize((char *)el->values[0].data, el->values[0].length);
    3325             :         else
    3326           0 :                 Py_RETURN_NONE;
    3327             : }
    3328             : 
    3329    34498203 : static void py_ldb_msg_element_dealloc(PyLdbMessageElementObject *self)
    3330             : {
    3331    34498203 :         talloc_free(self->mem_ctx);
    3332    34498203 :         PyObject_Del(self);
    3333    34498203 : }
    3334             : 
    3335          18 : static PyObject *py_ldb_msg_element_get_text(PyObject *self, void *closure)
    3336             : {
    3337          18 :         return wrap_text("MessageElementTextWrapper", self);
    3338             : }
    3339             : 
    3340             : static PyGetSetDef py_ldb_msg_element_getset[] = {
    3341             :         {
    3342             :                 .name = discard_const_p(char, "text"),
    3343             :                 .get  = (getter)py_ldb_msg_element_get_text,
    3344             :         },
    3345             :         { .name = NULL }
    3346             : };
    3347             : 
    3348             : static PyTypeObject PyLdbMessageElement = {
    3349             :         .tp_name = "ldb.MessageElement",
    3350             :         .tp_basicsize = sizeof(PyLdbMessageElementObject),
    3351             :         .tp_dealloc = (destructor)py_ldb_msg_element_dealloc,
    3352             :         .tp_repr = (reprfunc)py_ldb_msg_element_repr,
    3353             :         .tp_str = (reprfunc)py_ldb_msg_element_str,
    3354             :         .tp_methods = py_ldb_msg_element_methods,
    3355             :         .tp_getset = py_ldb_msg_element_getset,
    3356             :         .tp_richcompare = (richcmpfunc)py_ldb_msg_element_richcmp,
    3357             :         .tp_iter = (getiterfunc)py_ldb_msg_element_iter,
    3358             :         .tp_as_sequence = &py_ldb_msg_element_seq,
    3359             :         .tp_new = py_ldb_msg_element_new,
    3360             :         .tp_flags = Py_TPFLAGS_DEFAULT,
    3361             :         .tp_doc = "An element of a Message",
    3362             : };
    3363             : 
    3364             : 
    3365        1995 : static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args)
    3366             : {
    3367             :         PyObject *py_ldb;
    3368             :         PyObject *py_dict;
    3369             :         PyObject *py_ret;
    3370             :         struct ldb_message *msg;
    3371             :         struct ldb_context *ldb_ctx;
    3372        1995 :         unsigned int mod_flags = LDB_FLAG_MOD_REPLACE;
    3373             : 
    3374        1995 :         if (!PyArg_ParseTuple(args, "O!O!|I",
    3375             :                               &PyLdb, &py_ldb, &PyDict_Type, &py_dict,
    3376             :                               &mod_flags)) {
    3377           8 :                 return NULL;
    3378             :         }
    3379             : 
    3380        1987 :         if (!PyLdb_Check(py_ldb)) {
    3381           0 :                 PyErr_SetString(PyExc_TypeError, "Expected Ldb");
    3382           0 :                 return NULL;
    3383             :         }
    3384             : 
    3385             :         /* mask only flags we are going to use */
    3386        1987 :         mod_flags = LDB_FLAG_MOD_TYPE(mod_flags);
    3387        1987 :         if (!mod_flags) {
    3388           4 :                 PyErr_SetString(PyExc_ValueError,
    3389             :                                 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE"
    3390             :                                 " expected as mod_flag value");
    3391           4 :                 return NULL;
    3392             :         }
    3393             : 
    3394        1983 :         ldb_ctx = pyldb_Ldb_AS_LDBCONTEXT(py_ldb);
    3395             : 
    3396        1983 :         msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags);
    3397        1983 :         if (!msg) {
    3398           4 :                 return NULL;
    3399             :         }
    3400             : 
    3401        1979 :         py_ret = PyLdbMessage_FromMessage(msg);
    3402             : 
    3403        1979 :         talloc_unlink(ldb_ctx, msg);
    3404             : 
    3405        1979 :         return py_ret;
    3406             : }
    3407             : 
    3408      751673 : static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args)
    3409             : {
    3410             :         char *name;
    3411      751673 :         if (!PyArg_ParseTuple(args, "s", &name))
    3412           0 :                 return NULL;
    3413             : 
    3414      751673 :         ldb_msg_remove_attr(self->msg, name);
    3415             : 
    3416      751673 :         Py_RETURN_NONE;
    3417             : }
    3418             : 
    3419     1904668 : static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self,
    3420             :                 PyObject *Py_UNUSED(ignored))
    3421             : {
    3422     1904668 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3423     1904668 :         Py_ssize_t i, j = 0;
    3424     1904668 :         PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0));
    3425     1904668 :         if (msg->dn != NULL) {
    3426     1904667 :                 PyList_SetItem(obj, j, PyUnicode_FromString("dn"));
    3427     1904667 :                 j++;
    3428             :         }
    3429    20298563 :         for (i = 0; i < msg->num_elements; i++) {
    3430    18393895 :                 PyList_SetItem(obj, j, PyUnicode_FromString(msg->elements[i].name));
    3431    18393895 :                 j++;
    3432             :         }
    3433     1904668 :         return obj;
    3434             : }
    3435             : 
    3436     1435282 : static int py_ldb_msg_contains(PyLdbMessageObject *self, PyObject *py_name)
    3437             : {
    3438     1435282 :         struct ldb_message_element *el = NULL;
    3439     1435282 :         const char *name = NULL;
    3440     1435282 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3441     1435282 :         name = PyUnicode_AsUTF8(py_name);
    3442     1435282 :         if (name == NULL) {
    3443           2 :                 return -1;
    3444             :         }
    3445     1435280 :         if (!ldb_attr_cmp(name, "dn")) {
    3446          22 :                 return 1;
    3447             :         }
    3448     1435258 :         el = ldb_msg_find_element(msg, name);
    3449     1435258 :         return el != NULL ? 1 : 0;
    3450             : }
    3451             : 
    3452    28205910 : static PyObject *py_ldb_msg_getitem(PyLdbMessageObject *self, PyObject *py_name)
    3453             : {
    3454    28205910 :         struct ldb_message_element *el = NULL;
    3455    28205910 :         const char *name = NULL;
    3456    28205910 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3457    28205910 :         name = PyUnicode_AsUTF8(py_name);
    3458    28205910 :         if (name == NULL) {
    3459           2 :                 return NULL;
    3460             :         }
    3461    28205908 :         if (!ldb_attr_cmp(name, "dn")) {
    3462      541464 :                 return pyldb_Dn_FromDn(msg->dn);
    3463             :         }
    3464    27664444 :         el = ldb_msg_find_element(msg, name);
    3465    27664444 :         if (el == NULL) {
    3466         611 :                 PyErr_SetString(PyExc_KeyError, "No such element");
    3467         611 :                 return NULL;
    3468             :         }
    3469             : 
    3470    27663833 :         return PyLdbMessageElement_FromMessageElement(el, msg->elements);
    3471             : }
    3472             : 
    3473       72320 : static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args, PyObject *kwargs)
    3474             : {
    3475       72320 :         PyObject *def = NULL;
    3476       72320 :         const char *kwnames[] = { "name", "default", "idx", NULL };
    3477       72320 :         const char *name = NULL;
    3478       72320 :         int idx = -1;
    3479       72320 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3480             :         struct ldb_message_element *el;
    3481             : 
    3482       72320 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|Oi:msg",
    3483             :                                          discard_const_p(char *, kwnames), &name, &def, &idx)) {
    3484           2 :                 return NULL;
    3485             :         }
    3486             : 
    3487       72318 :         if (strcasecmp(name, "dn") == 0) {
    3488         567 :                 return pyldb_Dn_FromDn(msg->dn);
    3489             :         }
    3490             : 
    3491       71751 :         el = ldb_msg_find_element(msg, name);
    3492             : 
    3493       71751 :         if (el == NULL || (idx != -1 && el->num_values <= idx)) {
    3494       10994 :                 if (def != NULL) {
    3495         158 :                         Py_INCREF(def);
    3496         158 :                         return def;
    3497             :                 }
    3498       10836 :                 Py_RETURN_NONE;
    3499             :         }
    3500             : 
    3501       60757 :         if (idx == -1) {
    3502       59456 :                 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements);
    3503             :         }
    3504             : 
    3505        1301 :         return PyObject_FromLdbValue(&el->values[idx]);
    3506             : }
    3507             : 
    3508           8 : static PyObject *py_ldb_msg_items(PyLdbMessageObject *self,
    3509             :                 PyObject *Py_UNUSED(ignored))
    3510             : {
    3511           8 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3512           8 :         Py_ssize_t i, j = 0;
    3513           8 :         PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1));
    3514           8 :         if (l == NULL) {
    3515           0 :                 return PyErr_NoMemory();
    3516             :         }
    3517           8 :         if (msg->dn != NULL) {
    3518           4 :                 PyObject *value = NULL;
    3519           4 :                 PyObject *obj = pyldb_Dn_FromDn(msg->dn);
    3520           4 :                 int res = 0;
    3521           4 :                 value = Py_BuildValue("(sO)", "dn", obj);
    3522           4 :                 Py_CLEAR(obj);
    3523           4 :                 if (value == NULL) {
    3524           0 :                         Py_CLEAR(l);
    3525           0 :                         return NULL;
    3526             :                 }
    3527           4 :                 res = PyList_SetItem(l, 0, value);
    3528           4 :                 if (res == -1) {
    3529           0 :                         Py_CLEAR(l);
    3530           0 :                         return NULL;
    3531             :                 }
    3532           4 :                 j++;
    3533             :         }
    3534          16 :         for (i = 0; i < msg->num_elements; i++, j++) {
    3535           8 :                 PyObject *value = NULL;
    3536           8 :                 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements);
    3537           8 :                 int res = 0;
    3538           8 :                 value = Py_BuildValue("(sO)", msg->elements[i].name, py_el);
    3539           8 :                 Py_CLEAR(py_el);
    3540           8 :                 if (value == NULL ) {
    3541           0 :                         Py_CLEAR(l);
    3542           0 :                         return NULL;
    3543             :                 }
    3544           8 :                 res = PyList_SetItem(l, j, value);
    3545           8 :                 if (res == -1) {
    3546           0 :                         Py_CLEAR(l);
    3547           0 :                         return NULL;
    3548             :                 }
    3549             :         }
    3550           8 :         return l;
    3551             : }
    3552             : 
    3553           6 : static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self,
    3554             :                 PyObject *Py_UNUSED(ignored))
    3555             : {
    3556           6 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3557           6 :         Py_ssize_t i = 0;
    3558           6 :         PyObject *l = PyList_New(msg->num_elements);
    3559          10 :         for (i = 0; i < msg->num_elements; i++) {
    3560           4 :                 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements));
    3561             :         }
    3562           6 :         return l;
    3563             : }
    3564             : 
    3565         570 : static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args)
    3566             : {
    3567         570 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3568             :         PyLdbMessageElementObject *py_element;
    3569             :         int i, ret;
    3570             :         struct ldb_message_element *el;
    3571             :         struct ldb_message_element *el_new;
    3572             : 
    3573         570 :         if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element))
    3574           0 :                 return NULL;
    3575             : 
    3576         570 :         el = py_element->el;
    3577         570 :         if (el == NULL) {
    3578           0 :                 PyErr_SetString(PyExc_ValueError, "Invalid MessageElement object");
    3579           0 :                 return NULL;
    3580             :         }
    3581         570 :         if (el->name == NULL) {
    3582           0 :                 PyErr_SetString(PyExc_ValueError,
    3583             :                                 "The element has no name");
    3584           0 :                 return NULL;
    3585             :         }
    3586         570 :         ret = ldb_msg_add_empty(msg, el->name, el->flags, &el_new);
    3587         570 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
    3588             : 
    3589             :         /* now deep copy all attribute values */
    3590         570 :         el_new->values = talloc_array(msg->elements, struct ldb_val, el->num_values);
    3591         570 :         if (el_new->values == NULL) {
    3592           0 :                 PyErr_NoMemory();
    3593           0 :                 return NULL;
    3594             :         }
    3595         570 :         el_new->num_values = el->num_values;
    3596             : 
    3597         995 :         for (i = 0; i < el->num_values; i++) {
    3598         425 :                 el_new->values[i] = ldb_val_dup(el_new->values, &el->values[i]);
    3599         425 :                 if (el_new->values[i].data == NULL
    3600           0 :                                 && el->values[i].length != 0) {
    3601           0 :                         PyErr_NoMemory();
    3602           0 :                         return NULL;
    3603             :                 }
    3604             :         }
    3605             : 
    3606         570 :         Py_RETURN_NONE;
    3607             : }
    3608             : 
    3609             : static PyMethodDef py_ldb_msg_methods[] = {
    3610             :         { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS,
    3611             :                 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n"
    3612             :                 "Class method to create ldb.Message object from Dictionary.\n"
    3613             :                 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."},
    3614             :         { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS,
    3615             :                 "S.keys() -> list\n\n"
    3616             :                 "Return sequence of all attribute names." },
    3617             :         { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, 
    3618             :                 "S.remove(name)\n\n"
    3619             :                 "Remove all entries for attributes with the specified name."},
    3620             :         { "get", PY_DISCARD_FUNC_SIG(PyCFunction, py_ldb_msg_get),
    3621             :                 METH_VARARGS | METH_KEYWORDS,
    3622             :           "msg.get(name,default=None,idx=None) -> string\n"
    3623             :           "idx is the index into the values array\n"
    3624             :           "if idx is None, then a list is returned\n"
    3625             :           "if idx is not None, then the element with that index is returned\n"
    3626             :           "if you pass the special name 'dn' then the DN object is returned\n"},
    3627             :         { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL },
    3628             :         { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL },
    3629             :         { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS,
    3630             :                 "S.add(element)\n\n"
    3631             :                 "Add an element to this message." },
    3632             :         {0},
    3633             : };
    3634             : 
    3635     1620243 : static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
    3636             : {
    3637             :         PyObject *list, *iter;
    3638             : 
    3639     1620243 :         list = py_ldb_msg_keys(self, NULL);
    3640     1620243 :         iter = PyObject_GetIter(list);
    3641     1620243 :         Py_DECREF(list);
    3642     1620243 :         return iter;
    3643             : }
    3644             : 
    3645      276118 : static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
    3646             : {
    3647             :         const char *attr_name;
    3648             : 
    3649      276118 :         attr_name = PyUnicode_AsUTF8(name);
    3650      276118 :         if (attr_name == NULL) {
    3651           0 :                 PyErr_SetNone(PyExc_TypeError);
    3652           0 :                 return -1;
    3653             :         }
    3654             : 
    3655      276118 :         if (value == NULL) {
    3656             :                 /* delitem */
    3657         356 :                 ldb_msg_remove_attr(self->msg, attr_name);
    3658             :         } else {
    3659             :                 int ret;
    3660      275762 :                 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
    3661             :                                                                            value, 0, attr_name);
    3662      275762 :                 if (el == NULL) {
    3663           0 :                         return -1;
    3664             :                 }
    3665      275762 :                 ldb_msg_remove_attr(pyldb_Message_AsMessage(self), attr_name);
    3666      275762 :                 ret = ldb_msg_add(pyldb_Message_AsMessage(self), el, el->flags);
    3667      275762 :                 if (ret != LDB_SUCCESS) {
    3668           0 :                         PyErr_SetLdbError(PyExc_LdbError, ret, NULL);
    3669           0 :                         return -1;
    3670             :                 }
    3671             :         }
    3672      276118 :         return 0;
    3673             : }
    3674             : 
    3675       33216 : static Py_ssize_t py_ldb_msg_length(PyLdbMessageObject *self)
    3676             : {
    3677       33216 :         return pyldb_Message_AsMessage(self)->num_elements;
    3678             : }
    3679             : 
    3680             : static PySequenceMethods py_ldb_msg_sequence = {
    3681             :         .sq_contains = (objobjproc)py_ldb_msg_contains,
    3682             : };
    3683             : 
    3684             : static PyMappingMethods py_ldb_msg_mapping = {
    3685             :         .mp_length = (lenfunc)py_ldb_msg_length,
    3686             :         .mp_subscript = (binaryfunc)py_ldb_msg_getitem,
    3687             :         .mp_ass_subscript = (objobjargproc)py_ldb_msg_setitem,
    3688             : };
    3689             : 
    3690      168106 : static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
    3691             : {
    3692      168106 :         const char * const kwnames[] = { "dn", NULL };
    3693             :         struct ldb_message *ret;
    3694             :         TALLOC_CTX *mem_ctx;
    3695      168106 :         PyObject *pydn = NULL;
    3696             :         PyLdbMessageObject *py_ret;
    3697             : 
    3698      168106 :         if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|O",
    3699             :                                          discard_const_p(char *, kwnames),
    3700             :                                          &pydn))
    3701           0 :                 return NULL;
    3702             : 
    3703      168106 :         mem_ctx = talloc_new(NULL);
    3704      168106 :         if (mem_ctx == NULL) {
    3705           0 :                 PyErr_NoMemory();
    3706           0 :                 return NULL;
    3707             :         }
    3708             : 
    3709      168106 :         ret = ldb_msg_new(mem_ctx);
    3710      168106 :         if (ret == NULL) {
    3711           0 :                 talloc_free(mem_ctx);
    3712           0 :                 PyErr_NoMemory();
    3713           0 :                 return NULL;
    3714             :         }
    3715             : 
    3716      168106 :         if (pydn != NULL) {
    3717             :                 struct ldb_dn *dn;
    3718        5561 :                 if (!pyldb_Object_AsDn(NULL, pydn, NULL, &dn)) {
    3719           0 :                         talloc_free(mem_ctx);
    3720           0 :                         return NULL;
    3721             :                 }
    3722        5561 :                 ret->dn = talloc_reference(ret, dn);
    3723             :         }
    3724             : 
    3725      168106 :         py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
    3726      168106 :         if (py_ret == NULL) {
    3727           0 :                 PyErr_NoMemory();
    3728           0 :                 talloc_free(mem_ctx);
    3729           0 :                 return NULL;
    3730             :         }
    3731             : 
    3732      168106 :         py_ret->mem_ctx = mem_ctx;
    3733      168106 :         py_ret->msg = ret;
    3734      168106 :         return (PyObject *)py_ret;
    3735             : }
    3736             : 
    3737     3797076 : static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
    3738             : {
    3739             :         PyLdbMessageObject *ret;
    3740             : 
    3741     3797076 :         ret = (PyLdbMessageObject *)PyLdbMessage.tp_alloc(&PyLdbMessage, 0);
    3742     3797076 :         if (ret == NULL) {
    3743           0 :                 PyErr_NoMemory();
    3744           0 :                 return NULL;
    3745             :         }
    3746     3797076 :         ret->mem_ctx = talloc_new(NULL);
    3747     3797076 :         ret->msg = talloc_reference(ret->mem_ctx, msg);
    3748     3797076 :         return (PyObject *)ret;
    3749             : }
    3750             : 
    3751    12592062 : static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
    3752             : {
    3753    12592062 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3754    12592062 :         return pyldb_Dn_FromDn(msg->dn);
    3755             : }
    3756             : 
    3757      169162 : static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
    3758             : {
    3759      169162 :         struct ldb_message *msg = pyldb_Message_AsMessage(self);
    3760      169162 :         if (value == NULL) {
    3761           0 :                 PyErr_SetString(PyExc_AttributeError, "cannot delete dn");
    3762           0 :                 return -1;
    3763             :         }
    3764      169162 :         if (!pyldb_Dn_Check(value)) {
    3765           2 :                 PyErr_SetString(PyExc_TypeError, "expected dn");
    3766           2 :                 return -1;
    3767             :         }
    3768             : 
    3769      169160 :         msg->dn = talloc_reference(msg, pyldb_Dn_AS_DN(value));
    3770      169160 :         return 0;
    3771             : }
    3772             : 
    3773          81 : static PyObject *py_ldb_msg_get_text(PyObject *self, void *closure)
    3774             : {
    3775          81 :         return wrap_text("MessageTextWrapper", self);
    3776             : }
    3777             : 
    3778             : static PyGetSetDef py_ldb_msg_getset[] = {
    3779             :         {
    3780             :                 .name = discard_const_p(char, "dn"),
    3781             :                 .get  = (getter)py_ldb_msg_get_dn,
    3782             :                 .set  = (setter)py_ldb_msg_set_dn,
    3783             :         },
    3784             :         {
    3785             :                 .name = discard_const_p(char, "text"),
    3786             :                 .get  = (getter)py_ldb_msg_get_text,
    3787             :         },
    3788             :         { .name = NULL },
    3789             : };
    3790             : 
    3791       64663 : static PyObject *py_ldb_msg_repr(PyLdbMessageObject *self)
    3792             : {
    3793       64663 :         PyObject *dict = PyDict_New(), *ret, *repr;
    3794       64663 :         if (PyDict_Update(dict, (PyObject *)self) != 0)
    3795           0 :                 return NULL;
    3796       64663 :         repr = PyObject_Repr(dict);
    3797       64663 :         if (repr == NULL) {
    3798           0 :                 Py_DECREF(dict);
    3799           0 :                 return NULL;
    3800             :         }
    3801       64663 :         ret = PyUnicode_FromFormat("Message(%s)", PyUnicode_AsUTF8(repr));
    3802       64663 :         Py_DECREF(repr);
    3803       64663 :         Py_DECREF(dict);
    3804       64663 :         return ret;
    3805             : }
    3806             : 
    3807     3965182 : static void py_ldb_msg_dealloc(PyLdbMessageObject *self)
    3808             : {
    3809     3965182 :         talloc_free(self->mem_ctx);
    3810     3965182 :         PyObject_Del(self);
    3811     3965182 : }
    3812             : 
    3813        1679 : static PyObject *py_ldb_msg_richcmp(PyLdbMessageObject *py_msg1,
    3814             :                               PyLdbMessageObject *py_msg2, int op)
    3815             : {
    3816             :         struct ldb_message *msg1, *msg2;
    3817             :         unsigned int i;
    3818             :         int ret;
    3819             : 
    3820        1679 :         if (!PyLdbMessage_Check(py_msg2)) {
    3821         937 :                 Py_INCREF(Py_NotImplemented);
    3822         937 :                 return Py_NotImplemented;
    3823             :         }
    3824             : 
    3825         742 :         msg1 = pyldb_Message_AsMessage(py_msg1),
    3826         742 :         msg2 = pyldb_Message_AsMessage(py_msg2);
    3827             : 
    3828         742 :         if ((msg1->dn != NULL) || (msg2->dn != NULL)) {
    3829         740 :                 ret = ldb_dn_compare(msg1->dn, msg2->dn);
    3830         740 :                 if (ret != 0) {
    3831           0 :                         return richcmp(ret, op);
    3832             :                 }
    3833             :         }
    3834             : 
    3835         742 :         ret = msg1->num_elements - msg2->num_elements;
    3836         742 :         if (ret != 0) {
    3837           0 :                 return richcmp(ret, op);
    3838             :         }
    3839             : 
    3840        7348 :         for (i = 0; i < msg1->num_elements; i++) {
    3841        6608 :                 ret = ldb_msg_element_compare_name(&msg1->elements[i],
    3842        6608 :                                                    &msg2->elements[i]);
    3843        6608 :                 if (ret != 0) {
    3844           0 :                         return richcmp(ret, op);
    3845             :                 }
    3846             : 
    3847        6608 :                 ret = ldb_msg_element_compare(&msg1->elements[i],
    3848        6608 :                                               &msg2->elements[i]);
    3849        6608 :                 if (ret != 0) {
    3850           2 :                         return richcmp(ret, op);
    3851             :                 }
    3852             :         }
    3853             : 
    3854         740 :         return richcmp(0, op);
    3855             : }
    3856             : 
    3857             : static PyTypeObject PyLdbMessage = {
    3858             :         .tp_name = "ldb.Message",
    3859             :         .tp_methods = py_ldb_msg_methods,
    3860             :         .tp_getset = py_ldb_msg_getset,
    3861             :         .tp_as_sequence = &py_ldb_msg_sequence,
    3862             :         .tp_as_mapping = &py_ldb_msg_mapping,
    3863             :         .tp_basicsize = sizeof(PyLdbMessageObject),
    3864             :         .tp_dealloc = (destructor)py_ldb_msg_dealloc,
    3865             :         .tp_new = py_ldb_msg_new,
    3866             :         .tp_repr = (reprfunc)py_ldb_msg_repr,
    3867             :         .tp_flags = Py_TPFLAGS_DEFAULT,
    3868             :         .tp_iter = (getiterfunc)py_ldb_msg_iter,
    3869             :         .tp_richcompare = (richcmpfunc)py_ldb_msg_richcmp,
    3870             :         .tp_doc = "A LDB Message",
    3871             : };
    3872             : 
    3873           2 : static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
    3874             : {
    3875             :         PyLdbTreeObject *ret;
    3876             : 
    3877           2 :         ret = (PyLdbTreeObject *)PyLdbTree.tp_alloc(&PyLdbTree, 0);
    3878           2 :         if (ret == NULL) {
    3879           0 :                 PyErr_NoMemory();
    3880           0 :                 return NULL;
    3881             :         }
    3882             : 
    3883           2 :         ret->mem_ctx = talloc_new(NULL);
    3884           2 :         ret->tree = talloc_reference(ret->mem_ctx, tree);
    3885           2 :         return (PyObject *)ret;
    3886             : }
    3887             : 
    3888           2 : static void py_ldb_tree_dealloc(PyLdbTreeObject *self)
    3889             : {
    3890           2 :         talloc_free(self->mem_ctx);
    3891           2 :         PyObject_Del(self);
    3892           2 : }
    3893             : 
    3894             : static PyTypeObject PyLdbTree = {
    3895             :         .tp_name = "ldb.Tree",
    3896             :         .tp_basicsize = sizeof(PyLdbTreeObject),
    3897             :         .tp_dealloc = (destructor)py_ldb_tree_dealloc,
    3898             :         .tp_flags = Py_TPFLAGS_DEFAULT,
    3899             :         .tp_doc = "A search tree",
    3900             : };
    3901             : 
    3902             : /* Ldb_module */
    3903           2 : static int py_module_search(struct ldb_module *mod, struct ldb_request *req)
    3904             : {
    3905           2 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    3906             :         PyObject *py_result, *py_base, *py_attrs, *py_tree;
    3907             : 
    3908           2 :         py_base = pyldb_Dn_FromDn(req->op.search.base);
    3909             : 
    3910           2 :         if (py_base == NULL)
    3911           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    3912             : 
    3913           2 :         py_tree = PyLdbTree_FromTree(req->op.search.tree);
    3914             : 
    3915           2 :         if (py_tree == NULL)
    3916           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    3917             : 
    3918           2 :         if (req->op.search.attrs == NULL) {
    3919           0 :                 py_attrs = Py_None;
    3920             :         } else {
    3921             :                 int i, len;
    3922           2 :                 for (len = 0; req->op.search.attrs[len]; len++);
    3923           2 :                 py_attrs = PyList_New(len);
    3924          10 :                 for (i = 0; i < len; i++)
    3925           8 :                         PyList_SetItem(py_attrs, i, PyUnicode_FromString(req->op.search.attrs[i]));
    3926             :         }
    3927             : 
    3928           2 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "search"),
    3929             :                                         discard_const_p(char, "OiOO"),
    3930           2 :                                         py_base, req->op.search.scope, py_tree, py_attrs);
    3931             : 
    3932           2 :         Py_DECREF(py_attrs);
    3933           2 :         Py_DECREF(py_tree);
    3934           2 :         Py_DECREF(py_base);
    3935             : 
    3936           2 :         if (py_result == NULL) {
    3937           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    3938             :         }
    3939             : 
    3940           2 :         req->op.search.res = PyLdbResult_AsResult(NULL, py_result);
    3941           2 :         if (req->op.search.res == NULL) {
    3942           2 :                 return LDB_ERR_PYTHON_EXCEPTION;
    3943             :         }
    3944             : 
    3945           0 :         Py_DECREF(py_result);
    3946             : 
    3947           0 :         return LDB_SUCCESS;
    3948             : }
    3949             : 
    3950           0 : static int py_module_add(struct ldb_module *mod, struct ldb_request *req)
    3951             : {
    3952           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    3953             :         PyObject *py_result, *py_msg;
    3954             : 
    3955           0 :         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.add.message));
    3956             : 
    3957           0 :         if (py_msg == NULL) {
    3958           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    3959             :         }
    3960             : 
    3961           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "add"),
    3962             :                                         discard_const_p(char, "O"),
    3963             :                                         py_msg);
    3964             : 
    3965           0 :         Py_DECREF(py_msg);
    3966             : 
    3967           0 :         if (py_result == NULL) {
    3968           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    3969             :         }
    3970             : 
    3971           0 :         Py_DECREF(py_result);
    3972             : 
    3973           0 :         return LDB_SUCCESS;
    3974             : }
    3975             : 
    3976           0 : static int py_module_modify(struct ldb_module *mod, struct ldb_request *req)
    3977             : {
    3978           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    3979             :         PyObject *py_result, *py_msg;
    3980             : 
    3981           0 :         py_msg = PyLdbMessage_FromMessage(discard_const_p(struct ldb_message, req->op.mod.message));
    3982             : 
    3983           0 :         if (py_msg == NULL) {
    3984           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    3985             :         }
    3986             : 
    3987           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "modify"),
    3988             :                                         discard_const_p(char, "O"),
    3989             :                                         py_msg);
    3990             : 
    3991           0 :         Py_DECREF(py_msg);
    3992             : 
    3993           0 :         if (py_result == NULL) {
    3994           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    3995             :         }
    3996             : 
    3997           0 :         Py_DECREF(py_result);
    3998             : 
    3999           0 :         return LDB_SUCCESS;
    4000             : }
    4001             : 
    4002           0 : static int py_module_del(struct ldb_module *mod, struct ldb_request *req)
    4003             : {
    4004           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4005             :         PyObject *py_result, *py_dn;
    4006             : 
    4007           0 :         py_dn = pyldb_Dn_FromDn(req->op.del.dn);
    4008             : 
    4009           0 :         if (py_dn == NULL)
    4010           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    4011             : 
    4012           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "delete"),
    4013             :                                         discard_const_p(char, "O"),
    4014             :                                         py_dn);
    4015             : 
    4016           0 :         if (py_result == NULL) {
    4017           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4018             :         }
    4019             : 
    4020           0 :         Py_DECREF(py_result);
    4021             : 
    4022           0 :         return LDB_SUCCESS;
    4023             : }
    4024             : 
    4025           0 : static int py_module_rename(struct ldb_module *mod, struct ldb_request *req)
    4026             : {
    4027           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4028             :         PyObject *py_result, *py_olddn, *py_newdn;
    4029             : 
    4030           0 :         py_olddn = pyldb_Dn_FromDn(req->op.rename.olddn);
    4031             : 
    4032           0 :         if (py_olddn == NULL)
    4033           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    4034             : 
    4035           0 :         py_newdn = pyldb_Dn_FromDn(req->op.rename.newdn);
    4036             : 
    4037           0 :         if (py_newdn == NULL)
    4038           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    4039             : 
    4040           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "rename"),
    4041             :                                         discard_const_p(char, "OO"),
    4042             :                                         py_olddn, py_newdn);
    4043             : 
    4044           0 :         Py_DECREF(py_olddn);
    4045           0 :         Py_DECREF(py_newdn);
    4046             : 
    4047           0 :         if (py_result == NULL) {
    4048           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4049             :         }
    4050             : 
    4051           0 :         Py_DECREF(py_result);
    4052             : 
    4053           0 :         return LDB_SUCCESS;
    4054             : }
    4055             : 
    4056           2 : static int py_module_request(struct ldb_module *mod, struct ldb_request *req)
    4057             : {
    4058           2 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4059             :         PyObject *py_result;
    4060             : 
    4061           2 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "request"),
    4062             :                                         discard_const_p(char, ""));
    4063             : 
    4064           2 :         Py_XDECREF(py_result);
    4065             : 
    4066           2 :         return LDB_ERR_OPERATIONS_ERROR;
    4067             : }
    4068             : 
    4069           0 : static int py_module_extended(struct ldb_module *mod, struct ldb_request *req)
    4070             : {
    4071           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4072             :         PyObject *py_result;
    4073             : 
    4074           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "extended"),
    4075             :                                         discard_const_p(char, ""));
    4076             : 
    4077           0 :         Py_XDECREF(py_result);
    4078             : 
    4079           0 :         return LDB_ERR_OPERATIONS_ERROR;
    4080             : }
    4081             : 
    4082           0 : static int py_module_start_transaction(struct ldb_module *mod)
    4083             : {
    4084           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4085             :         PyObject *py_result;
    4086             : 
    4087           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "start_transaction"),
    4088             :                                         discard_const_p(char, ""));
    4089             : 
    4090           0 :         if (py_result == NULL) {
    4091           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4092             :         }
    4093             : 
    4094           0 :         Py_DECREF(py_result);
    4095             : 
    4096           0 :         return LDB_SUCCESS;
    4097             : }
    4098             : 
    4099           0 : static int py_module_end_transaction(struct ldb_module *mod)
    4100             : {
    4101           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4102             :         PyObject *py_result;
    4103             : 
    4104           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "end_transaction"),
    4105             :                                         discard_const_p(char, ""));
    4106             : 
    4107           0 :         if (py_result == NULL) {
    4108           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4109             :         }
    4110             : 
    4111           0 :         Py_DECREF(py_result);
    4112             : 
    4113           0 :         return LDB_SUCCESS;
    4114             : }
    4115             : 
    4116           0 : static int py_module_del_transaction(struct ldb_module *mod)
    4117             : {
    4118           0 :         PyObject *py_ldb = (PyObject *)mod->private_data;
    4119             :         PyObject *py_result;
    4120             : 
    4121           0 :         py_result = PyObject_CallMethod(py_ldb, discard_const_p(char, "del_transaction"),
    4122             :                                         discard_const_p(char, ""));
    4123             : 
    4124           0 :         if (py_result == NULL) {
    4125           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4126             :         }
    4127             : 
    4128           0 :         Py_DECREF(py_result);
    4129             : 
    4130           0 :         return LDB_SUCCESS;
    4131             : }
    4132             : 
    4133           0 : static int py_module_destructor(struct ldb_module *mod)
    4134             : {
    4135           0 :         Py_DECREF((PyObject *)mod->private_data);
    4136           0 :         return 0;
    4137             : }
    4138             : 
    4139           2 : static int py_module_init(struct ldb_module *mod)
    4140             : {
    4141           2 :         PyObject *py_class = (PyObject *)mod->ops->private_data;
    4142             :         PyObject *py_result, *py_next, *py_ldb;
    4143             : 
    4144           2 :         py_ldb = PyLdb_FromLdbContext(mod->ldb);
    4145             : 
    4146           2 :         if (py_ldb == NULL)
    4147           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    4148             : 
    4149           2 :         py_next = PyLdbModule_FromModule(mod->next);
    4150             : 
    4151           2 :         if (py_next == NULL)
    4152           0 :                 return LDB_ERR_OPERATIONS_ERROR;
    4153             : 
    4154           2 :         py_result = PyObject_CallFunction(py_class, discard_const_p(char, "OO"),
    4155             :                                           py_ldb, py_next);
    4156             : 
    4157           2 :         if (py_result == NULL) {
    4158           0 :                 return LDB_ERR_PYTHON_EXCEPTION;
    4159             :         }
    4160             : 
    4161           2 :         mod->private_data = py_result;
    4162             : 
    4163           2 :         talloc_set_destructor(mod, py_module_destructor);
    4164             : 
    4165           2 :         return ldb_next_init(mod);
    4166             : }
    4167             : 
    4168           4 : static PyObject *py_register_module(PyObject *module, PyObject *args)
    4169             : {
    4170             :         int ret;
    4171             :         struct ldb_module_ops *ops;
    4172             :         PyObject *input;
    4173           4 :         PyObject *tmp = NULL;
    4174           4 :         const char *name = NULL;
    4175             : 
    4176           4 :         if (!PyArg_ParseTuple(args, "O", &input))
    4177           0 :                 return NULL;
    4178             : 
    4179           4 :         ops = talloc_zero(NULL, struct ldb_module_ops);
    4180           4 :         if (ops == NULL) {
    4181           0 :                 PyErr_NoMemory();
    4182           0 :                 return NULL;
    4183             :         }
    4184             : 
    4185           4 :         tmp = PyObject_GetAttrString(input, discard_const_p(char, "name"));
    4186           4 :         if (tmp == NULL) {
    4187           0 :                 return NULL;
    4188             :         }
    4189           4 :         name = PyUnicode_AsUTF8(tmp);
    4190           4 :         if (name == NULL) {
    4191           0 :                 return NULL;
    4192             :         }
    4193           4 :         Py_XDECREF(tmp);
    4194           4 :         Py_INCREF(input);
    4195             : 
    4196           4 :         ops->name = talloc_strdup(ops, name);
    4197           4 :         ops->private_data = input;
    4198           4 :         ops->init_context = py_module_init;
    4199           4 :         ops->search = py_module_search;
    4200           4 :         ops->add = py_module_add;
    4201           4 :         ops->modify = py_module_modify;
    4202           4 :         ops->del = py_module_del;
    4203           4 :         ops->rename = py_module_rename;
    4204           4 :         ops->request = py_module_request;
    4205           4 :         ops->extended = py_module_extended;
    4206           4 :         ops->start_transaction = py_module_start_transaction;
    4207           4 :         ops->end_transaction = py_module_end_transaction;
    4208           4 :         ops->del_transaction = py_module_del_transaction;
    4209             : 
    4210           4 :         ret = ldb_register_module(ops);
    4211           4 :         if (ret != LDB_SUCCESS) {
    4212           0 :                 TALLOC_FREE(ops);
    4213             :         }
    4214             : 
    4215           4 :         PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
    4216             : 
    4217           4 :         Py_RETURN_NONE;
    4218             : }
    4219             : 
    4220         620 : static PyObject *py_timestring(PyObject *module, PyObject *args)
    4221             : {
    4222             :         /* most times "time_t" is a signed integer type with 32 or 64 bit:
    4223             :          * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */
    4224             :         long int t_val;
    4225             :         char *tresult;
    4226             :         PyObject *ret;
    4227         620 :         if (!PyArg_ParseTuple(args, "l", &t_val))
    4228           0 :                 return NULL;
    4229         620 :         tresult = ldb_timestring(NULL, (time_t) t_val);
    4230         620 :         if (tresult == NULL) {
    4231             :                 /*
    4232             :                  * Most likely EOVERFLOW from gmtime()
    4233             :                  */
    4234           6 :                 PyErr_SetFromErrno(PyExc_OSError);
    4235           6 :                 return NULL;
    4236             :         }
    4237         614 :         ret = PyUnicode_FromString(tresult);
    4238         614 :         talloc_free(tresult);
    4239         614 :         return ret;
    4240             : }
    4241             : 
    4242        1647 : static PyObject *py_string_to_time(PyObject *module, PyObject *args)
    4243             : {
    4244             :         char *str;
    4245        1647 :         if (!PyArg_ParseTuple(args, "s", &str))
    4246           0 :                 return NULL;
    4247             : 
    4248        1647 :         return PyLong_FromLong(ldb_string_to_time(str));
    4249             : }
    4250             : 
    4251           4 : static PyObject *py_valid_attr_name(PyObject *self, PyObject *args)
    4252             : {
    4253             :         char *name;
    4254           4 :         if (!PyArg_ParseTuple(args, "s", &name))
    4255           0 :                 return NULL;
    4256           4 :         return PyBool_FromLong(ldb_valid_attr_name(name));
    4257             : }
    4258             : 
    4259             : /*
    4260             :   encode a string using RFC2254 rules
    4261             :  */
    4262       38248 : static PyObject *py_binary_encode(PyObject *self, PyObject *args)
    4263             : {
    4264             :         char *str, *encoded;
    4265       38248 :         Py_ssize_t size = 0;
    4266             :         struct ldb_val val;
    4267             :         PyObject *ret;
    4268             : 
    4269       38248 :         if (!PyArg_ParseTuple(args, "s#", &str, &size))
    4270           0 :                 return NULL;
    4271       38248 :         val.data = (uint8_t *)str;
    4272       38248 :         val.length = size;
    4273             : 
    4274       38248 :         encoded = ldb_binary_encode(NULL, val);
    4275       38248 :         if (encoded == NULL) {
    4276           0 :                 PyErr_SetString(PyExc_TypeError, "unable to encode binary string");
    4277           0 :                 return NULL;
    4278             :         }
    4279       38248 :         ret = PyUnicode_FromString(encoded);
    4280       38248 :         talloc_free(encoded);
    4281       38248 :         return ret;
    4282             : }
    4283             : 
    4284             : /*
    4285             :   decode a string using RFC2254 rules
    4286             :  */
    4287           2 : static PyObject *py_binary_decode(PyObject *self, PyObject *args)
    4288             : {
    4289             :         char *str;
    4290             :         struct ldb_val val;
    4291             :         PyObject *ret;
    4292             : 
    4293           2 :         if (!PyArg_ParseTuple(args, "s", &str))
    4294           0 :                 return NULL;
    4295             : 
    4296           2 :         val = ldb_binary_decode(NULL, str);
    4297           2 :         if (val.data == NULL) {
    4298           0 :                 PyErr_SetString(PyExc_TypeError, "unable to decode binary string");
    4299           0 :                 return NULL;
    4300             :         }
    4301           2 :         ret = PyBytes_FromStringAndSize((const char*)val.data, val.length);
    4302           2 :         talloc_free(val.data);
    4303           2 :         return ret;
    4304             : }
    4305             : 
    4306             : static PyMethodDef py_ldb_global_methods[] = {
    4307             :         { "register_module", py_register_module, METH_VARARGS, 
    4308             :                 "S.register_module(module) -> None\n\n"
    4309             :                 "Register a LDB module."},
    4310             :         { "timestring", py_timestring, METH_VARARGS, 
    4311             :                 "S.timestring(int) -> string\n\n"
    4312             :                 "Generate a LDAP time string from a UNIX timestamp" },
    4313             :         { "string_to_time", py_string_to_time, METH_VARARGS,
    4314             :                 "S.string_to_time(string) -> int\n\n"
    4315             :                 "Parse a LDAP time string into a UNIX timestamp." },
    4316             :         { "valid_attr_name", py_valid_attr_name, METH_VARARGS,
    4317             :                 "S.valid_attr_name(name) -> bool\n\n"
    4318             :                 "Check whether the supplied name is a valid attribute name." },
    4319             :         { "binary_encode", py_binary_encode, METH_VARARGS,
    4320             :                 "S.binary_encode(string) -> string\n\n"
    4321             :                 "Perform a RFC2254 binary encoding on a string" },
    4322             :         { "binary_decode", py_binary_decode, METH_VARARGS,
    4323             :                 "S.binary_decode(string) -> string\n\n"
    4324             :                 "Perform a RFC2254 binary decode on a string" },
    4325             :         {0}
    4326             : };
    4327             : 
    4328             : #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."
    4329             : 
    4330             : #if PY_MAJOR_VERSION >= 3
    4331             : static struct PyModuleDef moduledef = {
    4332             :         PyModuleDef_HEAD_INIT,
    4333             :         .m_name = "ldb",
    4334             :         .m_doc = MODULE_DOC,
    4335             :         .m_size = -1,
    4336             :         .m_methods = py_ldb_global_methods,
    4337             : };
    4338             : #endif
    4339             : 
    4340        7569 : static PyObject* module_init(void)
    4341             : {
    4342             :         PyObject *m;
    4343             : 
    4344        7569 :         PyLdbBytesType.tp_base = &PyBytes_Type;
    4345        7569 :         if (PyType_Ready(&PyLdbBytesType) < 0) {
    4346           0 :                 return NULL;
    4347             :         }
    4348             : 
    4349        7569 :         if (PyType_Ready(&PyLdbDn) < 0)
    4350           0 :                 return NULL;
    4351             : 
    4352        7569 :         if (PyType_Ready(&PyLdbMessage) < 0)
    4353           0 :                 return NULL;
    4354             : 
    4355        7569 :         if (PyType_Ready(&PyLdbMessageElement) < 0)
    4356           0 :                 return NULL;
    4357             : 
    4358        7569 :         if (PyType_Ready(&PyLdb) < 0)
    4359           0 :                 return NULL;
    4360             : 
    4361        7569 :         if (PyType_Ready(&PyLdbModule) < 0)
    4362           0 :                 return NULL;
    4363             : 
    4364        7569 :         if (PyType_Ready(&PyLdbTree) < 0)
    4365           0 :                 return NULL;
    4366             : 
    4367        7569 :         if (PyType_Ready(&PyLdbResult) < 0)
    4368           0 :                 return NULL;
    4369             : 
    4370        7569 :         if (PyType_Ready(&PyLdbSearchIterator) < 0)
    4371           0 :                 return NULL;
    4372             : 
    4373        7569 :         if (PyType_Ready(&PyLdbControl) < 0)
    4374           0 :                 return NULL;
    4375             : 
    4376             : #if PY_MAJOR_VERSION >= 3
    4377        7569 :         m = PyModule_Create(&moduledef);
    4378             : #else
    4379             :         m = Py_InitModule3("ldb", py_ldb_global_methods, MODULE_DOC);
    4380             : #endif
    4381        7569 :         if (m == NULL)
    4382           0 :                 return NULL;
    4383             : 
    4384             : #define ADD_LDB_INT(val) PyModule_AddIntConstant(m, #val, LDB_ ## val)
    4385             : 
    4386        7569 :         ADD_LDB_INT(SEQ_HIGHEST_SEQ);
    4387        7569 :         ADD_LDB_INT(SEQ_HIGHEST_TIMESTAMP);
    4388        7569 :         ADD_LDB_INT(SEQ_NEXT);
    4389        7569 :         ADD_LDB_INT(SCOPE_DEFAULT);
    4390        7569 :         ADD_LDB_INT(SCOPE_BASE);
    4391        7569 :         ADD_LDB_INT(SCOPE_ONELEVEL);
    4392        7569 :         ADD_LDB_INT(SCOPE_SUBTREE);
    4393             : 
    4394        7569 :         ADD_LDB_INT(CHANGETYPE_NONE);
    4395        7569 :         ADD_LDB_INT(CHANGETYPE_ADD);
    4396        7569 :         ADD_LDB_INT(CHANGETYPE_DELETE);
    4397        7569 :         ADD_LDB_INT(CHANGETYPE_MODIFY);
    4398             : 
    4399        7569 :         ADD_LDB_INT(FLAG_MOD_ADD);
    4400        7569 :         ADD_LDB_INT(FLAG_MOD_REPLACE);
    4401        7569 :         ADD_LDB_INT(FLAG_MOD_DELETE);
    4402        7569 :         ADD_LDB_INT(FLAG_FORCE_NO_BASE64_LDIF);
    4403             : 
    4404        7569 :         ADD_LDB_INT(ATTR_FLAG_HIDDEN);
    4405        7569 :         ADD_LDB_INT(ATTR_FLAG_UNIQUE_INDEX);
    4406        7569 :         ADD_LDB_INT(ATTR_FLAG_SINGLE_VALUE);
    4407        7569 :         ADD_LDB_INT(ATTR_FLAG_FORCE_BASE64_LDIF);
    4408             : 
    4409        7569 :         ADD_LDB_INT(SUCCESS);
    4410        7569 :         ADD_LDB_INT(ERR_OPERATIONS_ERROR);
    4411        7569 :         ADD_LDB_INT(ERR_PROTOCOL_ERROR);
    4412        7569 :         ADD_LDB_INT(ERR_TIME_LIMIT_EXCEEDED);
    4413        7569 :         ADD_LDB_INT(ERR_SIZE_LIMIT_EXCEEDED);
    4414        7569 :         ADD_LDB_INT(ERR_COMPARE_FALSE);
    4415        7569 :         ADD_LDB_INT(ERR_COMPARE_TRUE);
    4416        7569 :         ADD_LDB_INT(ERR_AUTH_METHOD_NOT_SUPPORTED);
    4417        7569 :         ADD_LDB_INT(ERR_STRONG_AUTH_REQUIRED);
    4418        7569 :         ADD_LDB_INT(ERR_REFERRAL);
    4419        7569 :         ADD_LDB_INT(ERR_ADMIN_LIMIT_EXCEEDED);
    4420        7569 :         ADD_LDB_INT(ERR_UNSUPPORTED_CRITICAL_EXTENSION);
    4421        7569 :         ADD_LDB_INT(ERR_CONFIDENTIALITY_REQUIRED);
    4422        7569 :         ADD_LDB_INT(ERR_SASL_BIND_IN_PROGRESS);
    4423        7569 :         ADD_LDB_INT(ERR_NO_SUCH_ATTRIBUTE);
    4424        7569 :         ADD_LDB_INT(ERR_UNDEFINED_ATTRIBUTE_TYPE);
    4425        7569 :         ADD_LDB_INT(ERR_INAPPROPRIATE_MATCHING);
    4426        7569 :         ADD_LDB_INT(ERR_CONSTRAINT_VIOLATION);
    4427        7569 :         ADD_LDB_INT(ERR_ATTRIBUTE_OR_VALUE_EXISTS);
    4428        7569 :         ADD_LDB_INT(ERR_INVALID_ATTRIBUTE_SYNTAX);
    4429        7569 :         ADD_LDB_INT(ERR_NO_SUCH_OBJECT);
    4430        7569 :         ADD_LDB_INT(ERR_ALIAS_PROBLEM);
    4431        7569 :         ADD_LDB_INT(ERR_INVALID_DN_SYNTAX);
    4432        7569 :         ADD_LDB_INT(ERR_ALIAS_DEREFERENCING_PROBLEM);
    4433        7569 :         ADD_LDB_INT(ERR_INAPPROPRIATE_AUTHENTICATION);
    4434        7569 :         ADD_LDB_INT(ERR_INVALID_CREDENTIALS);
    4435        7569 :         ADD_LDB_INT(ERR_INSUFFICIENT_ACCESS_RIGHTS);
    4436        7569 :         ADD_LDB_INT(ERR_BUSY);
    4437        7569 :         ADD_LDB_INT(ERR_UNAVAILABLE);
    4438        7569 :         ADD_LDB_INT(ERR_UNWILLING_TO_PERFORM);
    4439        7569 :         ADD_LDB_INT(ERR_LOOP_DETECT);
    4440        7569 :         ADD_LDB_INT(ERR_NAMING_VIOLATION);
    4441        7569 :         ADD_LDB_INT(ERR_OBJECT_CLASS_VIOLATION);
    4442        7569 :         ADD_LDB_INT(ERR_NOT_ALLOWED_ON_NON_LEAF);
    4443        7569 :         ADD_LDB_INT(ERR_NOT_ALLOWED_ON_RDN);
    4444        7569 :         ADD_LDB_INT(ERR_ENTRY_ALREADY_EXISTS);
    4445        7569 :         ADD_LDB_INT(ERR_OBJECT_CLASS_MODS_PROHIBITED);
    4446        7569 :         ADD_LDB_INT(ERR_AFFECTS_MULTIPLE_DSAS);
    4447        7569 :         ADD_LDB_INT(ERR_OTHER);
    4448             : 
    4449        7569 :         ADD_LDB_INT(FLG_RDONLY);
    4450        7569 :         ADD_LDB_INT(FLG_NOSYNC);
    4451        7569 :         ADD_LDB_INT(FLG_RECONNECT);
    4452        7569 :         ADD_LDB_INT(FLG_NOMMAP);
    4453        7569 :         ADD_LDB_INT(FLG_SHOW_BINARY);
    4454        7569 :         ADD_LDB_INT(FLG_ENABLE_TRACING);
    4455        7569 :         ADD_LDB_INT(FLG_DONT_CREATE_DB);
    4456             : 
    4457        7569 :         ADD_LDB_INT(PACKING_FORMAT);
    4458        7569 :         ADD_LDB_INT(PACKING_FORMAT_V2);
    4459             : 
    4460             :         /* Historical misspelling */
    4461        7569 :         PyModule_AddIntConstant(m, "ERR_ALIAS_DEREFERINCING_PROBLEM", LDB_ERR_ALIAS_DEREFERENCING_PROBLEM);
    4462             : 
    4463        7569 :         PyModule_AddStringConstant(m, "__docformat__", "restructuredText");
    4464             : 
    4465        7569 :         PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
    4466        7569 :         PyModule_AddObject(m, "LdbError", PyExc_LdbError);
    4467             : 
    4468        7569 :         Py_INCREF(&PyLdb);
    4469        7569 :         Py_INCREF(&PyLdbDn);
    4470        7569 :         Py_INCREF(&PyLdbModule);
    4471        7569 :         Py_INCREF(&PyLdbMessage);
    4472        7569 :         Py_INCREF(&PyLdbMessageElement);
    4473        7569 :         Py_INCREF(&PyLdbTree);
    4474        7569 :         Py_INCREF(&PyLdbResult);
    4475        7569 :         Py_INCREF(&PyLdbControl);
    4476             : 
    4477        7569 :         PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb);
    4478        7569 :         PyModule_AddObject(m, "Dn", (PyObject *)&PyLdbDn);
    4479        7569 :         PyModule_AddObject(m, "Message", (PyObject *)&PyLdbMessage);
    4480        7569 :         PyModule_AddObject(m, "MessageElement", (PyObject *)&PyLdbMessageElement);
    4481        7569 :         PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule);
    4482        7569 :         PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree);
    4483        7569 :         PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl);
    4484             : 
    4485        7569 :         PyModule_AddStringConstant(m, "__version__", PACKAGE_VERSION);
    4486             : 
    4487             : #define ADD_LDB_STRING(val)  PyModule_AddStringConstant(m, #val, LDB_## val)
    4488             : 
    4489        7569 :         ADD_LDB_STRING(SYNTAX_DN);
    4490        7569 :         ADD_LDB_STRING(SYNTAX_DIRECTORY_STRING);
    4491        7569 :         ADD_LDB_STRING(SYNTAX_INTEGER);
    4492        7569 :         ADD_LDB_STRING(SYNTAX_ORDERED_INTEGER);
    4493        7569 :         ADD_LDB_STRING(SYNTAX_BOOLEAN);
    4494        7569 :         ADD_LDB_STRING(SYNTAX_OCTET_STRING);
    4495        7569 :         ADD_LDB_STRING(SYNTAX_UTC_TIME);
    4496        7569 :         ADD_LDB_STRING(OID_COMPARATOR_AND);
    4497        7569 :         ADD_LDB_STRING(OID_COMPARATOR_OR);
    4498             : 
    4499        7569 :         return m;
    4500             : }
    4501             : 
    4502             : #if PY_MAJOR_VERSION >= 3
    4503             : PyMODINIT_FUNC PyInit_ldb(void);
    4504        7569 : PyMODINIT_FUNC PyInit_ldb(void)
    4505             : {
    4506        7569 :         return module_init();
    4507             : }
    4508             : #else
    4509             : void initldb(void);
    4510             : void initldb(void)
    4511             : {
    4512             :         module_init();
    4513             : }
    4514             : #endif

Generated by: LCOV version 1.13