s4:ldb Add hooks to get/set the flags on a ldb_message_element
[ira/wip.git] / source4 / lib / ldb / pyldb.c
index bcca70eb82bb81e997b72f9d7e5655c2fc4e4243..94415c8c31de11feb110781cc8ece5d77338357c 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
    Copyright (C) 2006 Simo Sorce <idra@samba.org>
    Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
+   Copyright (C) 2009 Matthias Dieter Wallnöfer
 
         ** NOTE! The following LGPL license applies to the ldb
         ** library. This does NOT imply that all of Samba is released
@@ -210,7 +211,11 @@ static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
 
 static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
 {
-       return ldb_dn_compare(dn1->dn, dn2->dn);
+       int ret;
+       ret = ldb_dn_compare(dn1->dn, dn2->dn);
+       if (ret < 0) ret = -1;
+       if (ret > 0) ret = 1;
+       return ret;
 }
 
 static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
@@ -538,7 +543,8 @@ static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
                        PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
                        return NULL;
                }
-               ret[i] = PyString_AsString(item);
+               ret[i] = talloc_strndup(ret, PyString_AsString(item),
+                                                          PyString_Size(item));
        }
        ret[i] = NULL;
        return ret;
@@ -611,7 +617,7 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa
        const char **options;
        const char * const kwnames[] = { "url", "flags", "options", NULL };
 
-       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iO",
+       if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ziO",
                                         discard_const_p(char *, kwnames),
                                         &url, &flags, &py_options))
                return NULL;
@@ -839,6 +845,35 @@ static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
        return PyObject_GetIter(list);
 }
 
+static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
+{
+       PyObject *py_msg_old;
+       PyObject *py_msg_new;
+       struct ldb_message *diff;
+       PyObject *py_ret;
+
+       if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
+               return NULL;
+
+       if (!PyLdbMessage_Check(py_msg_old)) {
+               PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
+               return NULL;
+       }
+
+       if (!PyLdbMessage_Check(py_msg_new)) {
+               PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
+               return NULL;
+       }
+
+       diff = ldb_msg_diff(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg_old), PyLdbMessage_AsMessage(py_msg_new));
+       if (diff == NULL) 
+               return NULL;
+
+       py_ret = PyLdbMessage_FromMessage(diff);
+
+       return py_ret;
+}
+
 static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
 {
        const struct ldb_schema_attribute *a;
@@ -1081,6 +1116,9 @@ static PyMethodDef py_ldb_methods[] = {
        { "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
                "S.parse_ldif(ldif) -> iter(messages)\n"
                "Parse a string formatted using LDIF." },
+       { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
+               "S.msg_diff(Message) -> Message\n"
+               "Return an LDB Message of the difference between two Message objects." },
        { "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
                "S.get_opaque(name) -> value\n"
                "Get an opaque value set on this LDB connection. \n"
@@ -1393,17 +1431,19 @@ struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
        struct ldb_message_element *me;
 
        if (PyLdbMessageElement_Check(set_obj))
-               return PyLdbMessageElement_AsMessageElement(set_obj);
+               return talloc_reference(mem_ctx, 
+                                                               PyLdbMessageElement_AsMessageElement(set_obj));
 
        me = talloc(mem_ctx, struct ldb_message_element);
 
-       me->name = attr_name;
+       me->name = talloc_strdup(me, attr_name);
        me->flags = flags;
        if (PyString_Check(set_obj)) {
                me->num_values = 1;
                me->values = talloc_array(me, struct ldb_val, me->num_values);
                me->values[0].length = PyString_Size(set_obj);
-               me->values[0].data = (uint8_t *)PyString_AsString(set_obj);
+               me->values[0].data = talloc_memdup(me, 
+                       (uint8_t *)PyString_AsString(set_obj), me->values[0].length);
        } else if (PySequence_Check(set_obj)) {
                int i;
                me->num_values = PySequence_Size(set_obj);
@@ -1412,7 +1452,8 @@ struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
                        PyObject *obj = PySequence_GetItem(set_obj, i);
 
                        me->values[i].length = PyString_Size(obj);
-                       me->values[i].data = (uint8_t *)PyString_AsString(obj);
+                       me->values[i].data = talloc_memdup(me, 
+                               (uint8_t *)PyString_AsString(obj), me->values[i].length);
                }
        } else {
                talloc_free(me);
@@ -1452,8 +1493,30 @@ static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObjec
                                                                 &(PyLdbMessageElement_AsMessageElement(self)->values[i]));
 }
 
+static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
+{
+       struct ldb_message_element *el;
+
+       el = PyLdbMessageElement_AsMessageElement(self);
+       return PyInt_FromLong(el->flags);
+}
+
+static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
+{
+       int flags;
+       struct ldb_message_element *el;
+       if (!PyArg_ParseTuple(args, "i", &flags))
+               return NULL;
+
+       el = PyLdbMessageElement_AsMessageElement(self);
+       el->flags = flags;
+       Py_RETURN_NONE;
+}
+
 static PyMethodDef py_ldb_msg_element_methods[] = {
        { "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
+       { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
+       { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
        { NULL },
 };
 
@@ -1533,15 +1596,24 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
                if (PyString_Check(py_elements)) {
                        el->num_values = 1;
                        el->values = talloc_array(el, struct ldb_val, 1);
-                       el->values[0].data = (uint8_t *)PyString_AsString(py_elements);
                        el->values[0].length = PyString_Size(py_elements);
+                       el->values[0].data = talloc_memdup(el, 
+                               (uint8_t *)PyString_AsString(py_elements), el->values[0].length);
                } else if (PySequence_Check(py_elements)) {
                        el->num_values = PySequence_Size(py_elements);
                        el->values = talloc_array(el, struct ldb_val, el->num_values);
                        for (i = 0; i < el->num_values; i++) {
                                PyObject *item = PySequence_GetItem(py_elements, i);
-                               el->values[i].data = (uint8_t *)PyString_AsString(item);
+                               if (!PyString_Check(item)) {
+                                       PyErr_Format(PyExc_TypeError, 
+                                                       "Expected string as element %d in list", 
+                                                       i);
+                                       talloc_free(mem_ctx);
+                                       return NULL;
+                               }
                                el->values[i].length = PyString_Size(item);
+                               el->values[i].data = talloc_memdup(el, 
+                                       (uint8_t *)PyString_AsString(item), el->values[i].length);
                        }
                } else {
                        PyErr_SetString(PyExc_TypeError, 
@@ -1717,15 +1789,22 @@ static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
 
 static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
 {
-       char *attr_name = PyString_AsString(name);
+       char *attr_name;
+
+       if (!PyString_Check(name)) {
+               PyErr_SetNone(PyExc_TypeError);
+               return -1;
+       }
+       
+       attr_name = PyString_AsString(name);
        if (value == NULL) {
+               /* delitem */
                ldb_msg_remove_attr(self->msg, attr_name);
        } else {
-               struct ldb_message_element *el = PyObject_AsMessageElement(NULL,
+               struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
                                                                                        value, 0, attr_name);
                if (el == NULL)
                        return -1;
-               talloc_steal(self->msg, el);
                ldb_msg_remove_attr(PyLdbMessage_AsMessage(self), attr_name);
                ldb_msg_add(PyLdbMessage_AsMessage(self), el, el->flags);
        }
@@ -1747,6 +1826,7 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
 {
        const char * const kwnames[] = { "dn", NULL };
        struct ldb_message *ret;
+       TALLOC_CTX *mem_ctx;
        PyObject *pydn = NULL;
        PyLdbMessageObject *py_ret;
 
@@ -1755,8 +1835,15 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
                                         &pydn))
                return NULL;
 
-       ret = ldb_msg_new(NULL);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               PyErr_NoMemory();
+               return NULL;
+       }
+
+       ret = ldb_msg_new(mem_ctx);
        if (ret == NULL) {
+               talloc_free(mem_ctx);
                PyErr_NoMemory();
                return NULL;
        }
@@ -1764,7 +1851,7 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
        if (pydn != NULL) {
                struct ldb_dn *dn;
                if (!PyObject_AsDn(NULL, pydn, NULL, &dn)) {
-                       talloc_free(ret);
+                       talloc_free(mem_ctx);
                        return NULL;
                }
                ret->dn = talloc_reference(ret, dn);
@@ -1773,12 +1860,12 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
        py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
        if (py_ret == NULL) {
                PyErr_NoMemory();
-               talloc_free(ret);
+               talloc_free(mem_ctx);
                return NULL;
        }
 
-       py_ret->mem_ctx = talloc_new(NULL);
-       py_ret->msg = talloc_steal(py_ret->mem_ctx, ret);
+       py_ret->mem_ctx = mem_ctx;
+       py_ret->msg = ret;
        return (PyObject *)py_ret;
 }
 
@@ -1805,6 +1892,11 @@ static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
 static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
 {
        struct ldb_message *msg = PyLdbMessage_AsMessage(self);
+       if (!PyLdbDn_Check(value)) {
+               PyErr_SetNone(PyExc_TypeError);
+               return -1;
+       }
+
        msg->dn = talloc_reference(msg, PyLdbDn_AsDn(value));
        return 0;
 }
@@ -2256,6 +2348,10 @@ void initldb(void)
        PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
        PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
 
+       PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
+       PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
+       PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
+
        PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
        PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
        PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
@@ -2294,9 +2390,14 @@ void initldb(void)
        PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
        PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
        PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
-
        PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
 
+        PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
+        PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
+        PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
+        PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
+
+
        PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
 
        PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);