LCOV - code coverage report
Current view: top level - lib/ldb - pyldb.c (source / functions) Hit Total Coverage
Test: coverage report for master 2b515b7d Lines: 1835 2681 68.4 %
Date: 2024-02-28 12:06:22 Functions: 151 172 87.8 %

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

Generated by: LCOV version 1.14