# HG changeset patch # User Olaf Wintermann # Date 1577782892 -3600 # Node ID 8ed14d76db427dfccefceb3123f6591e0882134d # Parent ce2866ec97f61a9f6813229f68b9c07fdd67d2f7 add backend chaining diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/public/webdav.h --- 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 *); /* diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/test/webdav.c --- 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; diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/multistatus.c --- 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; +} diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/multistatus.h --- 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 diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/objs.mk --- 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 diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/operation.c --- /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 +#include + +#include + +#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; +} diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/operation.h --- /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 */ + diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/webdav.c --- 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 ... 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( diff -r ce2866ec97f6 -r 8ed14d76db42 src/server/webdav/webdav.h --- 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);