s4:ldb Add ldb_ldif_write_string() and python wrappers
authorAndrew Bartlett <abartlet@samba.org>
Wed, 26 Aug 2009 05:59:00 +0000 (15:59 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 26 Aug 2009 05:59:00 +0000 (15:59 +1000)
This allows us to turn a python LdbMessage back into a string.

Andrew Bartlett

source4/lib/ldb/common/ldb_ldif.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/pyldb.c
source4/lib/ldb/tests/python/api.py

index d890ff83006215373243057508f5f897e39c12c7..30370e6999aabd4cc754aae9c32589b639bff2f1 100644 (file)
@@ -759,3 +759,43 @@ int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif
        state.f = f;
        return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
 }
+
+/*
+  wrapper around ldif_write() for a string
+*/
+struct ldif_write_string_state {
+       char *string;
+};
+
+static int ldif_printf_string(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
+
+static int ldif_printf_string(void *private_data, const char *fmt, ...)
+{
+       struct ldif_write_string_state *state =
+               (struct ldif_write_string_state *)private_data;
+       va_list ap;
+       size_t oldlen = strlen(state->string);
+       va_start(ap, fmt);
+       
+       state->string = talloc_vasprintf_append(state->string, fmt, ap);
+       va_end(ap);
+       if (!state->string) {
+               return -1;
+       }
+               
+       return strlen(state->string) - oldlen;
+}
+
+char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, 
+                           const struct ldb_ldif *ldif)
+{
+       struct ldif_write_string_state state;
+       state.string = talloc_strdup(mem_ctx, "");
+       if (!state.string) {
+               return NULL;
+       }
+       if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) {
+               return NULL;
+       }
+       return state.string;
+}
index 20f0f9cc5a2ee4ce1968f84ac32e1a25fb375052..8972fc83e9a091ec733f34b45c0ba794ec4c178a 100644 (file)
@@ -1449,6 +1449,20 @@ struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s);
 */
 int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg);
 
+/**
+   Write an LDIF message to a string
+
+   \param ldb the ldb context (from ldb_init())
+   \param mem_ctx the talloc context on which to attach the string)
+   \param msg the message to write out
+
+   \return the string containing the LDIF, or NULL on error
+
+   \sa ldb_ldif_read_string for the reader equivalent to this function.
+*/
+char * ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, 
+                         const struct ldb_ldif *msg);
+
 /**
    Base64 encode a buffer
 
index 94415c8c31de11feb110781cc8ece5d77338357c..3f7fa2f395825671c882ea2f1d98954b1af2c932 100644 (file)
@@ -813,6 +813,41 @@ static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
 }
 
 
+static PyObject *py_ldb_write_ldif(PyLdbMessageObject *self, PyObject *args)
+{
+       int changetype;
+       PyObject *py_msg;
+       struct ldb_ldif ldif;
+       PyObject *ret;
+       char *string;
+       TALLOC_CTX *mem_ctx;
+
+       if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
+               return NULL;
+
+       if (!PyLdbMessage_Check(py_msg)) {
+               PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
+               return NULL;
+       }
+
+       ldif.msg = PyLdbMessage_AsMessage(py_msg);
+       ldif.changetype = changetype;
+
+       mem_ctx = talloc_new(NULL);
+
+       string = ldb_ldif_write_string(PyLdb_AsLdbContext(self), mem_ctx, &ldif);
+       if (!string) {
+               PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
+               return NULL;
+       }
+
+       ret = PyString_FromString(string);
+
+       talloc_free(mem_ctx);
+
+       return ret;
+}
+
 static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
 {
        PyObject *list;
@@ -1116,6 +1151,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." },
+       { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
+               "S.write_ldif(message, changetype) -> ldif\n"
+               "Print the message as 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." },
index 9bcb2251905561f92b5af8a387027e007d56538b..88983ac738bc53099130085c7b0312c551d600cb 100755 (executable)
@@ -402,7 +402,9 @@ class DnTests(unittest.TestCase):
         msg = msgs.next()
         self.assertEquals("foo=bar", str(msg[1].dn))
         self.assertTrue(isinstance(msg[1], ldb.Message))
-
+        ldif = self.ldb.write_ldif(msg[1], ldb.CHANGETYPE_NONE)
+        self.assertEquals("dn: foo=bar\n\n", ldif)
+        
     def test_parse_ldif_more(self):
         msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar")
         msg = msgs.next()