LCOV - code coverage report
Current view: top level - lib/ldb - pyldb.c (source / functions) Hit Total Coverage
Test: coverage report for recycleplus df22b230 Lines: 1530 2107 72.6 %
Date: 2024-02-14 10:14:15 Functions: 149 171 87.1 %

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

Generated by: LCOV version 1.14