prepare webdav copy webdav

Fri, 24 Jul 2020 08:00:11 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Fri, 24 Jul 2020 08:00:11 +0200
branch
webdav
changeset 252
5653a9626cc0
parent 251
f727a21497bb
child 259
0b8692959d37

prepare webdav copy

src/server/public/webdav.h file | annotate | diff | comparison | revisions
src/server/webdav/multistatus.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	Sat Jul 11 17:58:00 2020 +0200
+++ b/src/server/public/webdav.h	Fri Jul 24 08:00:11 2020 +0200
@@ -173,6 +173,7 @@
     
     WSBool allprop;
     WSBool propname;
+    WSBool deadproperties;
     
     int depth;
     
--- a/src/server/webdav/multistatus.c	Sat Jul 11 17:58:00 2020 +0200
+++ b/src/server/webdav/multistatus.c	Fri Jul 24 08:00:11 2020 +0200
@@ -559,9 +559,14 @@
     if(response->closing) {
         return 0; // close already in progress
     }
+    response->closing = TRUE;
     Multistatus *ms = response->multistatus;
     
     int ret = REQ_PROCEED;
+    
+    // PROPFIND:
+    // response_close will execute propfind_do of all remaining backends
+    // after that we will have all available properties
     WebdavOperation *op = ms->response.op;
     if(op->response_close(op, res)) {
         ret = REQ_ABORTED;
@@ -617,6 +622,5 @@
     ucx_map_free(response->properties);
     
     response->resource.isclosed = TRUE;
-    response->closing = FALSE;
     return ret;
 }
--- a/src/server/webdav/operation.h	Sat Jul 11 17:58:00 2020 +0200
+++ b/src/server/webdav/operation.h	Fri Jul 24 08:00:11 2020 +0200
@@ -30,6 +30,8 @@
 #define OPERATION_H
 
 #include "../public/webdav.h"
+#include <ucx/list.h>
+#include <ucx/map.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -38,6 +40,9 @@
 typedef int(*response_close_func)(WebdavOperation *, WebdavResource *);
 
 typedef struct WebdavVFSOperation WebdavVFSOperation;
+
+typedef struct WebdavCopy         WebdavCopy;
+typedef struct CopyResource       CopyResource;
     
 struct WebdavOperation {
     WebdavBackend          *dav;
@@ -68,6 +73,23 @@
     int                    stat_errno;
 };
 
+struct WebdavCopy {
+    WebdavResponse response;
+    Session *sn;
+    Request *rq;
+    CopyResource *current;
+    
+    char *src_href;
+    char *src_path;
+    char *dst_href;
+    char *dst_path;
+};
+
+struct CopyResource {
+    WebdavResource resource;
+    UcxMap *properties;
+};
+
 enum WebdavVFSOpType {
     WEBDAV_VFS_MKDIR = 0,
     WEBDAV_VFS_DELETE
@@ -159,6 +181,16 @@
 
 int webdav_vfs_unlink(WebdavVFSOperation *op);
 
+
+WebdavCopy* webdav_copy_create(
+        Session *sn,
+        Request *rq,
+        VFSContext *vfs,
+        char *from_href,
+        char *from_path,
+        char *to_href,
+        char *to_path);
+
 #ifdef __cplusplus
 }
 #endif
--- 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;
 }
 
--- a/src/server/webdav/webdav.h	Sat Jul 11 17:58:00 2020 +0200
+++ b/src/server/webdav/webdav.h	Fri Jul 24 08:00:11 2020 +0200
@@ -68,6 +68,14 @@
         const char *path,
         UcxList **out_req);
 
+int webdav_propfind_do(
+        WebdavBackend *dav,
+        WebdavPropfindRequest *propfind,
+        WebdavResponse *response,
+        VFSContext *vfs,
+        char *path,
+        char *uri);
+
 
 int webdav_proppatch(pblock *pb, Session *sn, Request *rq);
 int webdav_mkcol(pblock *pb, Session *sn, Request *rq);

mercurial