Changeset 745 for trunk/server/source4/lib/ldb/pyldb.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source4/lib/ldb/pyldb.c
r414 r745 6 6 Copyright (C) 2005,2006 Tim Potter <tpot@samba.org> 7 7 Copyright (C) 2006 Simo Sorce <idra@samba.org> 8 Copyright (C) 2007-20 09Jelmer Vernooij <jelmer@samba.org>9 Copyright (C) 2009 Matthias Dieter Wallnöfer10 11 12 13 8 Copyright (C) 2007-2010 Jelmer Vernooij <jelmer@samba.org> 9 Copyright (C) 2009-2010 Matthias Dieter Wallnöfer 10 11 ** NOTE! The following LGPL license applies to the ldb 12 ** library. This does NOT imply that all of Samba is released 13 ** under the LGPL 14 14 15 15 This library is free software; you can redistribute it and/or … … 27 27 */ 28 28 29 #include "replace.h" 29 #include <Python.h> 30 #include <pytalloc.h> 30 31 #include "ldb_private.h" 31 #include <Python.h>32 32 #include "pyldb.h" 33 34 void initldb(void); 35 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg); 36 static PyObject *PyExc_LdbError; 37 38 staticforward PyTypeObject PyLdbControl; 39 staticforward PyTypeObject PyLdbResult; 40 staticforward PyTypeObject PyLdbMessage; 41 staticforward PyTypeObject PyLdbModule; 42 staticforward PyTypeObject PyLdbDn; 43 staticforward PyTypeObject PyLdb; 44 staticforward PyTypeObject PyLdbMessageElement; 45 staticforward PyTypeObject PyLdbTree; 46 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx); 47 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod); 48 static struct ldb_message_element *PyObject_AsMessageElement( 49 TALLOC_CTX *mem_ctx, 50 PyObject *set_obj, 51 int flags, 52 const char *attr_name); 33 53 34 54 /* There's no Py_ssize_t in 2.4, apparently */ … … 43 63 #endif 44 64 65 #define SIGN(a) (((a) == 0)?0:((a) < 0?-1:1)) 66 67 68 69 static PyObject *py_ldb_control_str(PyLdbControlObject *self) 70 { 71 if (self->data != NULL) { 72 char* control = ldb_control_to_string(self->mem_ctx, self->data); 73 if (control == NULL) { 74 PyErr_NoMemory(); 75 return NULL; 76 } 77 return PyString_FromString(control); 78 } else { 79 return PyString_FromFormat("ldb control"); 80 } 81 } 82 83 static void py_ldb_control_dealloc(PyLdbControlObject *self) 84 { 85 if (self->mem_ctx != NULL) { 86 talloc_free(self->mem_ctx); 87 } 88 self->ob_type->tp_free(self); 89 } 90 91 static PyObject *py_ldb_control_get_oid(PyLdbControlObject *self) 92 { 93 return PyString_FromString(self->data->oid); 94 } 95 96 static PyObject *py_ldb_control_get_critical(PyLdbControlObject *self) 97 { 98 return PyBool_FromLong(self->data->critical); 99 } 100 101 static PyObject *py_ldb_control_set_critical(PyLdbControlObject *self, PyObject *value, void *closure) 102 { 103 if (PyObject_IsTrue(value)) { 104 self->data->critical = true; 105 } else { 106 self->data->critical = false; 107 } 108 return 0; 109 } 110 111 static PyObject *py_ldb_control_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) 112 { 113 char *data = NULL; 114 const char *array[2]; 115 const char * const kwnames[] = { "ldb", "data", NULL }; 116 struct ldb_control *parsed_controls; 117 PyLdbControlObject *ret; 118 PyObject *py_ldb; 119 TALLOC_CTX *mem_ctx; 120 struct ldb_context *ldb_ctx; 121 122 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "Os", 123 discard_const_p(char *, kwnames), 124 &py_ldb, &data)) 125 return NULL; 126 127 mem_ctx = talloc_new(NULL); 128 if (mem_ctx == NULL) { 129 PyErr_NoMemory(); 130 return NULL; 131 } 132 133 ldb_ctx = PyLdb_AsLdbContext(py_ldb); 134 parsed_controls = ldb_parse_control_from_string(ldb_ctx, mem_ctx, data); 135 136 if (!parsed_controls) { 137 talloc_free(mem_ctx); 138 PyErr_SetString(PyExc_ValueError, "unable to parse control string"); 139 return NULL; 140 } 141 142 ret = PyObject_New(PyLdbControlObject, type); 143 if (ret == NULL) { 144 PyErr_NoMemory(); 145 talloc_free(mem_ctx); 146 return NULL; 147 } 148 149 ret->mem_ctx = mem_ctx; 150 151 ret->data = talloc_steal(mem_ctx, parsed_controls); 152 if (ret->data == NULL) { 153 Py_DECREF(ret); 154 PyErr_NoMemory(); 155 talloc_free(mem_ctx); 156 return NULL; 157 } 158 159 return (PyObject *)ret; 160 } 161 162 static PyGetSetDef py_ldb_control_getset[] = { 163 { discard_const_p(char, "oid"), (getter)py_ldb_control_get_oid, NULL, NULL }, 164 { discard_const_p(char, "critical"), (getter)py_ldb_control_get_critical, (setter)py_ldb_control_set_critical, NULL }, 165 { NULL } 166 }; 167 168 static PyTypeObject PyLdbControl = { 169 .tp_name = "ldb.control", 170 .tp_dealloc = (destructor)py_ldb_control_dealloc, 171 .tp_getattro = PyObject_GenericGetAttr, 172 .tp_basicsize = sizeof(PyLdbControlObject), 173 .tp_getset = py_ldb_control_getset, 174 .tp_doc = "LDB control.", 175 .tp_str = (reprfunc)py_ldb_control_str, 176 .tp_new = py_ldb_control_new, 177 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 178 }; 179 45 180 static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx) 46 181 { … … 49 184 50 185 PyErr_SetObject(error, 51 Py_BuildValue(discard_const_p(char, "(i,s)"), ret, 52 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); 53 } 54 55 static PyObject *PyExc_LdbError; 56 57 PyAPI_DATA(PyTypeObject) PyLdbMessage; 58 PyAPI_DATA(PyTypeObject) PyLdbModule; 59 PyAPI_DATA(PyTypeObject) PyLdbDn; 60 PyAPI_DATA(PyTypeObject) PyLdb; 61 PyAPI_DATA(PyTypeObject) PyLdbMessageElement; 62 PyAPI_DATA(PyTypeObject) PyLdbTree; 63 64 static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx, 65 struct ldb_message_element *el, 66 struct ldb_val *val) 67 { 68 struct ldb_val new_val; 69 TALLOC_CTX *mem_ctx = talloc_new(NULL); 70 PyObject *ret; 71 72 new_val = *val; 73 74 ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length); 75 76 talloc_free(mem_ctx); 77 78 return ret; 186 Py_BuildValue(discard_const_p(char, "(i,s)"), ret, 187 ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx))); 188 } 189 190 static PyObject *PyObject_FromLdbValue(struct ldb_val *val) 191 { 192 return PyString_FromStringAndSize((const char *)val->data, val->length); 79 193 } 80 194 81 195 /** 82 * Obtain a ldb DN from a Python object.196 * Create a Python object from a ldb_result. 83 197 * 84 * @param mem_ctx Memory context 85 * @param object Python object 86 * @param ldb_ctx LDB context 87 * @return Whether or not the conversion succeeded 198 * @param result LDB result to convert 199 * @return Python object with converted result (a list object) 88 200 */ 89 bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, 90 struct ldb_context *ldb_ctx, struct ldb_dn **dn) 91 { 92 struct ldb_dn *odn; 93 94 if (ldb_ctx != NULL && PyString_Check(object)) { 95 odn = ldb_dn_new(mem_ctx, ldb_ctx, PyString_AsString(object)); 96 *dn = odn; 97 return true; 98 } 99 100 if (PyLdbDn_Check(object)) { 101 *dn = PyLdbDn_AsDn(object); 102 return true; 103 } 104 105 PyErr_SetString(PyExc_TypeError, "Expected DN"); 106 return false; 201 static PyObject *PyLdbControl_FromControl(struct ldb_control *control) 202 { 203 TALLOC_CTX *ctl_ctx = talloc_new(NULL); 204 PyLdbControlObject *ctrl; 205 if (ctl_ctx == NULL) { 206 PyErr_NoMemory(); 207 return NULL; 208 } 209 210 ctrl = (PyLdbControlObject *)PyLdbControl.tp_alloc(&PyLdbControl, 0); 211 if (ctrl == NULL) { 212 PyErr_NoMemory(); 213 return NULL; 214 } 215 ctrl->mem_ctx = ctl_ctx; 216 ctrl->data = talloc_steal(ctrl->mem_ctx, control); 217 if (ctrl->data == NULL) { 218 Py_DECREF(ctrl); 219 PyErr_NoMemory(); 220 return NULL; 221 } 222 return (PyObject*) ctrl; 107 223 } 108 224 … … 115 231 static PyObject *PyLdbResult_FromResult(struct ldb_result *result) 116 232 { 117 PyObject *ret; 118 int i; 233 PyLdbResultObject *ret; 234 PyObject *list, *controls, *referals; 235 Py_ssize_t i; 236 119 237 if (result == NULL) { 120 238 Py_RETURN_NONE; 121 } 122 ret = PyList_New(result->count); 239 } 240 241 ret = (PyLdbResultObject *)PyLdbResult.tp_alloc(&PyLdbResult, 0); 242 if (ret == NULL) { 243 PyErr_NoMemory(); 244 return NULL; 245 } 246 247 list = PyList_New(result->count); 248 if (list == NULL) { 249 PyErr_NoMemory(); 250 Py_DECREF(ret); 251 return NULL; 252 } 253 123 254 for (i = 0; i < result->count; i++) { 124 PyList_SetItem(ret, i, PyLdbMessage_FromMessage(result->msgs[i]) 125 ); 126 } 127 return ret; 255 PyList_SetItem(list, i, PyLdbMessage_FromMessage(result->msgs[i])); 256 } 257 258 ret->mem_ctx = talloc_new(NULL); 259 if (ret->mem_ctx == NULL) { 260 Py_DECREF(list); 261 Py_DECREF(ret); 262 PyErr_NoMemory(); 263 return NULL; 264 } 265 266 ret->msgs = list; 267 268 if (result->controls) { 269 controls = PyList_New(1); 270 if (controls == NULL) { 271 Py_DECREF(ret); 272 PyErr_NoMemory(); 273 return NULL; 274 } 275 for (i=0; result->controls[i]; i++) { 276 PyObject *ctrl = (PyObject*) PyLdbControl_FromControl(result->controls[i]); 277 if (ctrl == NULL) { 278 Py_DECREF(ret); 279 Py_DECREF(controls); 280 PyErr_NoMemory(); 281 return NULL; 282 } 283 PyList_SetItem(controls, i, ctrl); 284 } 285 } else { 286 /* 287 * No controls so we keep an empty list 288 */ 289 controls = PyList_New(0); 290 if (controls == NULL) { 291 Py_DECREF(ret); 292 PyErr_NoMemory(); 293 return NULL; 294 } 295 } 296 297 ret->controls = controls; 298 299 i = 0; 300 301 while (result->refs && result->refs[i]) { 302 i++; 303 } 304 305 referals = PyList_New(i); 306 if (referals == NULL) { 307 Py_DECREF(ret); 308 PyErr_NoMemory(); 309 return NULL; 310 } 311 312 for (i = 0;result->refs && result->refs[i]; i++) { 313 PyList_SetItem(referals, i, PyString_FromString(result->refs[i])); 314 } 315 ret->referals = referals; 316 return (PyObject *)ret; 128 317 } 129 318 … … 137 326 */ 138 327 static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, 139 328 PyObject *obj) 140 329 { 141 330 struct ldb_result *res; 142 int i;331 Py_ssize_t i; 143 332 144 333 if (obj == Py_None) … … 296 485 "S.canonical_ex_str() -> string\n" 297 486 "Canonical version of this DN (like a posix path, with terminating newline)." }, 298 { "check_special", (PyCFunction)py_ldb_dn_is_special, METH_VARARGS,299 NULL },300 487 { "parent", (PyCFunction)py_ldb_dn_get_parent, METH_NOARGS, 301 488 "S.parent() -> dn\n" … … 308 495 "Add a base DN to this DN." }, 309 496 { "check_special", (PyCFunction)py_ldb_dn_check_special, METH_VARARGS, 310 NULL }, 497 "S.check_special(name) -> bool\n\n" 498 "Check if name is a special DN name"}, 311 499 { NULL } 312 500 }; … … 366 554 367 555 ret = ldb_dn_new(mem_ctx, ldb_ctx, str); 368 369 if (ret == NULL || !ldb_dn_validate(ret)) { 556 if (!ldb_dn_validate(ret)) { 370 557 talloc_free(mem_ctx); 371 558 PyErr_SetString(PyExc_ValueError, "unable to parse dn string"); … … 384 571 } 385 572 386 PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)387 {388 PyLdbDnObject *py_ret;389 390 if (dn == NULL) {391 Py_RETURN_NONE;392 }393 394 py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);395 if (py_ret == NULL) {396 PyErr_NoMemory();397 return NULL;398 }399 py_ret->mem_ctx = talloc_new(NULL);400 py_ret->dn = talloc_reference(py_ret->mem_ctx, dn);401 return (PyObject *)py_ret;402 }403 404 573 static void py_ldb_dn_dealloc(PyLdbDnObject *self) 405 574 { 406 575 talloc_free(self->mem_ctx); 407 self->ob_type->tp_free(self);408 } 409 410 PyTypeObject PyLdbDn = {411 .tp_name = " Dn",576 PyObject_Del(self); 577 } 578 579 static PyTypeObject PyLdbDn = { 580 .tp_name = "ldb.Dn", 412 581 .tp_methods = py_ldb_dn_methods, 413 582 .tp_str = (reprfunc)py_ldb_dn_get_linearized, … … 418 587 .tp_new = py_ldb_dn_new, 419 588 .tp_dealloc = (destructor)py_ldb_dn_dealloc, 420 .tp_basicsize = sizeof(PyLdb Object),589 .tp_basicsize = sizeof(PyLdbDnObject), 421 590 .tp_flags = Py_TPFLAGS_DEFAULT, 422 591 }; … … 475 644 { 476 645 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self)); 646 Py_RETURN_NONE; 647 } 648 649 static PyObject *py_ldb_transaction_prepare_commit(PyLdbObject *self) 650 { 651 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_prepare_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self)); 477 652 Py_RETURN_NONE; 478 653 } … … 529 704 530 705 static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list, 531 706 const char *paramname) 532 707 { 533 708 const char **ret; 534 int i;709 Py_ssize_t i; 535 710 if (!PyList_Check(list)) { 536 711 PyErr_Format(PyExc_TypeError, "%s is not a list", paramname); … … 538 713 } 539 714 ret = talloc_array(NULL, const char *, PyList_Size(list)+1); 715 if (ret == NULL) { 716 PyErr_NoMemory(); 717 return NULL; 718 } 719 540 720 for (i = 0; i < PyList_Size(list); i++) { 541 721 PyObject *item = PyList_GetItem(list, i); … … 545 725 } 546 726 ret[i] = talloc_strndup(ret, PyString_AsString(item), 547 727 PyString_Size(item)); 548 728 } 549 729 ret[i] = NULL; … … 642 822 { 643 823 PyObject *py_msg; 644 int ret; 645 if (!PyArg_ParseTuple(args, "O", &py_msg)) 646 return NULL; 647 648 if (!PyLdbMessage_Check(py_msg)) { 649 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); 650 return NULL; 651 } 652 653 ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg)); 654 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 655 656 Py_RETURN_NONE; 657 } 658 659 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args) 660 { 661 PyObject *py_msg; 662 int ret; 663 Py_ssize_t dict_pos, msg_pos; 664 struct ldb_message_element *msgel; 665 struct ldb_message *msg; 824 PyObject *py_controls = Py_None; 666 825 struct ldb_context *ldb_ctx; 667 826 struct ldb_request *req; 668 PyObject *key, *value; 669 PyObject *py_controls = Py_None; 827 struct ldb_control **parsed_controls; 828 struct ldb_message *msg; 829 int ret; 670 830 TALLOC_CTX *mem_ctx; 671 struct ldb_control **parsed_controls; 672 673 if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls )) 674 return NULL; 831 832 if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls)) 833 return NULL; 834 835 mem_ctx = talloc_new(NULL); 836 if (mem_ctx == NULL) { 837 PyErr_NoMemory(); 838 return NULL; 839 } 675 840 ldb_ctx = PyLdb_AsLdbContext(self); 676 841 677 mem_ctx = talloc_new(NULL);678 842 if (py_controls == Py_None) { 679 843 parsed_controls = NULL; 680 844 } else { 681 const char **controls = PyList_AsStringList( ldb_ctx, py_controls, "controls");682 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);845 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 846 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 683 847 talloc_free(controls); 684 848 } 685 if (PyDict_Check(py_msg)) { 686 PyObject *dn_value = PyDict_GetItemString(py_msg, "dn"); 687 msg = ldb_msg_new(mem_ctx); 688 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg)); 689 msg_pos = dict_pos = 0; 690 if (dn_value) { 691 if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) { 692 PyErr_SetString(PyExc_TypeError, "unable to import dn object"); 693 talloc_free(mem_ctx); 694 return NULL; 695 } 696 if (msg->dn == NULL) { 697 PyErr_SetString(PyExc_TypeError, "dn set but not found"); 698 talloc_free(mem_ctx); 699 return NULL; 700 } 701 } 702 703 while (PyDict_Next(py_msg, &dict_pos, &key, &value)) { 704 char *key_str = PyString_AsString(key); 705 if (strcmp(key_str, "dn") != 0) { 706 msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str); 707 if (msgel == NULL) { 708 PyErr_SetString(PyExc_TypeError, "unable to import element"); 709 talloc_free(mem_ctx); 710 return NULL; 711 } 712 memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel)); 713 msg_pos++; 714 } 715 } 716 717 if (msg->dn == NULL) { 718 PyErr_SetString(PyExc_TypeError, "no dn set"); 719 talloc_free(mem_ctx); 720 return NULL; 721 } 722 723 msg->num_elements = msg_pos; 724 } else { 725 msg = PyLdbMessage_AsMessage(py_msg); 726 } 727 849 850 if (!PyLdbMessage_Check(py_msg)) { 851 PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); 852 talloc_free(mem_ctx); 853 return NULL; 854 } 855 msg = PyLdbMessage_AsMessage(py_msg); 856 728 857 ret = ldb_msg_sanity_check(ldb_ctx, msg); 729 730 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));858 if (ret != LDB_SUCCESS) { 859 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 731 860 talloc_free(mem_ctx); 732 861 return NULL; 733 } 734 735 ret = ldb_build_add_req(&req, ldb_ctx, ldb_ctx, 736 msg, 737 parsed_controls, 738 NULL, 739 ldb_op_default_callback, 740 NULL); 741 862 } 863 864 ret = ldb_build_mod_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, 865 NULL, ldb_op_default_callback, NULL); 742 866 if (ret != LDB_SUCCESS) { 743 867 PyErr_SetString(PyExc_TypeError, "failed to build request"); … … 746 870 } 747 871 748 872 /* do request and autostart a transaction */ 749 873 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 750 874 751 ret = ldb_transaction_start(ldb_ctx); 752 if (ret != LDB_SUCCESS) { 753 talloc_free(req); 875 ret = ldb_transaction_start(ldb_ctx); 876 if (ret != LDB_SUCCESS) { 754 877 talloc_free(mem_ctx); 755 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 756 } 757 758 ret = ldb_request(ldb_ctx, req); 759 if (ret == LDB_SUCCESS) { 760 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 761 } 762 878 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 879 } 880 881 ret = ldb_request(ldb_ctx, req); 763 882 if (ret == LDB_SUCCESS) { 764 ret = ldb_transaction_commit(ldb_ctx); 765 } else { 766 ldb_transaction_cancel(ldb_ctx); 883 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 884 } 885 886 if (ret == LDB_SUCCESS) { 887 ret = ldb_transaction_commit(ldb_ctx); 888 } else { 889 ldb_transaction_cancel(ldb_ctx); 767 890 if (ldb_ctx->err_string == NULL) { 768 891 /* no error string was setup by the backend */ … … 770 893 } 771 894 } 772 talloc_free(req); 895 773 896 talloc_free(mem_ctx); 774 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); 897 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 898 899 Py_RETURN_NONE; 900 } 901 902 903 /** 904 * Obtain a ldb message from a Python Dictionary object. 905 * 906 * @param mem_ctx Memory context 907 * @param py_obj Python Dictionary object 908 * @param ldb_ctx LDB context 909 * @param mod_flags Flags to be set on every message element 910 * @return ldb_message on success or NULL on failure 911 */ 912 static struct ldb_message *PyDict_AsMessage(TALLOC_CTX *mem_ctx, 913 PyObject *py_obj, 914 struct ldb_context *ldb_ctx, 915 unsigned int mod_flags) 916 { 917 struct ldb_message *msg; 918 unsigned int msg_pos = 0; 919 Py_ssize_t dict_pos = 0; 920 PyObject *key, *value; 921 struct ldb_message_element *msg_el; 922 PyObject *dn_value = PyDict_GetItemString(py_obj, "dn"); 923 924 msg = ldb_msg_new(mem_ctx); 925 msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_obj)); 926 927 if (dn_value) { 928 if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) { 929 PyErr_SetString(PyExc_TypeError, "unable to import dn object"); 930 return NULL; 931 } 932 if (msg->dn == NULL) { 933 PyErr_SetString(PyExc_TypeError, "dn set but not found"); 934 return NULL; 935 } 936 } else { 937 PyErr_SetString(PyExc_TypeError, "no dn set"); 938 return NULL; 939 } 940 941 while (PyDict_Next(py_obj, &dict_pos, &key, &value)) { 942 char *key_str = PyString_AsString(key); 943 if (strcmp(key_str, "dn") != 0) { 944 msg_el = PyObject_AsMessageElement(msg->elements, value, 945 mod_flags, key_str); 946 if (msg_el == NULL) { 947 PyErr_SetString(PyExc_TypeError, "unable to import element"); 948 return NULL; 949 } 950 memcpy(&msg->elements[msg_pos], msg_el, sizeof(*msg_el)); 951 msg_pos++; 952 } 953 } 954 955 msg->num_elements = msg_pos; 956 957 return msg; 958 } 959 960 static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args) 961 { 962 PyObject *py_obj; 963 int ret; 964 struct ldb_context *ldb_ctx; 965 struct ldb_request *req; 966 struct ldb_message *msg = NULL; 967 PyObject *py_controls = Py_None; 968 TALLOC_CTX *mem_ctx; 969 struct ldb_control **parsed_controls; 970 971 if (!PyArg_ParseTuple(args, "O|O", &py_obj, &py_controls )) 972 return NULL; 973 974 mem_ctx = talloc_new(NULL); 975 if (mem_ctx == NULL) { 976 PyErr_NoMemory(); 977 return NULL; 978 } 979 ldb_ctx = PyLdb_AsLdbContext(self); 980 981 if (py_controls == Py_None) { 982 parsed_controls = NULL; 983 } else { 984 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 985 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 986 talloc_free(controls); 987 } 988 989 if (PyLdbMessage_Check(py_obj)) { 990 msg = PyLdbMessage_AsMessage(py_obj); 991 } else if (PyDict_Check(py_obj)) { 992 msg = PyDict_AsMessage(mem_ctx, py_obj, ldb_ctx, LDB_FLAG_MOD_ADD); 993 } else { 994 PyErr_SetString(PyExc_TypeError, 995 "Dictionary or LdbMessage object expected!"); 996 } 997 998 if (!msg) { 999 /* we should have a PyErr already set */ 1000 talloc_free(mem_ctx); 1001 return NULL; 1002 } 1003 1004 ret = ldb_msg_sanity_check(ldb_ctx, msg); 1005 if (ret != LDB_SUCCESS) { 1006 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1007 talloc_free(mem_ctx); 1008 return NULL; 1009 } 1010 1011 ret = ldb_build_add_req(&req, ldb_ctx, mem_ctx, msg, parsed_controls, 1012 NULL, ldb_op_default_callback, NULL); 1013 if (ret != LDB_SUCCESS) { 1014 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1015 talloc_free(mem_ctx); 1016 return NULL; 1017 } 1018 1019 /* do request and autostart a transaction */ 1020 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1021 1022 ret = ldb_transaction_start(ldb_ctx); 1023 if (ret != LDB_SUCCESS) { 1024 talloc_free(mem_ctx); 1025 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1026 } 1027 1028 ret = ldb_request(ldb_ctx, req); 1029 if (ret == LDB_SUCCESS) { 1030 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1031 } 1032 1033 if (ret == LDB_SUCCESS) { 1034 ret = ldb_transaction_commit(ldb_ctx); 1035 } else { 1036 ldb_transaction_cancel(ldb_ctx); 1037 if (ldb_ctx->err_string == NULL) { 1038 /* no error string was setup by the backend */ 1039 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1040 } 1041 } 1042 1043 talloc_free(mem_ctx); 1044 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 775 1045 776 1046 Py_RETURN_NONE; … … 782 1052 struct ldb_dn *dn; 783 1053 int ret; 784 struct ldb_context *ldb; 785 if (!PyArg_ParseTuple(args, "O", &py_dn)) 786 return NULL; 787 788 ldb = PyLdb_AsLdbContext(self); 789 790 if (!PyObject_AsDn(NULL, py_dn, ldb, &dn)) 791 return NULL; 792 793 ret = ldb_delete(ldb, dn); 794 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); 1054 struct ldb_context *ldb_ctx; 1055 struct ldb_request *req; 1056 PyObject *py_controls = Py_None; 1057 TALLOC_CTX *mem_ctx; 1058 struct ldb_control **parsed_controls; 1059 1060 if (!PyArg_ParseTuple(args, "O|O", &py_dn, &py_controls)) 1061 return NULL; 1062 1063 mem_ctx = talloc_new(NULL); 1064 if (mem_ctx == NULL) { 1065 PyErr_NoMemory(); 1066 return NULL; 1067 } 1068 ldb_ctx = PyLdb_AsLdbContext(self); 1069 1070 if (py_controls == Py_None) { 1071 parsed_controls = NULL; 1072 } else { 1073 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1074 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1075 talloc_free(controls); 1076 } 1077 1078 if (!PyObject_AsDn(mem_ctx, py_dn, ldb_ctx, &dn)) { 1079 talloc_free(mem_ctx); 1080 return NULL; 1081 } 1082 1083 ret = ldb_build_del_req(&req, ldb_ctx, mem_ctx, dn, parsed_controls, 1084 NULL, ldb_op_default_callback, NULL); 1085 if (ret != LDB_SUCCESS) { 1086 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1087 talloc_free(mem_ctx); 1088 return NULL; 1089 } 1090 1091 /* do request and autostart a transaction */ 1092 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1093 1094 ret = ldb_transaction_start(ldb_ctx); 1095 if (ret != LDB_SUCCESS) { 1096 talloc_free(mem_ctx); 1097 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1098 } 1099 1100 ret = ldb_request(ldb_ctx, req); 1101 if (ret == LDB_SUCCESS) { 1102 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1103 } 1104 1105 if (ret == LDB_SUCCESS) { 1106 ret = ldb_transaction_commit(ldb_ctx); 1107 } else { 1108 ldb_transaction_cancel(ldb_ctx); 1109 if (ldb_ctx->err_string == NULL) { 1110 /* no error string was setup by the backend */ 1111 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1112 } 1113 } 1114 1115 talloc_free(mem_ctx); 1116 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 795 1117 796 1118 Py_RETURN_NONE; … … 804 1126 struct ldb_context *ldb; 805 1127 TALLOC_CTX *mem_ctx; 806 if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2)) 807 return NULL; 1128 PyObject *py_controls = Py_None; 1129 struct ldb_control **parsed_controls; 1130 struct ldb_context *ldb_ctx; 1131 struct ldb_request *req; 1132 1133 ldb_ctx = PyLdb_AsLdbContext(self); 1134 1135 if (!PyArg_ParseTuple(args, "OO|O", &py_dn1, &py_dn2, &py_controls)) 1136 return NULL; 1137 808 1138 809 1139 mem_ctx = talloc_new(NULL); … … 813 1143 } 814 1144 ldb = PyLdb_AsLdbContext(self); 1145 1146 if (py_controls == Py_None) { 1147 parsed_controls = NULL; 1148 } else { 1149 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1150 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1151 talloc_free(controls); 1152 } 1153 1154 815 1155 if (!PyObject_AsDn(mem_ctx, py_dn1, ldb, &dn1)) { 816 1156 talloc_free(mem_ctx); … … 823 1163 } 824 1164 825 ret = ldb_rename(ldb, dn1, dn2); 1165 ret = ldb_build_rename_req(&req, ldb_ctx, mem_ctx, dn1, dn2, parsed_controls, 1166 NULL, ldb_op_default_callback, NULL); 1167 if (ret != LDB_SUCCESS) { 1168 PyErr_SetString(PyExc_TypeError, "failed to build request"); 1169 talloc_free(mem_ctx); 1170 return NULL; 1171 } 1172 1173 /* do request and autostart a transaction */ 1174 /* Then let's LDB handle the message error in case of pb as they are meaningful */ 1175 1176 ret = ldb_transaction_start(ldb_ctx); 1177 if (ret != LDB_SUCCESS) { 1178 talloc_free(mem_ctx); 1179 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1180 } 1181 1182 ret = ldb_request(ldb_ctx, req); 1183 if (ret == LDB_SUCCESS) { 1184 ret = ldb_wait(req->handle, LDB_WAIT_ALL); 1185 } 1186 1187 if (ret == LDB_SUCCESS) { 1188 ret = ldb_transaction_commit(ldb_ctx); 1189 } else { 1190 ldb_transaction_cancel(ldb_ctx); 1191 if (ldb_ctx->err_string == NULL) { 1192 /* no error string was setup by the backend */ 1193 ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); 1194 } 1195 } 1196 826 1197 talloc_free(mem_ctx); 827 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb );1198 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 828 1199 829 1200 Py_RETURN_NONE; … … 869 1240 870 1241 871 static PyObject *py_ldb_write_ldif(PyLdb MessageObject *self, PyObject *args)1242 static PyObject *py_ldb_write_ldif(PyLdbObject *self, PyObject *args) 872 1243 { 873 1244 int changetype; … … 938 1309 static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args) 939 1310 { 1311 int ldb_ret; 940 1312 PyObject *py_msg_old; 941 1313 PyObject *py_msg_new; 942 1314 struct ldb_message *diff; 1315 struct ldb_context *ldb; 943 1316 PyObject *py_ret; 944 1317 … … 956 1329 } 957 1330 958 diff = ldb_msg_diff(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg_old), PyLdbMessage_AsMessage(py_msg_new)); 959 if (diff == NULL) 960 return NULL; 1331 ldb = PyLdb_AsLdbContext(self); 1332 ldb_ret = ldb_msg_difference(ldb, ldb, 1333 PyLdbMessage_AsMessage(py_msg_old), 1334 PyLdbMessage_AsMessage(py_msg_new), 1335 &diff); 1336 if (ldb_ret != LDB_SUCCESS) { 1337 PyErr_SetString(PyExc_RuntimeError, "Failed to generate the Ldb Message diff"); 1338 return NULL; 1339 } 961 1340 962 1341 py_ret = PyLdbMessage_FromMessage(diff); 1342 1343 talloc_unlink(ldb, diff); 963 1344 964 1345 return py_ret; … … 1004 1385 { 1005 1386 PyObject *py_base = Py_None; 1006 enum ldb_scopescope = LDB_SCOPE_DEFAULT;1387 int scope = LDB_SCOPE_DEFAULT; 1007 1388 char *expr = NULL; 1008 1389 PyObject *py_attrs = Py_None; … … 1017 1398 struct ldb_dn *base; 1018 1399 PyObject *py_ret; 1019 1400 TALLOC_CTX *mem_ctx; 1401 1402 /* type "int" rather than "enum" for "scope" is intentional */ 1020 1403 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO", 1021 1404 discard_const_p(char *, kwnames), … … 1023 1406 return NULL; 1024 1407 1408 1409 mem_ctx = talloc_new(NULL); 1410 if (mem_ctx == NULL) { 1411 PyErr_NoMemory(); 1412 return NULL; 1413 } 1025 1414 ldb_ctx = PyLdb_AsLdbContext(self); 1026 1415 … … 1028 1417 attrs = NULL; 1029 1418 } else { 1030 attrs = PyList_AsStringList(NULL, py_attrs, "attrs"); 1031 if (attrs == NULL) 1419 attrs = PyList_AsStringList(mem_ctx, py_attrs, "attrs"); 1420 if (attrs == NULL) { 1421 talloc_free(mem_ctx); 1032 1422 return NULL; 1423 } 1033 1424 } 1034 1425 … … 1045 1436 parsed_controls = NULL; 1046 1437 } else { 1047 const char **controls = PyList_AsStringList( ldb_ctx, py_controls, "controls");1048 parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);1438 const char **controls = PyList_AsStringList(mem_ctx, py_controls, "controls"); 1439 parsed_controls = ldb_parse_control_strings(ldb_ctx, mem_ctx, controls); 1049 1440 talloc_free(controls); 1050 1441 } 1051 1442 1052 res = talloc_zero( ldb_ctx, struct ldb_result);1443 res = talloc_zero(mem_ctx, struct ldb_result); 1053 1444 if (res == NULL) { 1054 1445 PyErr_NoMemory(); 1055 talloc_free( attrs);1056 return NULL; 1057 } 1058 1059 ret = ldb_build_search_req(&req, ldb_ctx, ldb_ctx,1446 talloc_free(mem_ctx); 1447 return NULL; 1448 } 1449 1450 ret = ldb_build_search_req(&req, ldb_ctx, mem_ctx, 1060 1451 base, 1061 1452 scope, … … 1067 1458 NULL); 1068 1459 1460 if (ret != LDB_SUCCESS) { 1461 talloc_free(mem_ctx); 1462 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1463 return NULL; 1464 } 1465 1069 1466 talloc_steal(req, attrs); 1070 1071 if (ret != LDB_SUCCESS) {1072 talloc_free(res);1073 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);1074 return NULL;1075 }1076 1467 1077 1468 ret = ldb_request(ldb_ctx, req); … … 1081 1472 } 1082 1473 1083 talloc_free(req);1084 1085 1474 if (ret != LDB_SUCCESS) { 1086 talloc_free( res);1475 talloc_free(mem_ctx); 1087 1476 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx); 1088 1477 return NULL; … … 1091 1480 py_ret = PyLdbResult_FromResult(res); 1092 1481 1093 talloc_free( res);1482 talloc_free(mem_ctx); 1094 1483 1095 1484 return py_ret; … … 1142 1531 } 1143 1532 1533 static PyObject *py_ldb_sequence_number(PyLdbObject *self, PyObject *args) 1534 { 1535 struct ldb_context *ldb = PyLdb_AsLdbContext(self); 1536 int type, ret; 1537 uint64_t value; 1538 1539 if (!PyArg_ParseTuple(args, "i", &type)) 1540 return NULL; 1541 1542 /* FIXME: More interpretation */ 1543 1544 ret = ldb_sequence_number(ldb, type, &value); 1545 1546 if (ret != LDB_SUCCESS) { 1547 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb); 1548 return NULL; 1549 } 1550 return PyLong_FromLongLong(value); 1551 } 1144 1552 static PyMethodDef py_ldb_methods[] = { 1145 1553 { "set_debug", (PyCFunction)py_ldb_set_debug, METH_VARARGS, … … 1156 1564 "S.transaction_start() -> None\n" 1157 1565 "Start a new transaction." }, 1566 { "transaction_prepare_commit", (PyCFunction)py_ldb_transaction_prepare_commit, METH_NOARGS, 1567 "S.transaction_prepare_commit() -> None\n" 1568 "prepare to commit a new transaction (2-stage commit)." }, 1158 1569 { "transaction_commit", (PyCFunction)py_ldb_transaction_commit, METH_NOARGS, 1159 1570 "S.transaction_commit() -> None\n" … … 1225 1636 "S.modules() -> list\n" 1226 1637 "Return the list of modules on this LDB connection " }, 1638 { "sequence_number", (PyCFunction)py_ldb_sequence_number, METH_VARARGS, 1639 "S.sequence_number(type) -> value\n" 1640 "Return the value of the sequence according to the requested type" }, 1227 1641 { NULL }, 1228 1642 }; 1229 1643 1230 PyObject *PyLdbModule_FromModule(struct ldb_module *mod)1644 static PyObject *PyLdbModule_FromModule(struct ldb_module *mod) 1231 1645 { 1232 1646 PyLdbModuleObject *ret; … … 1257 1671 struct ldb_dn *dn; 1258 1672 struct ldb_result *result; 1673 unsigned int count; 1259 1674 int ret; 1260 int count; 1261 1262 if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) 1675 1676 if (!PyObject_AsDn(ldb_ctx, obj, ldb_ctx, &dn)) { 1263 1677 return -1; 1264 1265 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL); 1678 } 1679 1680 ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, 1681 NULL); 1266 1682 if (ret != LDB_SUCCESS) { 1267 1683 PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx); … … 1273 1689 talloc_free(result); 1274 1690 1691 if (count > 1) { 1692 PyErr_Format(PyExc_RuntimeError, 1693 "Searching for [%s] dn gave %u results!", 1694 ldb_dn_get_linearized(dn), 1695 count); 1696 return -1; 1697 } 1698 1275 1699 return count; 1276 1700 } … … 1280 1704 }; 1281 1705 1282 PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx)1706 static PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx) 1283 1707 { 1284 1708 PyLdbObject *ret; … … 1300 1724 } 1301 1725 1302 PyTypeObject PyLdb = {1303 .tp_name = " Ldb",1726 static PyTypeObject PyLdb = { 1727 .tp_name = "ldb.Ldb", 1304 1728 .tp_methods = py_ldb_methods, 1305 1729 .tp_repr = (reprfunc)py_ldb_repr, … … 1315 1739 }; 1316 1740 1741 static void py_ldb_result_dealloc(PyLdbResultObject *self) 1742 { 1743 talloc_free(self->mem_ctx); 1744 Py_DECREF(self->msgs); 1745 Py_DECREF(self->referals); 1746 Py_DECREF(self->controls); 1747 self->ob_type->tp_free(self); 1748 } 1749 1750 static PyObject *py_ldb_result_get_msgs(PyLdbResultObject *self, void *closure) 1751 { 1752 Py_INCREF(self->msgs); 1753 return self->msgs; 1754 } 1755 1756 static PyObject *py_ldb_result_get_controls(PyLdbResultObject *self, void *closure) 1757 { 1758 Py_INCREF(self->controls); 1759 return self->controls; 1760 } 1761 1762 static PyObject *py_ldb_result_get_referals(PyLdbResultObject *self, void *closure) 1763 { 1764 Py_INCREF(self->referals); 1765 return self->referals; 1766 } 1767 1768 static PyObject *py_ldb_result_get_count(PyLdbResultObject *self, void *closure) 1769 { 1770 Py_ssize_t size; 1771 if (self->msgs == NULL) { 1772 PyErr_SetString(PyExc_AttributeError, "Count attribute is meaningless in this context"); 1773 return NULL; 1774 } 1775 size = PyList_Size(self->msgs); 1776 return PyInt_FromLong(size); 1777 } 1778 1779 static PyGetSetDef py_ldb_result_getset[] = { 1780 { discard_const_p(char, "controls"), (getter)py_ldb_result_get_controls, NULL, NULL }, 1781 { discard_const_p(char, "msgs"), (getter)py_ldb_result_get_msgs, NULL, NULL }, 1782 { discard_const_p(char, "referals"), (getter)py_ldb_result_get_referals, NULL, NULL }, 1783 { discard_const_p(char, "count"), (getter)py_ldb_result_get_count, NULL, NULL }, 1784 { NULL } 1785 }; 1786 1787 static PyObject *py_ldb_result_iter(PyLdbResultObject *self) 1788 { 1789 return PyObject_GetIter(self->msgs); 1790 } 1791 1792 static Py_ssize_t py_ldb_result_len(PyLdbResultObject *self) 1793 { 1794 return PySequence_Size(self->msgs); 1795 } 1796 1797 static PyObject *py_ldb_result_find(PyLdbResultObject *self, Py_ssize_t idx) 1798 { 1799 return PySequence_GetItem(self->msgs, idx); 1800 } 1801 1802 static PySequenceMethods py_ldb_result_seq = { 1803 .sq_length = (lenfunc)py_ldb_result_len, 1804 .sq_item = (ssizeargfunc)py_ldb_result_find, 1805 }; 1806 1807 static PyObject *py_ldb_result_repr(PyLdbObject *self) 1808 { 1809 return PyString_FromFormat("<ldb result>"); 1810 } 1811 1812 1813 static PyTypeObject PyLdbResult = { 1814 .tp_name = "ldb.Result", 1815 .tp_repr = (reprfunc)py_ldb_result_repr, 1816 .tp_dealloc = (destructor)py_ldb_result_dealloc, 1817 .tp_iter = (getiterfunc)py_ldb_result_iter, 1818 .tp_getset = py_ldb_result_getset, 1819 .tp_getattro = PyObject_GenericGetAttr, 1820 .tp_basicsize = sizeof(PyLdbResultObject), 1821 .tp_as_sequence = &py_ldb_result_seq, 1822 .tp_doc = "LDB result.", 1823 .tp_flags = Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, 1824 }; 1825 1317 1826 static PyObject *py_ldb_module_repr(PyLdbModuleObject *self) 1318 1827 { … … 1352 1861 const char * const*attrs; 1353 1862 1863 /* type "int" rather than "enum" for "scope" is intentional */ 1354 1864 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO", 1355 1865 discard_const_p(char *, kwnames), … … 1490 2000 { 1491 2001 talloc_free(self->mem_ctx); 1492 self->ob_type->tp_free(self);1493 } 1494 1495 PyTypeObject PyLdbModule = {1496 .tp_name = " LdbModule",2002 PyObject_Del(self); 2003 } 2004 2005 static PyTypeObject PyLdbModule = { 2006 .tp_name = "ldb.LdbModule", 1497 2007 .tp_methods = py_ldb_module_methods, 1498 2008 .tp_repr = (reprfunc)py_ldb_module_repr, … … 1518 2028 * @return New ldb_message_element, allocated as child of mem_ctx 1519 2029 */ 1520 struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx, 1521 PyObject *set_obj, int flags, 1522 const char *attr_name) 2030 static struct ldb_message_element *PyObject_AsMessageElement( 2031 TALLOC_CTX *mem_ctx, 2032 PyObject *set_obj, 2033 int flags, 2034 const char *attr_name) 1523 2035 { 1524 2036 struct ldb_message_element *me; 1525 2037 1526 if (PyLdbMessageElement_Check(set_obj)) 1527 return talloc_reference(mem_ctx, 1528 PyLdbMessageElement_AsMessageElement(set_obj)); 2038 if (PyLdbMessageElement_Check(set_obj)) { 2039 PyLdbMessageElementObject *set_obj_as_me = (PyLdbMessageElementObject *)set_obj; 2040 /* We have to talloc_reference() the memory context, not the pointer 2041 * which may not actually be it's own context */ 2042 if (talloc_reference(mem_ctx, set_obj_as_me->mem_ctx)) { 2043 return PyLdbMessageElement_AsMessageElement(set_obj); 2044 } 2045 return NULL; 2046 } 1529 2047 1530 2048 me = talloc(mem_ctx, struct ldb_message_element); 2049 if (me == NULL) { 2050 PyErr_NoMemory(); 2051 return NULL; 2052 } 1531 2053 1532 2054 me->name = talloc_strdup(me, attr_name); … … 1537 2059 me->values[0].length = PyString_Size(set_obj); 1538 2060 me->values[0].data = talloc_memdup(me, 1539 (uint8_t *)PyString_AsString(set_obj), me->values[0].length );2061 (uint8_t *)PyString_AsString(set_obj), me->values[0].length+1); 1540 2062 } else if (PySequence_Check(set_obj)) { 1541 int i;2063 Py_ssize_t i; 1542 2064 me->num_values = PySequence_Size(set_obj); 1543 2065 me->values = talloc_array(me, struct ldb_val, me->num_values); 1544 2066 for (i = 0; i < me->num_values; i++) { 1545 2067 PyObject *obj = PySequence_GetItem(set_obj, i); 2068 if (!PyString_Check(obj)) { 2069 PyErr_Format(PyExc_TypeError, 2070 "Expected string as element %zd in list", i); 2071 talloc_free(me); 2072 return NULL; 2073 } 1546 2074 1547 2075 me->values[i].length = PyString_Size(obj); 1548 2076 me->values[i].data = talloc_memdup(me, 1549 (uint8_t *)PyString_AsString(obj), me->values[i].length );2077 (uint8_t *)PyString_AsString(obj), me->values[i].length+1); 1550 2078 } 1551 2079 } else { … … 1558 2086 1559 2087 1560 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 1561 1562 { 1563 int i;2088 static PyObject *ldb_msg_element_to_set(struct ldb_context *ldb_ctx, 2089 struct ldb_message_element *me) 2090 { 2091 Py_ssize_t i; 1564 2092 PyObject *result; 1565 2093 … … 1569 2097 for (i = 0; i < me->num_values; i++) { 1570 2098 PyList_SetItem(result, i, 1571 PyObject_FromLdbValue( ldb_ctx, me,&me->values[i]));2099 PyObject_FromLdbValue(&me->values[i])); 1572 2100 } 1573 2101 … … 1577 2105 static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObject *args) 1578 2106 { 1579 int i;1580 if (!PyArg_ParseTuple(args, " i", &i))1581 return NULL; 1582 if (i < 0 || i>= PyLdbMessageElement_AsMessageElement(self)->num_values)2107 unsigned int i; 2108 if (!PyArg_ParseTuple(args, "I", &i)) 2109 return NULL; 2110 if (i >= PyLdbMessageElement_AsMessageElement(self)->num_values) 1583 2111 Py_RETURN_NONE; 1584 2112 1585 return PyObject_FromLdbValue(NULL, PyLdbMessageElement_AsMessageElement(self), 1586 &(PyLdbMessageElement_AsMessageElement(self)->values[i])); 2113 return PyObject_FromLdbValue(&(PyLdbMessageElement_AsMessageElement(self)->values[i])); 1587 2114 } 1588 2115 1589 2116 static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args) 1590 2117 { 1591 struct ldb_message_element *el; 1592 1593 el = PyLdbMessageElement_AsMessageElement(self); 2118 struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self); 1594 2119 return PyInt_FromLong(el->flags); 1595 2120 } … … 1636 2161 static int py_ldb_msg_element_cmp(PyLdbMessageElementObject *self, PyLdbMessageElementObject *other) 1637 2162 { 1638 return ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 1639 PyLdbMessageElement_AsMessageElement(other)); 2163 int ret = ldb_msg_element_compare(PyLdbMessageElement_AsMessageElement(self), 2164 PyLdbMessageElement_AsMessageElement(other)); 2165 return SIGN(ret); 1640 2166 } 1641 2167 … … 1645 2171 } 1646 2172 1647 PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx)2173 static PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *el, TALLOC_CTX *mem_ctx) 1648 2174 { 1649 2175 PyLdbMessageElementObject *ret; 1650 ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);2176 ret = PyObject_New(PyLdbMessageElementObject, &PyLdbMessageElement); 1651 2177 if (ret == NULL) { 1652 2178 PyErr_NoMemory(); … … 1684 2210 1685 2211 el = talloc_zero(mem_ctx, struct ldb_message_element); 2212 if (el == NULL) { 2213 PyErr_NoMemory(); 2214 talloc_free(mem_ctx); 2215 return NULL; 2216 } 1686 2217 1687 2218 if (py_elements != NULL) { 1688 int i;2219 Py_ssize_t i; 1689 2220 if (PyString_Check(py_elements)) { 1690 2221 el->num_values = 1; 1691 2222 el->values = talloc_array(el, struct ldb_val, 1); 2223 if (el->values == NULL) { 2224 talloc_free(mem_ctx); 2225 PyErr_NoMemory(); 2226 return NULL; 2227 } 1692 2228 el->values[0].length = PyString_Size(py_elements); 1693 el->values[0].data = talloc_memdup(el ,1694 (uint8_t *)PyString_AsString(py_elements), el->values[0].length );2229 el->values[0].data = talloc_memdup(el->values, 2230 (uint8_t *)PyString_AsString(py_elements), el->values[0].length+1); 1695 2231 } else if (PySequence_Check(py_elements)) { 1696 2232 el->num_values = PySequence_Size(py_elements); 1697 2233 el->values = talloc_array(el, struct ldb_val, el->num_values); 2234 if (el->values == NULL) { 2235 talloc_free(mem_ctx); 2236 PyErr_NoMemory(); 2237 return NULL; 2238 } 1698 2239 for (i = 0; i < el->num_values; i++) { 1699 2240 PyObject *item = PySequence_GetItem(py_elements, i); 2241 if (item == NULL) { 2242 talloc_free(mem_ctx); 2243 return NULL; 2244 } 1700 2245 if (!PyString_Check(item)) { 1701 2246 PyErr_Format(PyExc_TypeError, 1702 "Expected string as element %d in list", 1703 i); 2247 "Expected string as element %zd in list", i); 1704 2248 talloc_free(mem_ctx); 1705 2249 return NULL; 1706 2250 } 1707 2251 el->values[i].length = PyString_Size(item); 1708 el->values[i].data = talloc_memdup(el, 1709 (uint8_t *)PyString_AsString(item), el->values[i].length );2252 el->values[i].data = talloc_memdup(el, 2253 (uint8_t *)PyString_AsString(item), el->values[i].length+1); 1710 2254 } 1711 2255 } else { … … 1720 2264 el->name = talloc_strdup(el, name); 1721 2265 1722 ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);2266 ret = PyObject_New(PyLdbMessageElementObject, type); 1723 2267 if (ret == NULL) { 1724 PyErr_NoMemory();1725 2268 talloc_free(mem_ctx); 1726 2269 return NULL; … … 1735 2278 { 1736 2279 char *element_str = NULL; 1737 int i;2280 Py_ssize_t i; 1738 2281 struct ldb_message_element *el = PyLdbMessageElement_AsMessageElement(self); 1739 2282 PyObject *ret; … … 1747 2290 } 1748 2291 1749 ret = PyString_FromFormat("MessageElement([%s])", element_str); 1750 1751 talloc_free(element_str); 2292 if (element_str != NULL) { 2293 ret = PyString_FromFormat("MessageElement([%s])", element_str); 2294 talloc_free(element_str); 2295 } else { 2296 ret = PyString_FromString("MessageElement([])"); 2297 } 1752 2298 1753 2299 return ret; … … 1760 2306 if (el->num_values == 1) 1761 2307 return PyString_FromStringAndSize((char *)el->values[0].data, el->values[0].length); 1762 else 2308 else 1763 2309 Py_RETURN_NONE; 1764 2310 } … … 1767 2313 { 1768 2314 talloc_free(self->mem_ctx); 1769 self->ob_type->tp_free(self);1770 } 1771 1772 PyTypeObject PyLdbMessageElement = {1773 .tp_name = " MessageElement",2315 PyObject_Del(self); 2316 } 2317 2318 static PyTypeObject PyLdbMessageElement = { 2319 .tp_name = "ldb.MessageElement", 1774 2320 .tp_basicsize = sizeof(PyLdbMessageElementObject), 1775 2321 .tp_dealloc = (destructor)py_ldb_msg_element_dealloc, … … 1784 2330 }; 1785 2331 2332 2333 static PyObject *py_ldb_msg_from_dict(PyTypeObject *type, PyObject *args) 2334 { 2335 PyObject *py_ldb; 2336 PyObject *py_dict; 2337 PyObject *py_ret; 2338 struct ldb_message *msg; 2339 struct ldb_context *ldb_ctx; 2340 unsigned int mod_flags = LDB_FLAG_MOD_REPLACE; 2341 2342 if (!PyArg_ParseTuple(args, "O!O!|I", 2343 &PyLdb, &py_ldb, &PyDict_Type, &py_dict, 2344 &mod_flags)) { 2345 return NULL; 2346 } 2347 2348 /* mask only flags we are going to use */ 2349 mod_flags = LDB_FLAG_MOD_TYPE(mod_flags); 2350 if (!mod_flags) { 2351 PyErr_SetString(PyExc_ValueError, 2352 "FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE" 2353 " expected as mod_flag value"); 2354 return NULL; 2355 } 2356 2357 ldb_ctx = PyLdb_AsLdbContext(py_ldb); 2358 2359 msg = PyDict_AsMessage(ldb_ctx, py_dict, ldb_ctx, mod_flags); 2360 if (!msg) { 2361 return NULL; 2362 } 2363 2364 py_ret = PyLdbMessage_FromMessage(msg); 2365 2366 talloc_unlink(ldb_ctx, msg); 2367 2368 return py_ret; 2369 } 2370 1786 2371 static PyObject *py_ldb_msg_remove_attr(PyLdbMessageObject *self, PyObject *args) 1787 2372 { … … 1798 2383 { 1799 2384 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 1800 int i, j = 0;2385 Py_ssize_t i, j = 0; 1801 2386 PyObject *obj = PyList_New(msg->num_elements+(msg->dn != NULL?1:0)); 1802 2387 if (msg->dn != NULL) { … … 1827 2412 return NULL; 1828 2413 } 1829 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg );2414 return (PyObject *)PyLdbMessageElement_FromMessageElement(el, msg->elements); 1830 2415 } 1831 2416 … … 1858 2443 { 1859 2444 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 1860 int i, j;2445 Py_ssize_t i, j = 0; 1861 2446 PyObject *l = PyList_New(msg->num_elements + (msg->dn == NULL?0:1)); 1862 j = 0;1863 2447 if (msg->dn != NULL) { 1864 2448 PyList_SetItem(l, 0, Py_BuildValue("(sO)", "dn", PyLdbDn_FromDn(msg->dn))); … … 1866 2450 } 1867 2451 for (i = 0; i < msg->num_elements; i++, j++) { 1868 PyList_SetItem(l, j, Py_BuildValue("(sO)", msg->elements[i].name, PyLdbMessageElement_FromMessageElement(&msg->elements[i], self->msg))); 2452 PyObject *py_el = PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements); 2453 PyObject *value = Py_BuildValue("(sO)", msg->elements[i].name, py_el); 2454 PyList_SetItem(l, j, value); 1869 2455 } 1870 2456 return l; 1871 2457 } 1872 2458 1873 static PyMethodDef py_ldb_msg_methods[] = { 1874 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, NULL }, 1875 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, NULL }, 2459 static PyObject *py_ldb_msg_elements(PyLdbMessageObject *self) 2460 { 2461 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 2462 Py_ssize_t i = 0; 2463 PyObject *l = PyList_New(msg->num_elements); 2464 for (i = 0; i < msg->num_elements; i++) { 2465 PyList_SetItem(l, i, PyLdbMessageElement_FromMessageElement(&msg->elements[i], msg->elements)); 2466 } 2467 return l; 2468 } 2469 2470 static PyObject *py_ldb_msg_add(PyLdbMessageObject *self, PyObject *args) 2471 { 2472 struct ldb_message *msg = PyLdbMessage_AsMessage(self); 2473 PyLdbMessageElementObject *py_element; 2474 int ret; 2475 struct ldb_message_element *el; 2476 2477 if (!PyArg_ParseTuple(args, "O!", &PyLdbMessageElement, &py_element)) 2478 return NULL; 2479 2480 el = talloc_reference(msg, py_element->el); 2481 if (el == NULL) { 2482 PyErr_NoMemory(); 2483 return NULL; 2484 } 2485 2486 ret = ldb_msg_add(msg, el, el->flags); 2487 PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL); 2488 2489 Py_RETURN_NONE; 2490 } 2491 2492 static PyMethodDef py_ldb_msg_methods[] = { 2493 { "from_dict", (PyCFunction)py_ldb_msg_from_dict, METH_CLASS | METH_VARARGS, 2494 "Message.from_dict(ldb, dict, mod_flag=FLAG_MOD_REPLACE) -> ldb.Message\n" 2495 "Class method to create ldb.Message object from Dictionary.\n" 2496 "mod_flag is one of FLAG_MOD_ADD, FLAG_MOD_REPLACE or FLAG_MOD_DELETE."}, 2497 { "keys", (PyCFunction)py_ldb_msg_keys, METH_NOARGS, 2498 "S.keys() -> list\n\n" 2499 "Return sequence of all attribute names." }, 2500 { "remove", (PyCFunction)py_ldb_msg_remove_attr, METH_VARARGS, 2501 "S.remove(name)\n\n" 2502 "Remove all entries for attributes with the specified name."}, 1876 2503 { "get", (PyCFunction)py_ldb_msg_get, METH_VARARGS, NULL }, 1877 2504 { "items", (PyCFunction)py_ldb_msg_items, METH_NOARGS, NULL }, 2505 { "elements", (PyCFunction)py_ldb_msg_elements, METH_NOARGS, NULL }, 2506 { "add", (PyCFunction)py_ldb_msg_add, METH_VARARGS, 2507 "S.append(element)\n\n" 2508 "Add an element to this message." }, 1878 2509 { NULL }, 1879 2510 }; … … 1897 2528 return -1; 1898 2529 } 1899 2530 1900 2531 attr_name = PyString_AsString(name); 1901 2532 if (value == NULL) { … … 1904 2535 } else { 1905 2536 struct ldb_message_element *el = PyObject_AsMessageElement(self->msg, 1906 2537 value, 0, attr_name); 1907 2538 if (el == NULL) 1908 2539 return -1; … … 1971 2602 } 1972 2603 1973 PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)2604 static PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg) 1974 2605 { 1975 2606 PyLdbMessageObject *ret; … … 2021 2652 { 2022 2653 talloc_free(self->mem_ctx); 2023 self->ob_type->tp_free(self); 2024 } 2025 2026 PyTypeObject PyLdbMessage = { 2027 .tp_name = "Message", 2654 PyObject_Del(self); 2655 } 2656 2657 static int py_ldb_msg_compare(PyLdbMessageObject *py_msg1, 2658 PyLdbMessageObject *py_msg2) 2659 { 2660 struct ldb_message *msg1 = PyLdbMessage_AsMessage(py_msg1), 2661 *msg2 = PyLdbMessage_AsMessage(py_msg2); 2662 unsigned int i; 2663 int ret; 2664 2665 if ((msg1->dn != NULL) || (msg2->dn != NULL)) { 2666 ret = ldb_dn_compare(msg1->dn, msg2->dn); 2667 if (ret != 0) { 2668 return SIGN(ret); 2669 } 2670 } 2671 2672 ret = msg1->num_elements - msg2->num_elements; 2673 if (ret != 0) { 2674 return SIGN(ret); 2675 } 2676 2677 for (i = 0; i < msg1->num_elements; i++) { 2678 ret = ldb_msg_element_compare_name(&msg1->elements[i], 2679 &msg2->elements[i]); 2680 if (ret != 0) { 2681 return SIGN(ret); 2682 } 2683 2684 ret = ldb_msg_element_compare(&msg1->elements[i], 2685 &msg2->elements[i]); 2686 if (ret != 0) { 2687 return SIGN(ret); 2688 } 2689 } 2690 2691 return 0; 2692 } 2693 2694 static PyTypeObject PyLdbMessage = { 2695 .tp_name = "ldb.Message", 2028 2696 .tp_methods = py_ldb_msg_methods, 2029 2697 .tp_getset = py_ldb_msg_getset, … … 2035 2703 .tp_flags = Py_TPFLAGS_DEFAULT, 2036 2704 .tp_iter = (getiterfunc)py_ldb_msg_iter, 2705 .tp_compare = (cmpfunc)py_ldb_msg_compare, 2037 2706 }; 2038 2707 2039 PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)2708 static PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree) 2040 2709 { 2041 2710 PyLdbTreeObject *ret; … … 2055 2724 { 2056 2725 talloc_free(self->mem_ctx); 2057 self->ob_type->tp_free(self);2058 } 2059 2060 PyTypeObject PyLdbTree = {2061 .tp_name = " Tree",2726 PyObject_Del(self); 2727 } 2728 2729 static PyTypeObject PyLdbTree = { 2730 .tp_name = "ldb.Tree", 2062 2731 .tp_basicsize = sizeof(PyLdbTreeObject), 2063 2732 .tp_dealloc = (destructor)py_ldb_tree_dealloc, … … 2367 3036 static PyObject *py_timestring(PyObject *module, PyObject *args) 2368 3037 { 2369 time_t t; 3038 /* most times "time_t" is a signed integer type with 32 or 64 bit: 3039 * http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to */ 3040 long int t_val; 2370 3041 char *tresult; 2371 3042 PyObject *ret; 2372 if (!PyArg_ParseTuple(args, " L", &t))2373 return NULL; 2374 tresult = ldb_timestring(NULL, t);3043 if (!PyArg_ParseTuple(args, "l", &t_val)) 3044 return NULL; 3045 tresult = ldb_timestring(NULL, (time_t) t_val); 2375 3046 ret = PyString_FromString(tresult); 2376 3047 talloc_free(tresult); … … 2435 3106 return; 2436 3107 3108 if (PyType_Ready(&PyLdbResult) < 0) 3109 return; 3110 3111 if (PyType_Ready(&PyLdbControl) < 0) 3112 return; 3113 2437 3114 m = Py_InitModule3("ldb", py_ldb_global_methods, 2438 3115 "An interface to LDB, a LDAP-like API that can either to talk an embedded database (TDB-based) or a standards-compliant LDAP server."); … … 2440 3117 return; 2441 3118 3119 PyModule_AddObject(m, "SEQ_HIGHEST_SEQ", PyInt_FromLong(LDB_SEQ_HIGHEST_SEQ)); 3120 PyModule_AddObject(m, "SEQ_HIGHEST_TIMESTAMP", PyInt_FromLong(LDB_SEQ_HIGHEST_TIMESTAMP)); 3121 PyModule_AddObject(m, "SEQ_NEXT", PyInt_FromLong(LDB_SEQ_NEXT)); 2442 3122 PyModule_AddObject(m, "SCOPE_DEFAULT", PyInt_FromLong(LDB_SCOPE_DEFAULT)); 2443 3123 PyModule_AddObject(m, "SCOPE_BASE", PyInt_FromLong(LDB_SCOPE_BASE)); … … 2494 3174 PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER)); 2495 3175 2496 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY)); 2497 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC)); 2498 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT)); 2499 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP)); 2500 3176 PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY)); 3177 PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC)); 3178 PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT)); 3179 PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP)); 2501 3180 2502 3181 PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText")); … … 2511 3190 Py_INCREF(&PyLdbMessageElement); 2512 3191 Py_INCREF(&PyLdbTree); 3192 Py_INCREF(&PyLdbResult); 3193 Py_INCREF(&PyLdbControl); 2513 3194 2514 3195 PyModule_AddObject(m, "Ldb", (PyObject *)&PyLdb); … … 2518 3199 PyModule_AddObject(m, "Module", (PyObject *)&PyLdbModule); 2519 3200 PyModule_AddObject(m, "Tree", (PyObject *)&PyLdbTree); 2520 } 3201 PyModule_AddObject(m, "Control", (PyObject *)&PyLdbControl); 3202 3203 PyModule_AddObject(m, "__version__", PyString_FromString(PACKAGE_VERSION)); 3204 }
Note:
See TracChangeset
for help on using the changeset viewer.