LCOV - code coverage report
Current view: top level - lib/ldb - pyldb.c (source / functions) Hit Total Coverage
Test: coverage report for abartlet/fix-coverage dd10fb34 Lines: 1514 2083 72.7 %
Date: 2021-09-23 10:06:22 Functions: 152 174 87.4 %

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

Generated by: LCOV version 1.13