--- a/src/server/webdav/webdav.c Sat Jul 11 17:58:00 2020 +0200 +++ b/src/server/webdav/webdav.c Fri Jul 24 08:00:11 2020 +0200 @@ -208,17 +208,6 @@ char *path = pblock_findkeyval(pb_key_path, rq->vars); char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); - // VFS settings are only taken from the first backend - uint32_t settings = dav->settings; - - // list of individual WebdavPropfindRequest objects for each Backend - UcxList *requestObjects = NULL; - - // Initialize all Webdav Backends - if(webdav_propfind_init(dav, propfind, path, &requestObjects)) { - return REQ_ABORTED; - } - // The multistatus response object contains responses for all // requested resources. At the end the Multistatus object will be // serialized to xml @@ -226,63 +215,9 @@ 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_create_propfind_operation( - sn, - rq, - dav, - propfind->properties, - requestObjects, - response); - - // some Backends can list all children by themselves, but some - // require the VFS for this - WSBool usevfs = (settings & WS_WEBDAV_PROPFIND_USE_VFS) - == WS_WEBDAV_PROPFIND_USE_VFS; - struct stat s; - struct stat *statptr = NULL; - VFSContext *vfs = NULL; - if(usevfs) { - vfs = vfs_request_context(sn, rq); - if(!vfs) { - return REQ_ABORTED; - } - - if(vfs_stat(vfs, path, &s)) { - protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL); - return REQ_ABORTED; - } - statptr = &s; - if(!S_ISDIR(s.st_mode)) { - // the file is not a directory, therefore we don't need the VFS - usevfs = FALSE; - } - } - if(propfind->depth == 0) { - usevfs = FALSE; - } - - int ret = REQ_PROCEED; - - // create WebdavResource object for requested resource - if(!webdav_op_propfind_begin(op, uri, NULL, statptr)) { - // propfind for the requested resource was successful - - // usevfsdir is TRUE if - // the webdav backend has not disabled vfs usage - // the file is a directory - // depth is not 0 - // in this case we need to execute propfind_do for all children - if(usevfs) { - if(webdav_op_propfind_children(op, vfs, uri, path)) { - ret = REQ_ABORTED; - } - } - } + int ret = webdav_propfind_do(dav, propfind, (WebdavResponse*)ms, NULL, path, uri); // if propfind was successful, send the result to the client if(ret == REQ_PROCEED && multistatus_send(ms, sn->csd)) { @@ -292,17 +227,11 @@ // TODO: error response } - // finish the propfind request - // this function should cleanup all resources, therefore we execute it - // even if a previous function failed - if(webdav_op_propfind_finish(op)) { - // TODO: log error - ret = REQ_ABORTED; + // cleanup + if(propfind->doc) { + xmlFreeDoc(propfind->doc); } - // cleanup - xmlFreeDoc(propfind->doc); - return ret; } @@ -367,6 +296,92 @@ return REQ_PROCEED; } +int webdav_propfind_do( + WebdavBackend *dav, + WebdavPropfindRequest *propfind, + WebdavResponse *response, + VFSContext *vfs, + char *path, + char *uri) +{ + Session *sn = propfind->sn; + Request *rq = propfind->rq; + + // VFS settings are only taken from the first backend + uint32_t settings = dav->settings; + + // list of individual WebdavPropfindRequest objects for each Backend + UcxList *requestObjects = NULL; + + // Initialize all Webdav Backends + if(webdav_propfind_init(dav, propfind, path, &requestObjects)) { + return REQ_ABORTED; + } + + WebdavOperation *op = webdav_create_propfind_operation( + sn, + rq, + dav, + propfind->properties, + requestObjects, + response); + + // some Backends can list all children by themselves, but some + // require the VFS for this + WSBool usevfs = (settings & WS_WEBDAV_PROPFIND_USE_VFS) + == WS_WEBDAV_PROPFIND_USE_VFS; + struct stat s; + struct stat *statptr = NULL; + + if(usevfs && !vfs) { + vfs = vfs_request_context(sn, rq); + if(!vfs) { + return REQ_ABORTED; + } + + if(vfs_stat(vfs, path, &s)) { + protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL); + return REQ_ABORTED; + } + statptr = &s; + if(!S_ISDIR(s.st_mode)) { + // the file is not a directory, therefore we don't need the VFS + usevfs = FALSE; + } + } + if(propfind->depth == 0) { + usevfs = FALSE; + } + + int ret = REQ_PROCEED; + + // create WebdavResource object for requested resource + if(!webdav_op_propfind_begin(op, uri, NULL, statptr)) { + // propfind for the requested resource was successful + + // usevfsdir is TRUE if + // the webdav backend has not disabled vfs usage + // the file is a directory + // depth is not 0 + // in this case we need to execute propfind_do for all children + if(usevfs) { + if(webdav_op_propfind_children(op, vfs, uri, 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(webdav_op_propfind_finish(op)) { + // TODO: log error + ret = REQ_ABORTED; + } + + return ret; +} + int webdav_proppatch(pblock *pb, Session *sn, Request *rq) { char *expect = pblock_findkeyval(pb_key_expect, rq->headers); @@ -662,6 +677,30 @@ } int webdav_copy(pblock *pb, Session *sn, Request *rq) { + char *path = pblock_findkeyval(pb_key_path, rq->vars); + char *uri = pblock_findkeyval(pb_key_uri, rq->reqpb); + + char *destination = pblock_findval("destination", rq->headers); + if(!destination) { + protocol_status(sn, rq, PROTOCOL_BAD_REQUEST, NULL); + return REQ_ABORTED; + } + + VFSContext *vfs = vfs_request_context(sn, rq); + if(!vfs) { + protocol_status(sn, rq, PROTOCOL_SERVER_ERROR, NULL); + return REQ_ABORTED; + } + + struct stat src_s; + if(vfs_stat(vfs, path, &src_s)) { + protocol_status(sn, rq, util_errno2status(vfs->vfs_errno), NULL); + return REQ_ABORTED; + } + + // TODO: if src is a directory, make sure the uri has a trailing path separator + + return REQ_ABORTED; }