Sun, 01 May 2022 10:48:20 +0200
add WebdavNSList <-> string converting functions
--- 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 *****************************************************************************/