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

Generated by: LCOV version 1.14