src/server/webdav/webdav.c

changeset 415
d938228c382e
parent 414
99a34860c105
child 453
4586d534f9b5
--- a/src/server/webdav/webdav.c	Wed Nov 02 19:19:01 2022 +0100
+++ b/src/server/webdav/webdav.c	Sun Nov 06 15:53:32 2022 +0100
@@ -30,8 +30,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <ucx/buffer.h>
-#include <ucx/list.h>
+#include <cx/buffer.h>
+#include <cx/list.h>
+#include <cx/linked_list.h>
+#include <cx/hash_map.h>
+#include <cx/printf.h>
 
 #include "webdav.h"
 
@@ -53,14 +56,14 @@
  * key: http method name (string)
  * value: SAF fptr
  */
-static UcxMap *method_handler_map;
+static CxMap *method_handler_map;
 
 /*
  * webdav backend types
  * key: backend name (string)
  * value: WebdavBackend*
  */
-static UcxMap *webdav_type_map;
+static CxMap *webdav_type_map;
 
 static WebdavBackend default_backend;
 
@@ -89,11 +92,11 @@
     WebdavType *webdavType = malloc(sizeof(WebdavType));
     webdavType->init = webdavInit;
     webdavType->create = webdavCreate;
-    return ucx_map_cstr_put(webdav_type_map, name, webdavType);
+    return cxMapPut(webdav_type_map, cx_hash_key_str(name), webdavType);
 }
 
-WebdavType* webdav_get_type(scstr_t dav_class) {
-    return ucx_map_sstr_get(webdav_type_map, dav_class);
+WebdavType* webdav_get_type(cxstring dav_class) {
+    return cxMapGet(webdav_type_map, cx_hash_key_bytes((unsigned const char *)dav_class.ptr, dav_class.length));
 }
 
 void* webdav_init_backend(ServerConfiguration *cfg, pool_handle_t *pool, WebdavType *dav_class, WSConfigNode *config, int *error) {
@@ -110,7 +113,7 @@
 }
 
 WebdavBackend* webdav_create(Session *sn, Request *rq, const char *dav_class, pblock *pb, void *initData) {
-    WebdavType *webdavType = ucx_map_cstr_get(webdav_type_map, dav_class);
+    WebdavType *webdavType = cxMapGet(webdav_type_map, cx_hash_key_str(dav_class));
     if(!webdavType) {
         log_ereport(LOG_MISCONFIG, "webdav_create: unkown dav type %s", dav_class);
         return NULL;
@@ -127,43 +130,43 @@
     }
     webdav_is_initialized = TRUE;
     
-    webdav_type_map = ucx_map_new(8);
+    webdav_type_map = cxHashMapCreate(cxDefaultAllocator, 8);
     if(!webdav_type_map) {
         return REQ_ABORTED;
     }
     
-    method_handler_map = ucx_map_new(64);
+    method_handler_map = cxHashMapCreate(cxDefaultAllocator, 64);
     if(!method_handler_map) {
         return REQ_ABORTED;
     }
     
     init_default_backend();
-    ucx_map_cstr_put(webdav_type_map, "default", &default_backend);
+    cxMapPut(webdav_type_map, cx_hash_key_str("default"), &default_backend);
     
-    ucx_map_cstr_put(method_handler_map, "OPTIONS", webdav_options);
-    ucx_map_cstr_put(method_handler_map, "PROPFIND", webdav_propfind);
-    ucx_map_cstr_put(method_handler_map, "PROPPATCH", webdav_proppatch);
-    ucx_map_cstr_put(method_handler_map, "MKCOL", webdav_mkcol);
-    ucx_map_cstr_put(method_handler_map, "POST", webdav_post);
-    ucx_map_cstr_put(method_handler_map, "DELETE", webdav_delete);
-    ucx_map_cstr_put(method_handler_map, "PUT", webdav_put);
-    ucx_map_cstr_put(method_handler_map, "COPY", webdav_copy);
-    ucx_map_cstr_put(method_handler_map, "MOVE", webdav_move);
-    ucx_map_cstr_put(method_handler_map, "LOCK", webdav_lock);
-    ucx_map_cstr_put(method_handler_map, "UNLOCK", webdav_unlock);
-    ucx_map_cstr_put(method_handler_map, "REPORT", webdav_report);
-    ucx_map_cstr_put(method_handler_map, "ACL", webdav_acl);
+    cxMapPut(method_handler_map, cx_hash_key_str("OPTIONS"), webdav_options);
+    cxMapPut(method_handler_map, cx_hash_key_str("PROPFIND"), webdav_propfind);
+    cxMapPut(method_handler_map, cx_hash_key_str("PROPPATCH"), webdav_proppatch);
+    cxMapPut(method_handler_map, cx_hash_key_str("MKCOL"), webdav_mkcol);
+    cxMapPut(method_handler_map, cx_hash_key_str("POST"), webdav_post);
+    cxMapPut(method_handler_map, cx_hash_key_str("DELETE"), webdav_delete);
+    cxMapPut(method_handler_map, cx_hash_key_str("PUT"), webdav_put);
+    cxMapPut(method_handler_map, cx_hash_key_str("COPY"), webdav_copy);
+    cxMapPut(method_handler_map, cx_hash_key_str("MOVE"), webdav_move);
+    cxMapPut(method_handler_map, cx_hash_key_str("LOCK"), webdav_lock);
+    cxMapPut(method_handler_map, cx_hash_key_str("UNLOCK"), webdav_unlock);
+    cxMapPut(method_handler_map, cx_hash_key_str("REPORT"), webdav_report);
+    cxMapPut(method_handler_map, cx_hash_key_str("ACL"), webdav_acl);
     
-    ucx_map_cstr_put(method_handler_map, "SEARCH", webdav_search);
+    cxMapPut(method_handler_map, cx_hash_key_str("SEARCH"), webdav_search);
     
-    ucx_map_cstr_put(method_handler_map, "VERSION-CONTROL", webdav_version_control);
-    ucx_map_cstr_put(method_handler_map, "CHECKOUT", webdav_checkout);
-    ucx_map_cstr_put(method_handler_map, "CHECKIN", webdav_checkin);
-    ucx_map_cstr_put(method_handler_map, "UNCHECKOUT", webdav_uncheckout);
-    ucx_map_cstr_put(method_handler_map, "MKWORKSPACE", webdav_mkworkspace);
-    ucx_map_cstr_put(method_handler_map, "UPDATE", webdav_update);
-    ucx_map_cstr_put(method_handler_map, "LABEL", webdav_label);
-    ucx_map_cstr_put(method_handler_map, "MERGE", webdav_merge);
+    cxMapPut(method_handler_map, cx_hash_key_str("VERSION-CONTROL"), webdav_version_control);
+    cxMapPut(method_handler_map, cx_hash_key_str("CHECKOUT"), webdav_checkout);
+    cxMapPut(method_handler_map, cx_hash_key_str("CHECKIN"), webdav_checkin);
+    cxMapPut(method_handler_map, cx_hash_key_str("UNCHECKOUT"), webdav_uncheckout);
+    cxMapPut(method_handler_map, cx_hash_key_str("MKWORKSPACE"), webdav_mkworkspace);
+    cxMapPut(method_handler_map, cx_hash_key_str("UPDATE"), webdav_update);
+    cxMapPut(method_handler_map, cx_hash_key_str("LABEL"), webdav_label);
+    cxMapPut(method_handler_map, cx_hash_key_str("MERGE"), webdav_merge);
     
     dav_namespace.href = (xmlChar*)"DAV:";
     dav_namespace.prefix = (xmlChar*)"D";
@@ -191,7 +194,7 @@
     }
     char *method = pblock_findkeyval(pb_key_method, rq->reqpb);
     
-    FuncPtr saf = (FuncPtr)ucx_map_cstr_get(method_handler_map, method);
+    FuncPtr saf = (FuncPtr)cxMapGet(method_handler_map, cx_hash_key_str(method));
     if(!saf) {
         return REQ_NOACTION;
     }
@@ -199,33 +202,30 @@
     return saf(pb, sn, rq);
 }
 
-UcxBuffer* rqbody2buffer(Session *sn, Request *rq) {
+int rqbody2buffer(Session *sn, Request *rq, CxBuffer *buf) {
     if(!sn->inbuf) {
         //request body required, set http response code
         protocol_status(sn, rq, 400, NULL);
-        return NULL;
+        return 1;
     }
     
-    UcxBuffer *buf = ucx_buffer_new(
-            NULL,
-            sn->inbuf->maxsize,
-            UCX_BUFFER_AUTOEXTEND);
-    if(!buf) {
+    CxAllocator *a = pool_allocator(sn->pool);
+    if(cxBufferInit(buf, NULL, sn->inbuf->maxsize, a, CX_BUFFER_AUTO_EXTEND|CX_BUFFER_FREE_CONTENTS)) {
         protocol_status(sn, rq, 500, NULL);
-        return NULL;
+        return 1;
     }
     
     char in[2048];
     int r;
     while((r = netbuf_getbytes(sn->inbuf, in, 2048)) > 0) {
-        if(ucx_buffer_write(in, 1, r, buf) != r) {
+        if(cxBufferWrite(in, 1, r, buf) != r) {
             protocol_status(sn, rq, 500, NULL);
-            ucx_buffer_free(buf);
-            return NULL;
+            cxBufferDestroy(buf);
+            return 1;
         }
     }
     
-    return buf;
+    return 0;
 }
 
 int webdav_options(pblock *pb, Session *sn, Request *rq) {
@@ -254,8 +254,8 @@
         }
     }
     
-    UcxBuffer *reqbody = rqbody2buffer(sn, rq);
-    if(!reqbody) {
+    CxBuffer reqbody;
+    if(rqbody2buffer(sn, rq, &reqbody)) {
         return REQ_ABORTED;
     }
     
@@ -263,10 +263,10 @@
     WebdavPropfindRequest *propfind = propfind_parse(
             sn,
             rq,
-            reqbody->space,
-            reqbody->size,
+            reqbody.space,
+            reqbody.size,
             &error);
-    ucx_buffer_free(reqbody);
+    cxBufferDestroy(&reqbody);
     if(!propfind) {
         log_ereport(LOG_FAILURE, "webdav-propfind: %s", propfind_error2str(error));
         return REQ_ABORTED;
@@ -318,13 +318,14 @@
         WebdavPropfindRequest *propfind,
         const char *path,
         const char *uri,
-        UcxList **out_req)
+        WebdavPropfindRequestList **out_req)
 {   
     pool_handle_t *pool = propfind->sn->pool;
-    UcxAllocator *a = session_get_allocator(propfind->sn);
+    CxAllocator *a = pool_allocator(pool);
     
     // list of individual WebdavPropfindRequest objects for each Backend
-    UcxList *requestObjects = NULL;
+    WebdavPropfindRequestList *requestObjectsBegin = NULL;
+    WebdavPropfindRequestList *requestObjectsEnd = NULL;
     
     // new properties after init, start with clone of original plist
     WebdavPList *newProp = webdav_plist_clone(pool, propfind->properties);
@@ -347,10 +348,18 @@
         pReq->dav = davList;
         
         // add new WebdavPropfindRequest object to list for later use
-        requestObjects = ucx_list_append_a(a, requestObjects, pReq);
-        if(!requestObjects) {
+        WebdavPropfindRequestList *reqListElm = pool_malloc(pool, sizeof(WebdavPropfindRequestList));
+        if(!reqListElm) {
             return REQ_ABORTED; // OOM
         }
+        reqListElm->propfind = pReq;
+        reqListElm->next = NULL;
+        cx_linked_list_add(
+                (void**)&requestObjectsBegin,
+                (void**)&requestObjectsEnd,
+                -1,
+                offsetof(WebdavPropfindRequestList, next),
+                reqListElm);
         
         // create plist copy as out-plist for init
         newProp = webdav_plist_clone(pool, newProp);
@@ -366,7 +375,7 @@
         davList = davList->next;
     }
     
-    *out_req = requestObjects;
+    *out_req = requestObjectsBegin;
     return REQ_PROCEED;
 }
 
@@ -385,7 +394,7 @@
     uint32_t settings = dav->settings;
     
     // list of individual WebdavPropfindRequest objects for each Backend
-    UcxList *requestObjects = NULL;
+    WebdavPropfindRequestList *requestObjects = NULL;
     
     // Initialize all Webdav Backends
     if(webdav_propfind_init(dav, propfind, path, uri, &requestObjects)) {
@@ -480,8 +489,8 @@
         }
     }
     
-    UcxBuffer *reqbody = rqbody2buffer(sn, rq);
-    if(!reqbody) {
+    CxBuffer reqbody;
+    if(rqbody2buffer(sn, rq, &reqbody)) {
         // most likely OOM
         return REQ_ABORTED;
     }
@@ -490,10 +499,10 @@
     WebdavProppatchRequest *proppatch = proppatch_parse(
             sn,
             rq,
-            reqbody->space,
-            reqbody->size,
+            reqbody.space,
+            reqbody.size,
             &error);
-    ucx_buffer_free(reqbody);
+    cxBufferDestroy(&reqbody);
     if(!proppatch) {
         log_ereport(LOG_FAILURE, "webdav-proppatch: %s", proppatch_error2str(error));
         return REQ_ABORTED;
@@ -587,14 +596,16 @@
 typedef struct DeleteFile {
     char *path;
     struct stat s;
+    struct DeleteFile *prev;
+    struct DeleteFile *next;
 } DeleteFile;
 
 typedef struct DeleteLists {
-    UcxAllocator *a;
-    UcxList *dirs_begin;
-    UcxList *dirs_end;
-    UcxList *files_begin;
-    UcxList *files_end;
+    CxAllocator *a;
+    DeleteFile *dirs_begin;
+    DeleteFile *dirs_end;
+    DeleteFile *files_begin;
+    DeleteFile *files_end;
 } DeleteOp;
 
 static int deletelist_add(
@@ -608,19 +619,20 @@
     DeleteOp *op = userdata;
     
     // create object for this file
-    DeleteFile *file = almalloc(op->a, sizeof(DeleteFile));
+    DeleteFile *file = cxMalloc(op->a, sizeof(DeleteFile));
     if(!file) {
         return 1;
     }
-    file->path = sstrdup_a(op->a, sstr((char*)path)).ptr;
+    file->path = cx_strdup_a(op->a, cx_str((char*)path)).ptr;
     if(!file->path) {
         return 1;
     }
     file->s = *s;
+    file->next = NULL;
     
     // determine which list to use
-    UcxList **begin;
-    UcxList **end;
+    DeleteFile **begin;
+    DeleteFile **end;
     if(S_ISDIR(s->st_mode)) {
         begin = &op->dirs_begin;
         end = &op->dirs_end;
@@ -630,19 +642,10 @@
     }
     
     // add file to list
-    UcxList *elm = ucx_list_append_a(op->a, NULL, file);
-    if(!elm) {
-        alfree(op->a, file->path); // at least do some cleanup, although it
-        alfree(op->a, file);       // isn't really necessary
-        return 1;
-    }
-    if(*begin == NULL) {
-        *begin = elm;
-        *end = elm;
-    } else {
-        ucx_list_concat(*end, elm);
-        *end = elm;
-    }
+    cx_linked_list_add(
+            (void**)begin, (void**)end,
+            offsetof(DeleteFile, prev), offsetof(DeleteFile, next),
+            file);
     
     return 0;
 }
@@ -651,7 +654,7 @@
 {
     DeleteOp del;
     ZERO(&del, sizeof(DeleteOp));
-    del.a = session_get_allocator(op->sn);
+    del.a = pool_allocator(op->sn->pool);
     
     // get a list of all files
     if(webdav_op_iterate_children(op->vfs, -1, NULL, op->path,
@@ -664,22 +667,18 @@
     DeleteFile root;
     root.path = op->path;
     root.s = *op->stat;
-    UcxList root_elm;
-    root_elm.data = &root;
-    root_elm.prev = NULL;
-    root_elm.next = del.dirs_begin;
+    root.prev = NULL;
+    root.next = del.dirs_begin;
     
     if(del.dirs_begin) {
-        del.dirs_begin->prev = &root_elm;
-        del.dirs_begin = &root_elm;
+        del.dirs_begin->prev = &root;
     } else {
-        del.dirs_begin = &root_elm;
-        del.dirs_end = &root_elm;
+        del.dirs_end = &root;
     }
+    del.dirs_begin = &root;
     
     // delete files first
-    UCX_FOREACH(elm, del.files_begin) {
-        DeleteFile *file = elm->data;
+    for(DeleteFile *file=del.files_begin;file;file=file->next) {
         WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s);
         if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) {
             return 1;
@@ -687,8 +686,7 @@
     }
     
     // delete directories, reverse order
-    for(UcxList *elm=del.dirs_end;elm;elm=elm->prev) {
-        DeleteFile *file = elm->data;
+    for(DeleteFile *file=del.dirs_end;file;file=file->prev) {
         WebdavVFSOperation sub = webdav_vfs_sub_op(op, file->path, &file->s);
         if(webdav_vfs_op_do(&sub, WEBDAV_VFS_DELETE)) {
             return 1;
@@ -913,18 +911,16 @@
 
 /* ------------------------------ Utils ------------------------------ */
 
-UcxKey webdav_property_key(const char *ns, const char *name) {
-    UcxKey key;
-    sstr_t data = ucx_sprintf("%s\n%s", name, ns);
-    key.data = data.ptr;
+CxHashKey webdav_property_key(const char *ns, const char *name) {
+    CxHashKey key;
+    cxmutstr data = cx_asprintf("%s\n%s", name, ns);
+    key.data.str = data.ptr;
     key.len = data.length;
-    key.hash = ucx_hash(data.ptr, data.length);
+    cx_hash_murmur(&key);
     return key;
 }
 
 
-
-
 /* ------------------------------ public API ------------------------------ */
 
 int webdav_getdepth(Request *rq) {

mercurial