add WebdavNSList <-> string converting functions webdav

Sun, 01 May 2022 10:48:20 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 01 May 2022 10:48:20 +0200
branch
webdav
changeset 319
a9b9344875aa
parent 318
60870dbac94f
child 320
a40f7af1b670

add WebdavNSList <-> string converting functions

src/server/plugins/postgresql/pgtest.c file | annotate | diff | comparison | revisions
src/server/public/webdav.h file | annotate | diff | comparison | revisions
src/server/test/main.c file | annotate | diff | comparison | revisions
src/server/test/xml.c file | annotate | diff | comparison | revisions
src/server/test/xml.h file | annotate | diff | comparison | revisions
src/server/webdav/xml.c file | annotate | diff | comparison | revisions
--- a/src/server/plugins/postgresql/pgtest.c	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/plugins/postgresql/pgtest.c	Sun May 01 10:48:20 2022 +0200
@@ -835,7 +835,7 @@
     ret = webdav_proppatch(pb, sn, rq);
     UCX_TEST_ASSERT(ret == REQ_PROCEED, "proppatch1 failed");
     
-    printf("\n\n%.*s\n", (int)st->buf->size, st->buf->space);
+    //printf("\n\n%.*s\n", (int)st->buf->size, st->buf->space);
     
     TestMultistatus *ms = test_parse_multistatus(st->buf->space, st->buf->size);
     UCX_TEST_ASSERT(ms, "proppatch1 response is not valid xml");
--- a/src/server/public/webdav.h	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/public/webdav.h	Sun May 01 10:48:20 2022 +0200
@@ -480,6 +480,20 @@
         pool_handle_t *pool,
         WSXmlNode *node);
 
+/*
+ * converts a property list to a string
+ * 
+ * namespaces are separated by a newline character and have the format:
+ * <prefix>:<href>
+ */
+char* wsxml_nslist2string(pool_handle_t *pool, WebdavNSList *nslist);
+
+/*
+ * converts a namespace list string (created by wsxml_nslist2string) to
+ * a WebdavNSList object
+ */
+WebdavNSList* wsxml_string2nslist(pool_handle_t *pool, char *nsliststr);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/src/server/test/main.c	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/test/main.c	Sun May 01 10:48:20 2022 +0200
@@ -86,6 +86,8 @@
     ucx_test_register(suite, test_wsxml_iterator);
     ucx_test_register(suite, test_wsxml_get_required_namespaces);
     ucx_test_register(suite, test_wsxml_write_nodes);
+    ucx_test_register(suite, test_wsxml_nslist2string);
+    ucx_test_register(suite, test_wsxml_string2nslist);
     
     // webdav tests
     ucx_test_register(suite, test_webdav_plist_add);
--- a/src/server/test/xml.c	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/test/xml.c	Sun May 01 10:48:20 2022 +0200
@@ -203,6 +203,8 @@
     xmlFreeDoc(doc2);
     xmlFreeDoc(doc6);
     UCX_TEST_END;
+    
+    testutil_destroy_session(sn);
 }
 
 // checks if the namespace list contains the test namespaces x1, x2, x3 and x4
@@ -300,6 +302,8 @@
     xmlFreeDoc(doc4);
     xmlFreeDoc(doc5);
     UCX_TEST_END;
+    
+    testutil_destroy_session(sn);
 }
 
 UCX_TEST(test_wsxml_write_nodes) {
@@ -334,4 +338,93 @@
     
     UCX_TEST_END;
     testutil_iostream_destroy(st);
+    testutil_destroy_session(sn);
 }
+
+UCX_TEST(test_wsxml_nslist2string) {
+    Session *sn = testutil_session();
+    
+    UCX_TEST_BEGIN;
+    
+    WSNamespace ns1;
+    WSNamespace ns2;
+    WSNamespace ns3;  
+    memset(&ns1, 0, sizeof(WSNamespace));
+    memset(&ns2, 0, sizeof(WSNamespace));
+    memset(&ns3, 0, sizeof(WSNamespace));
+    ns1.prefix = (const xmlChar*)"x";
+    ns1.href = (const xmlChar*)"ns1";
+    ns2.prefix = (const xmlChar*)"y";
+    ns2.href = (const xmlChar*)"ns2";
+    ns3.prefix = (const xmlChar*)"z";
+    ns3.href = (const xmlChar*)"ns3";
+    
+    WebdavNSList elm1 = { &ns1, NULL, NULL };
+    WebdavNSList elm2 = { &ns2, NULL, NULL };
+    WebdavNSList elm3 = { &ns3, NULL, NULL };
+    
+    // single elm test
+    char *str1 = wsxml_nslist2string(sn->pool, &elm1);
+    UCX_TEST_ASSERT(str1, "str1 is null");
+    UCX_TEST_ASSERT(!strcmp(str1, "x:ns1"), "str1: wrong content");
+    
+    // 2 elm test
+    elm1.next = &elm2;
+    char *str2 = wsxml_nslist2string(sn->pool, &elm1);
+    UCX_TEST_ASSERT(str2, "str2 is null");
+    UCX_TEST_ASSERT(!strcmp(str2, "x:ns1\ny:ns2"), "str2: wrong content");
+    
+    // 3 elm test
+    elm2.next = &elm3;
+    char *str3 = wsxml_nslist2string(sn->pool, &elm1);
+    UCX_TEST_ASSERT(str3, "str3 is null");
+    UCX_TEST_ASSERT(!strcmp(str3, "x:ns1\ny:ns2\nz:ns3"), "str3: wrong content");
+    
+    // empty prefix test
+    ns1.prefix = NULL;
+    char *str4 = wsxml_nslist2string(sn->pool, &elm1);
+    UCX_TEST_ASSERT(str4, "str3 is null");
+    UCX_TEST_ASSERT(!strcmp(str4, ":ns1\ny:ns2\nz:ns3"), "str4: wrong content");
+    
+    UCX_TEST_END;
+    testutil_destroy_session(sn);
+}
+
+UCX_TEST(test_wsxml_string2nslist) {
+    Session *sn = testutil_session();
+    
+    UCX_TEST_BEGIN;
+    
+    // empty list
+    WebdavNSList *list1 = wsxml_string2nslist(sn->pool, "");
+    UCX_TEST_ASSERT(!list1, "list1 should be NULL");
+    
+    // 1 elm list
+    WebdavNSList *list2 = wsxml_string2nslist(sn->pool, "x:ns1");
+    UCX_TEST_ASSERT(list2, "list2 is NULL");
+    UCX_TEST_ASSERT(list2->namespace, "list2 namespace is NULL");
+    UCX_TEST_ASSERT(!strcmp((const char*)list2->namespace->prefix, "x"), "list2: wrong prefix");
+    UCX_TEST_ASSERT(!strcmp((const char*)list2->namespace->href, "ns1"), "list2: wrong href");
+    
+    // 2 elm list
+    WebdavNSList *list3 = wsxml_string2nslist(sn->pool, "x:ns1\ny:ns2");
+    UCX_TEST_ASSERT(list3, "list3 is NULL");
+    UCX_TEST_ASSERT(list3->namespace, "list3 namespace is NULL");
+    UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->prefix, "x"), "list3: wrong prefix");
+    UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: wrong href");
+    UCX_TEST_ASSERT(list3->next, "list3 elm2 is NULL");
+    UCX_TEST_ASSERT(list3->next->namespace, "list3 namespace 2 is NULL");
+    UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->prefix, "x"), "list3: elm2 wrong prefix");
+    UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: elm2 wrong href");
+    
+    // empty prefix
+    WebdavNSList *list4 = wsxml_string2nslist(sn->pool, ":x\ny:ns2");
+    UCX_TEST_ASSERT(list4, "list4 is NULL");
+    UCX_TEST_ASSERT(list4->namespace, "list4 namespace is NULL");
+    UCX_TEST_ASSERT(!list4->namespace->prefix, "list4 elm1 prefix should be NULL");
+    UCX_TEST_ASSERT(!strcmp((const char*)list3->namespace->href, "ns1"), "list3: wrong href");
+    
+    
+    UCX_TEST_END;
+    //testutil_destroy_session(sn);
+}
--- a/src/server/test/xml.h	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/test/xml.h	Sun May 01 10:48:20 2022 +0200
@@ -39,6 +39,8 @@
 UCX_TEST(test_wsxml_iterator);
 UCX_TEST(test_wsxml_get_required_namespaces);
 UCX_TEST(test_wsxml_write_nodes);
+UCX_TEST(test_wsxml_nslist2string);
+UCX_TEST(test_wsxml_string2nslist);
 
 
 #define XML_TESTDATA1 "<?xml version=\"1.0\" encoding=\"utf-8\" ?> \
--- a/src/server/webdav/xml.c	Sat Apr 30 20:44:38 2022 +0200
+++ b/src/server/webdav/xml.c	Sun May 01 10:48:20 2022 +0200
@@ -35,6 +35,7 @@
 #include <ucx/buffer.h>
 
 #include "../util/util.h"
+#include "../util/pool.h"
 
 #include "xml.h"
 
@@ -314,7 +315,7 @@
 }
 
 
-static ssize_t buf_writefunc(void *buf, const void *s, size_t len) {
+static ssize_t buf_writefunc(void *buf, const char *s, size_t len) {
     int w = ucx_buffer_write(s, 1, len, buf);
     return w == 0 ? IO_ERROR : w;
 }
@@ -357,6 +358,131 @@
     return data;
 }
 
+char* wsxml_nslist2string(pool_handle_t *pool, WebdavNSList *nslist) {
+    if(!nslist) return NULL;
+    
+    // get required string length
+    size_t len = 0;
+    WebdavNSList *elm = nslist;
+    while(elm) {
+        WSNamespace *ns = elm->namespace;
+        if(ns) {
+            if(ns->prefix) len += strlen((const char*)ns->prefix);
+            if(ns->href) len += strlen((const char*)ns->href);
+            len += 2; // 1 char for ':', 1 char for \n or \0
+        }
+        elm = elm->next;
+    }
+    
+    // alloc string
+    char *str = pool_malloc(pool, len);
+    if(!str) {
+        return NULL;
+    }
+    char *pos = str;
+    
+    // copy namespace definitions to the string
+    elm = nslist;
+    while(elm) {
+        WSNamespace *ns = elm->namespace;
+        if(ns) {
+            if(ns->prefix) {
+                size_t prefixlen = strlen((const char*)ns->prefix);
+                memcpy(pos, ns->prefix, prefixlen);
+                pos[prefixlen] = ':';
+                pos += prefixlen + 1;
+            } else {
+                pos[0] = ':';
+                pos++;
+            }
+            if(ns->href) {
+                size_t hreflen = strlen((const char*)ns->href);
+                memcpy(pos, ns->href, hreflen);
+                pos[hreflen] = elm->next ? '\n' : '\0';
+                pos += hreflen + 1;
+            } else {
+                pos[0] = elm->next ? '\n' : '\0';
+                pos++;
+            }      
+        }
+        elm = elm->next;
+    }
+    
+    return str;
+}
+
+WebdavNSList* wsxml_string2nslist(pool_handle_t *pool, char *nsliststr) {
+    if(!nsliststr) return NULL;
+    size_t len = strlen(nsliststr);
+    WebdavNSList *list_start = NULL;
+    WebdavNSList *list_current = NULL;
+    
+    char *prefix = nsliststr;
+    size_t prefix_start = 0;
+    size_t prefix_len = 0;
+    char *href = NULL;
+    size_t href_start = len;
+    size_t i;
+    for(i=0;i<=len;i++) {
+        char c = nsliststr[i];
+        if(c == '\n' || c == '\0') {
+            if(i > href_start) {
+                WebdavNSList *elm = pool_malloc(pool, sizeof(WebdavNSList));
+                if(!elm) {
+                    break;
+                }
+                elm->prev = list_current;
+                elm->next = NULL;
+                WSNamespace *ns = pool_malloc(pool, sizeof(WSNamespace));
+                elm->namespace = ns;
+                if(!ns) {
+                    break;
+                }
+                memset(ns, 0, sizeof(WSNamespace));
+                ns->prefix = prefix_len > 0 ? (xmlChar*)sstrdup_pool(pool, sstrn(prefix, prefix_len)).ptr : NULL;
+                ns->href = (xmlChar*)sstrdup_pool(pool, sstrn(href, i-href_start)).ptr;
+                if(list_current) {
+                    list_current->next = elm;
+                } else {
+                    list_start = elm; 
+                }
+                list_current = elm;
+            }
+            prefix_start = i + 1;
+            prefix = nsliststr + prefix_start;
+            prefix_len = 0;
+            href_start = len;
+            href = NULL;
+        } else if(!href && c == ':') {
+            prefix_len = i - prefix_start;
+            href_start = i + 1;
+            href = nsliststr + href_start;
+        }
+    }
+    
+    if(i < len) {
+        // error, cleanup
+        while(list_start) {
+            if(list_start->namespace) {
+                WSNamespace *ns = list_start->namespace;
+                if(ns->prefix) {
+                    pool_free(pool, (char*)ns->prefix);
+                }
+                if(ns->href) {
+                    pool_free(pool, (char*)ns->href);
+                }
+                pool_free(pool, ns);
+            }
+            WebdavNSList *next = list_start->next;
+            pool_free(pool, list_start);
+            list_start = next;
+        }
+        list_start = NULL;
+    }
+    
+    return list_start;
+}
+
 /*****************************************************************************
  *    Non public functions
  *****************************************************************************/

mercurial