add backend chaining webdav

Tue, 31 Dec 2019 10:01:32 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Tue, 31 Dec 2019 10:01:32 +0100
branch
webdav
changeset 217
8ed14d76db42
parent 216
ce2866ec97f6
child 218
2ba512b284b9

add backend chaining

src/server/public/webdav.h file | annotate | diff | comparison | revisions
src/server/test/webdav.c file | annotate | diff | comparison | revisions
src/server/webdav/multistatus.c file | annotate | diff | comparison | revisions
src/server/webdav/multistatus.h file | annotate | diff | comparison | revisions
src/server/webdav/objs.mk file | annotate | diff | comparison | revisions
src/server/webdav/operation.c file | annotate | diff | comparison | revisions
src/server/webdav/operation.h file | annotate | diff | comparison | revisions
src/server/webdav/webdav.c file | annotate | diff | comparison | revisions
src/server/webdav/webdav.h file | annotate | diff | comparison | revisions
--- a/src/server/public/webdav.h	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/public/webdav.h	Tue Dec 31 10:01:32 2019 +0100
@@ -62,6 +62,8 @@
 
 typedef struct WebdavVFSProperties    WebdavVFSProperties;
 
+typedef struct WebdavOperation        WebdavOperation;
+
 typedef struct WSXmlData              WSXmlData;
 typedef struct WSText                 WSText;
 
@@ -205,18 +207,29 @@
 };
 
 struct WebdavResponse {
+    WebdavOperation *op;
+    
     WebdavResource* (*addresource)(WebdavResponse*, const char*);
 };
 
 struct WebdavResource {
     char *href;
     
+    WSBool isclosed;
+    
     /*
      * int addprop(WebdavResource *res, WebdavProperty *property, int status);
      * 
      * Adds a property to the resource
      */
     int (*addproperty)(WebdavResource*, WebdavProperty*, int);
+    
+    /*
+     * int close(WebdavResource *res);
+     * 
+     * Closes a resource object
+     */
+    int (*close)(WebdavResource*);
 };
 
 struct WebdavBackend {
@@ -238,7 +251,7 @@
      *     WebdavPropfindRequest *rq,
      *     WebdavResponse *response,
      *     VFS_DIR parent,
-     *     const char *path,
+     *     WebdavResource *resource,
      *     struct stat *s);
      * 
      * This function is called for the requsted resource and for all children
@@ -248,7 +261,7 @@
             WebdavPropfindRequest *,
             WebdavResponse *,
             VFS_DIR,
-            const char *,
+            WebdavResource *,
             struct stat *);
     
     /*
--- a/src/server/test/webdav.c	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/test/webdav.c	Tue Dec 31 10:01:32 2019 +0100
@@ -38,6 +38,82 @@
 
 #include "webdav.h"
 
+/* ----------------------------- Test Backends --------------------------*/
+
+// backend2
+static int backend2_propfind_init(
+        WebdavPropfindRequest *propfind,
+        const char *path,
+        WebdavPList **outPList)
+{
+    return 0;
+}
+
+static int backend2_propfind_do(
+            WebdavPropfindRequest *propfind,
+            WebdavResponse *response,
+            VFS_DIR parent,
+            WebdavResource *resource,
+            struct stat *s)
+{
+    return 0;
+}
+
+static int backend2_propfind_finish(WebdavPropfindRequest *propfind) {
+    return 0;
+}
+
+static WebdavBackend backend2 = {
+    backend2_propfind_init,
+    backend2_propfind_do,
+    backend2_propfind_finish,
+    0,
+    NULL
+};
+
+// backend1
+static int backend1_propfind_init(
+        WebdavPropfindRequest *propfind,
+        const char *path,
+        WebdavPList **outPList)
+{
+    WebdavPList *plist = *outPList;
+    WebdavProperty *p = plist->property;
+    if(!strcmp(p->name, "displayname")) {
+        plist->next->prev = NULL;
+        *outPList = plist->next; // remove first item from plist
+    } else {
+        return 1;
+    }
+    
+    return 0;
+}
+
+static int backend1_propfind_do(
+            WebdavPropfindRequest *propfind,
+            WebdavResponse *response,
+            VFS_DIR parent,
+            WebdavResource *resource,
+            struct stat *s)
+{
+    return 0;
+}
+
+static int backend1_propfind_finish(WebdavPropfindRequest *propfind) {
+    return 0;
+}
+
+WebdavBackend backend1 = {
+    backend1_propfind_init,
+    backend1_propfind_do,
+    backend1_propfind_finish,
+    0,
+    &backend2
+};
+
+/* ----------------------------------------------------------------------*/
+
+
 static int test_init(
         Session **out_sn,
         Request **out_rq,
@@ -604,81 +680,6 @@
     UCX_TEST_END;
 }
 
-/* ----------------------------- Test Backends --------------------------*/
-
-// backend2
-static int backend2_propfind_init(
-        WebdavPropfindRequest *propfind,
-        const char *path,
-        WebdavPList **outPList)
-{
-    return 0;
-}
-
-static int backend2_propfind_do(
-            WebdavPropfindRequest *propfind,
-            WebdavResponse *response,
-            VFS_DIR parent,
-            const char *path,
-            struct stat *s)
-{
-    return 0;
-}
-
-static int backend2_propfind_finish(WebdavPropfindRequest *propfind) {
-    return 0;
-}
-
-static WebdavBackend backend2 = {
-    backend2_propfind_init,
-    backend2_propfind_do,
-    backend2_propfind_finish,
-    0,
-    NULL
-};
-
-// backend1
-static int backend1_propfind_init(
-        WebdavPropfindRequest *propfind,
-        const char *path,
-        WebdavPList **outPList)
-{
-    WebdavPList *plist = *outPList;
-    WebdavProperty *p = plist->property;
-    if(!strcmp(p->name, "displayname")) {
-        plist->next->prev = NULL;
-        *outPList = plist->next; // remove first item from plist
-    } else {
-        return 1;
-    }
-    
-    return 0;
-}
-
-static int backend1_propfind_do(
-            WebdavPropfindRequest *propfind,
-            WebdavResponse *response,
-            VFS_DIR parent,
-            const char *path,
-            struct stat *s)
-{
-    return 0;
-}
-
-static int backend1_propfind_finish(WebdavPropfindRequest *propfind) {
-    return 0;
-}
-
-WebdavBackend backend1 = {
-    backend1_propfind_init,
-    backend1_propfind_do,
-    backend1_propfind_finish,
-    0,
-    &backend2
-};
-
-/* ----------------------------------------------------------------------*/
-
 UCX_TEST(test_webdav_propfind_init) {
     Session *sn;
     Request *rq;
--- a/src/server/webdav/multistatus.c	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/webdav/multistatus.c	Tue Dec 31 10:01:32 2019 +0100
@@ -31,6 +31,8 @@
 
 #include "../daemon/session.h"
 
+#include "operation.h"
+
 #include "multistatus.h"
 
 #define MULTISTATUS_BUFFER_LENGTH 2048
@@ -266,13 +268,17 @@
     ZERO(res, sizeof(MSResponse));
     
     res->resource.addproperty = msresponse_addproperty;
+    res->resource.close = msresponse_close;
     
     res->multistatus = ms;
     res->errors = NULL;
-    res->end = 0;
+    res->resource.isclosed = 0;
+    res->closing = 0;
     
     if(ms->current) {
-        ms->current->end = 1;
+        if(!ms->current->resource.isclosed) {
+            msresponse_close((WebdavResource*)ms->current);
+        }
         ms->current->next = res;
     } else {
         ms->first = res;
@@ -288,7 +294,7 @@
         int status)
 {
     MSResponse *response = (MSResponse*)res;
-    if(response->end) {
+    if(response->resource.isclosed) {
         log_ereport(
                 LOG_WARN,
                 "%s",
@@ -389,3 +395,20 @@
     }
     return 0;
 }
+
+int msresponse_close(WebdavResource *res) {
+    MSResponse *response = (MSResponse*)res;
+    if(response->closing) {
+        return 0; // close already in progress
+    }
+    
+    int ret = REQ_PROCEED;
+    WebdavOperation *op = response->multistatus->response.op;
+    if(webdav_op_propfiond_close_resource(op, res)) {
+        ret = REQ_ABORTED;
+    }
+    
+    response->resource.isclosed = TRUE;
+    response->closing = FALSE;
+    return ret;
+}
--- a/src/server/webdav/multistatus.h	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/webdav/multistatus.h	Tue Dec 31 10:01:32 2019 +0100
@@ -76,7 +76,7 @@
     WebdavPList *plist_end;
     
     MSResponse *next;
-    WSBool end;
+    WSBool closing;
 };
 
 struct PropertyErrorList {
@@ -104,6 +104,8 @@
         WebdavProperty *property,
         int statuscode);
 
+int msresponse_close(WebdavResource *res);
+
 #ifdef __cplusplus
 }
 #endif
--- a/src/server/webdav/objs.mk	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/webdav/objs.mk	Tue Dec 31 10:01:32 2019 +0100
@@ -32,6 +32,7 @@
 
 DAVOBJ = webdav.o
 DAVOBJ += requestparser.o
+DAVOBJ += operation.o
 DAVOBJ += multistatus.o
 DAVOBJ += search.o
 DAVOBJ += versioning.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webdav/operation.c	Tue Dec 31 10:01:32 2019 +0100
@@ -0,0 +1,253 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2019 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <ucx/list.h>
+
+#include "../daemon/session.h"
+
+#include "operation.h"
+
+#define WEBDAV_PATH_MAX 8192
+
+WebdavOperation* webdav_operation_create(
+        pool_handle_t *pool,
+        WebdavBackend *dav,
+        UcxList *requests,
+        WebdavResponse *response)
+{
+    WebdavOperation *op = pool_malloc(pool, sizeof(WebdavOperation));
+    ZERO(op, sizeof(WebdavOperation));
+    op->dav = dav;
+    op->requests = requests;
+    op->response = response;
+    
+    response->op = op;
+    
+    return op;
+}
+
+int webdav_op_propfind_begin(
+        WebdavOperation *op,
+        const char *path,
+        VFS_DIR parent,
+        struct stat *s)
+{
+    // create WebdavResource object for requested resource
+    WebdavResource *resource = op->response->addresource(op->response, path);
+    if(!resource) {
+        return REQ_ABORTED;
+    }
+    
+    // store data that we need when the resource will be closed
+    op->stat = s;
+    op->parent = parent;
+    
+    // get first propfind object
+    WebdavPropfindRequest *propfind = op->requests->data;
+    
+    // execute propfind_do of the first backend for the first resource
+    if(op->dav->propfind_do(propfind, op->response, NULL, resource, s)) {
+        return REQ_ABORTED;
+    }
+    
+    return REQ_PROCEED;
+}
+
+int webdav_op_propfind_children(
+        WebdavOperation *op,
+        VFSContext *vfs,
+        char *path)
+{
+    WebdavResponse *response = op->response;
+    WebdavPropfindRequest *request = op->requests->data;
+    
+    UcxAllocator *a = session_get_allocator(request->sn);
+    pool_handle_t *pool = request->sn->pool;
+    UcxList *stack = ucx_list_prepend_a(a, NULL, path);
+    UcxList *stack_end = stack;
+    if(!stack) {
+        return 1;
+    }
+    
+    // reusable buffer for full child path
+    char *newpath = NULL;
+    size_t newpathlen = 0;
+    
+    int err = 0;
+    while(stack && !err) {
+        char *cur_path = stack->data;
+        size_t parent_len = strlen(cur_path);
+        if(parent_len > WEBDAV_PATH_MAX) {
+            log_ereport(LOG_FAILURE, "webdav: maximal path length exceeded");
+            err = 1;
+            break;
+        }
+        if(cur_path[parent_len-1] == '/') {
+            parent_len--;
+        }
+        size_t max_child_len = WEBDAV_PATH_MAX - parent_len;
+        
+        // when newpath is initialized with the parent path
+        // set path_buf_init to TRUE
+        WSBool path_buf_init = FALSE;
+        
+        VFS_DIR dir = vfs_opendir(vfs, path);
+        if(!dir) {
+            log_ereport(
+                    LOG_FAILURE,
+                    "webdav: propfind: cannot open directory %d",
+                    vfs->vfs_errno);
+            err = 1;
+            break;
+        }
+        
+        VFS_ENTRY f;
+        while(vfs_readdir_stat(dir, &f)) {
+            if(f.stat_errno != 0) {
+                continue;
+            }
+            
+            size_t child_len = strlen(f.name);
+            if(child_len > max_child_len) {
+                log_ereport(LOG_FAILURE, "webdav: maximal path length exceeded");
+                err = 1;
+                break;
+            }
+            size_t childpathlen = parent_len + child_len + 1; // +1 '/'
+            if(childpathlen > newpathlen) {
+                // we're gonna need a bigger boa^H^H^Hbuffer
+                if(newpath) {
+                    pool_free(pool, newpath);
+                }
+                newpath = pool_malloc(pool, childpathlen + 1);
+                if(!newpath) {
+                    err = 1;
+                    break;
+                }
+                newpathlen = childpathlen;
+                path_buf_init = FALSE;
+            }
+            // create full path string for this child
+            if(!path_buf_init) {
+                memcpy(newpath, cur_path, parent_len);
+                newpath[parent_len] = '/';
+            }
+            memcpy(newpath+parent_len+1, f.name, child_len);
+            newpath[childpathlen] = 0;
+            
+            // propfind for this child
+            if(webdav_op_propfind_begin(op, newpath, dir, &f.stat)) {
+                err = 1;
+                break;
+            }
+            
+            // depth of -1 means infinity
+            if(request->depth == -1 && S_ISDIR(f.stat.st_mode)) {
+                char *pathcp = pool_malloc(pool, childpathlen + 1);
+                memcpy(pathcp, newpath, childpathlen + 1);
+                
+                // add the newpath copy to the stack
+                // stack_end is always not NULL here, because we remove
+                // the first stack element at the end of the loop
+                UcxList *newlistelm = ucx_list_append_a(a, stack_end, pathcp);
+                if(!newlistelm) {
+                    err = 1;
+                    break;
+                }
+                stack_end = newlistelm;
+            }
+        }
+        
+        vfs_closedir(dir);
+        
+        if(cur_path != path) {
+            pool_free(pool, cur_path);
+        }
+        stack = ucx_list_remove_a(a, stack, stack);
+    }
+    
+    // in case of an error, we have to free all remaining stack elements
+    UCX_FOREACH(elm, stack) {
+        char *data = elm->data;
+        if(data != path) {
+            pool_free(pool, data);
+        }
+    }
+    
+    return err;
+}
+
+int webdav_op_propfiond_close_resource(
+        WebdavOperation *op,
+        WebdavResource *resource)
+{
+    // start with second backend and request, because
+    // the first one was already called by webdav_op_propfind_begin
+    WebdavBackend *dav = op->dav->next;
+    UcxList *request = op->requests->next;
+    
+    // call propfind_do of all remaining backends
+    int ret = REQ_PROCEED;
+    while(dav && request) {
+        if(dav->propfind_do(
+                request->data,
+                op->response,
+                op->parent,
+                resource,
+                op->stat))
+        {
+            ret = REQ_ABORTED;
+        }
+        
+        dav = dav->next;
+        request = request->next;
+    }
+    return ret;
+}
+
+/*
+ * Executes propfind_finish for each Backend
+ */
+int webdav_op_propfind_finish(WebdavOperation *op) {
+    WebdavBackend *dav = op->dav;
+    UcxList *requests = op->requests;
+    
+    int ret = REQ_PROCEED;
+    while(dav && requests) {
+        if(dav->propfind_finish(requests->data)) {
+            ret = REQ_ABORTED;
+        }
+        
+        dav = dav->next;
+        requests = requests->next;
+    }
+    return ret;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/server/webdav/operation.h	Tue Dec 31 10:01:32 2019 +0100
@@ -0,0 +1,76 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2019 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef OPERATION_H
+#define OPERATION_H
+
+#include "../public/webdav.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct WebdavOperation {
+    WebdavBackend    *dav;
+    UcxList          *requests; /* backend specific request objects */
+    
+    WebdavResponse   *response;
+    
+    VFS_DIR          parent;    /* current directory */
+    struct stat      *stat;     /* current stat object */
+};
+
+WebdavOperation* webdav_operation_create(
+        pool_handle_t *pool,
+        WebdavBackend *dav,
+        UcxList *requests,
+        WebdavResponse *response);
+
+int webdav_op_propfind_begin(
+        WebdavOperation *op,
+        const char *path,
+        VFS_DIR parent,
+        struct stat *s);
+
+int webdav_op_propfind_children(
+        WebdavOperation *op,
+        VFSContext *vfs,
+        char *path);
+
+int webdav_op_propfiond_close_resource(
+        WebdavOperation *op,
+        WebdavResource *resource);
+
+int webdav_op_propfind_finish(WebdavOperation *op);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OPERATION_H */
+
--- a/src/server/webdav/webdav.c	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/webdav/webdav.c	Tue Dec 31 10:01:32 2019 +0100
@@ -39,6 +39,7 @@
 #include "versioning.h"
 #include "multistatus.h"
 #include "requestparser.h"
+#include "operation.h"
 
 #include "../util/pblock.h"
 #include "../util/util.h"
@@ -182,19 +183,9 @@
         }
     }
     
-    // The multistatus response object contains responses for all
-    // requested resources. At the end the Multistatus object will be
-    // serialized to xml
-    Multistatus *ms = multistatus_response(sn, rq);
-    if(!ms) {
-        return REQ_ABORTED;
-    }
-    // WebdavResponse is the public interface used by Backends
-    // for adding resources to the response
-    WebdavResponse *response = (WebdavResponse*)ms;
+    WebdavBackend *dav =  rq->davCollection ?
+                              rq->davCollection : &default_backend;
     
-    WebdavBackend *dav = 
-            rq->davCollection ? rq->davCollection : &default_backend;
     
     // requested uri path
     char *path = pblock_findkeyval(pb_key_path, rq->vars);
@@ -210,6 +201,23 @@
         return REQ_ABORTED;
     }
     
+    // The multistatus response object contains responses for all
+    // requested resources. At the end the Multistatus object will be
+    // serialized to xml
+    Multistatus *ms = multistatus_response(sn, rq);
+    if(!ms) {
+        return REQ_ABORTED;
+    }
+    // WebdavResponse is the public interface used by Backends
+    // for adding resources to the response
+    WebdavResponse *response = (WebdavResponse*)ms;
+    
+    WebdavOperation *op = webdav_operation_create(
+            sn->pool,
+            dav,
+            requestObjects,
+            response);
+    
     // some Backends can list all children by themselves, but some
     // require the VFS for this
     WSBool usevfs = (settings & WS_PROPFIND_NO_VFS) != WS_PROPFIND_NO_VFS;
@@ -234,8 +242,10 @@
         usevfs = FALSE;
     }
     
-    int ret = REQ_ABORTED;
-    if(!webdav_propfind_do(dav, requestObjects, response, NULL, path, statptr)) {
+    int ret = REQ_PROCEED;
+    
+    // create WebdavResource object for requested resource
+    if(!webdav_op_propfind_begin(op, path, NULL, statptr)) {
         // propfind for the requested resource was successful
         
         // usevfsdir is TRUE if
@@ -243,15 +253,17 @@
         //   the file is a directory
         //   depth is not 0
         // in this case we need to execute propfind_do for all children
-        if(usevfs && !propfind_children(dav, requestObjects, response, vfs, path)) {
-            ret = REQ_PROCEED;
+        if(usevfs) {
+            if(!webdav_op_propfind_children(op, vfs, path)) {
+                ret = REQ_ABORTED;
+            }
         }
     }
     
     // finish the propfind request
     // this function should cleanup all resources, therefore we execute it
     // even if a previous function failed
-    if(dav->propfind_finish(propfind)) {
+    if(webdav_op_propfind_finish(op)) {
         ret = REQ_ABORTED;
     }
     
@@ -320,176 +332,6 @@
 }
 
 
-/*
- * Executes propfind_do for each Backend
- * The list requests must contain all WebdavPropfindRequest objects
- * of all backends
- */
-int webdav_propfind_do(
-        WebdavBackend *dav,
-        UcxList *requests,
-        WebdavResponse *response,
-        VFS_DIR parent,
-        const char *path,
-        struct stat *s)
-{
-    while(dav && requests) {
-        if(dav->propfind_do(requests->data, response, parent, path, s)) {
-            return REQ_ABORTED;
-        }
-        
-        dav = dav->next;
-        requests = requests->next;
-    }
-    return REQ_PROCEED;
-}
-
-/*
- * Executes propfind_finish for each Backend
- */
-int webdav_propfind_finish(WebdavBackend *dav, UcxList *requests) {
-    int ret = REQ_PROCEED;
-    while(dav && requests) {
-        if(dav->propfind_finish(requests->data)) {
-            ret = REQ_ABORTED;
-        }
-        
-        dav = dav->next;
-        requests = requests->next;
-    }
-    return ret;
-}
-
-
-/*
- * Uses the VFS to iterate over all children of the requsted resource
- * and executes propfind for each child
- */
-int propfind_children(
-        WebdavBackend *dav,
-        UcxList *requests,
-        WebdavResponse *response,
-        VFSContext *vfs,
-        char *path)
-{
-    WebdavPropfindRequest *request = requests->data;
-    
-    UcxAllocator *a = session_get_allocator(request->sn);
-    pool_handle_t *pool = request->sn->pool;
-    UcxList *stack = ucx_list_prepend_a(a, NULL, path);
-    UcxList *stack_end = stack;
-    if(!stack) {
-        return 1;
-    }
-    
-    // reusable buffer for full child path
-    char *newpath = NULL;
-    size_t newpathlen = 0;
-    
-    int err = 0;
-    while(stack && !err) {
-        char *cur_path = stack->data;
-        size_t parent_len = strlen(cur_path);
-        if(parent_len > WEBDAV_PATH_MAX) {
-            log_ereport(LOG_FAILURE, "webdav: maximal path length exceeded");
-            err = 1;
-            break;
-        }
-        if(cur_path[parent_len-1] == '/') {
-            parent_len--;
-        }
-        size_t max_child_len = WEBDAV_PATH_MAX - parent_len;
-        
-        // when newpath is initialized with the parent path
-        // set path_buf_init to TRUE
-        WSBool path_buf_init = FALSE;
-        
-        VFS_DIR dir = vfs_opendir(vfs, path);
-        if(!dir) {
-            log_ereport(
-                    LOG_FAILURE,
-                    "webdav: propfind: cannot open directory %d",
-                    vfs->vfs_errno);
-            err = 1;
-            break;
-        }
-        
-        VFS_ENTRY f;
-        while(vfs_readdir_stat(dir, &f)) {
-            if(f.stat_errno != 0) {
-                continue;
-            }
-            
-            size_t child_len = strlen(f.name);
-            if(child_len > max_child_len) {
-                log_ereport(LOG_FAILURE, "webdav: maximal path length exceeded");
-                err = 1;
-                break;
-            }
-            size_t childpathlen = parent_len + child_len + 1; // +1 '/'
-            if(childpathlen > newpathlen) {
-                // we're gonna need a bigger boa^H^H^Hbuffer
-                if(newpath) {
-                    pool_free(pool, newpath);
-                }
-                newpath = pool_malloc(pool, childpathlen + 1);
-                if(!newpath) {
-                    err = 1;
-                    break;
-                }
-                newpathlen = childpathlen;
-                path_buf_init = FALSE;
-            }
-            // create full path string for this child
-            if(!path_buf_init) {
-                memcpy(newpath, cur_path, parent_len);
-                newpath[parent_len] = '/';
-            }
-            memcpy(newpath+parent_len+1, f.name, child_len);
-            newpath[childpathlen] = 0;
-            
-            // propfind for this child
-            if(webdav_propfind_do(dav, requests, response, dir, newpath, &f.stat)) {
-                err = 1;
-                break;
-            }
-            
-            // depth of -1 means infinity
-            if(request->depth == -1 && S_ISDIR(f.stat.st_mode)) {
-                char *pathcp = pool_malloc(pool, childpathlen + 1);
-                memcpy(pathcp, newpath, childpathlen + 1);
-                
-                // add the newpath copy to the stack
-                // stack_end is always not NULL here, because we remove
-                // the first stack element at the end of the loop
-                UcxList *newlistelm = ucx_list_append_a(a, stack_end, pathcp);
-                if(!newlistelm) {
-                    err = 1;
-                    break;
-                }
-                stack_end = newlistelm;
-            }
-        }
-        
-        vfs_closedir(dir);
-        
-        if(cur_path != path) {
-            pool_free(pool, cur_path);
-        }
-        stack = ucx_list_remove_a(a, stack, stack);
-    }
-    
-    // in case of an error, we have to free all remaining stack elements
-    UCX_FOREACH(elm, stack) {
-        char *data = elm->data;
-        if(data != path) {
-            pool_free(pool, data);
-        }
-    }
-    
-    return err;
-}
-
 int webdav_proppatch(pblock *pb, Session *sn, Request *rq) {
     return REQ_ABORTED;
 }
@@ -559,18 +401,12 @@
         WebdavPropfindRequest *request,
         WebdavResponse *response,
         VFS_DIR parent,
-        const char *path,
+        WebdavResource *resource,
         struct stat *s)
 {
     DefaultWebdavData *data = request->userdata;
     
-    // add a resource to the response
-    // usually this will lead to a <response> ... </response> tag in the
-    // multistatus response
-    WebdavResource *resource = response->addresource(response, path);
-    if(!resource) {
-        return 1;
-    }
+    // TODO: rework
     
     // add all requested vfs properties like getcontentlength ...
     if(webdav_add_vfs_properties(
--- a/src/server/webdav/webdav.h	Mon Dec 30 16:33:20 2019 +0100
+++ b/src/server/webdav/webdav.h	Tue Dec 31 10:01:32 2019 +0100
@@ -37,8 +37,8 @@
 #ifdef	__cplusplus
 extern "C" {
 #endif
+   
 
-#define WEBDAV_PATH_MAX 8192
     
 typedef struct DefaultWebdavData {
     WebdavVFSProperties vfsproperties;
@@ -68,22 +68,10 @@
         const char *path,
         UcxList **out_req);
 
-int webdav_propfind_do(
-        WebdavBackend *webdav,
-        UcxList *requests,
-        WebdavResponse *response,
-        VFS_DIR parent,
-        const char *path,
-        struct stat *s);
+
 
 int webdav_propfind_finish(WebdavBackend *webdav, UcxList *requests);
 
-int propfind_children(
-        WebdavBackend *webdav,
-        UcxList *requests,
-        WebdavResponse *response,
-        VFSContext *vfs,
-        char *path);
 
 int webdav_proppatch(pblock *pb, Session *sn, Request *rq);
 int webdav_mkcol(pblock *pb, Session *sn, Request *rq);
@@ -106,7 +94,7 @@
         WebdavPropfindRequest *request,
         WebdavResponse *response,
         VFS_DIR parent,
-        const char *path,
+        WebdavResource *resource,
         struct stat *s);
 int default_propfind_finish(WebdavPropfindRequest *rq);
 

mercurial