implement propfind for webdav xattr backend

Sun, 19 Mar 2023 11:14:10 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sun, 19 Mar 2023 11:14:10 +0100
changeset 482
b02da778362e
parent 481
31affbf33911
child 483
f69d88f86b9c

implement propfind for webdav xattr backend

src/server/webdav/xattrbackend.c file | annotate | diff | comparison | revisions
src/server/webdav/xattrbackend.h file | annotate | diff | comparison | revisions
--- a/src/server/webdav/xattrbackend.c	Sat Mar 18 19:33:06 2023 +0100
+++ b/src/server/webdav/xattrbackend.c	Sun Mar 19 11:14:10 2023 +0100
@@ -137,11 +137,13 @@
 {
     Session *sn = request->sn;
     Request *rq = request->rq;
+    CxAllocator *a = pool_allocator(sn->pool);
     
     WebdavXAttrBackend *xdav = request->dav->instance;
     WebdavXAttrRepository *repo = xdav->repo;
     XAttrPropfind *xprop = request->userdata;
     
+    // get resource path
     const char *path;
     char *path_dp = NULL;
     if(!parent) {
@@ -175,18 +177,83 @@
             repo->xattr_name,
             &xattr_data_len);
     
-    if(xattr_data) {
-        
+    if(!xattr_data) {
+        // no properties for this resource
+        return 0;
     }
     
+    CxMap *pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path);
+    pool_free(sn->pool, xattr_data);
+    if(!pmap) {
+        return 1;
+    }
     
-    return 0;
+    int err;
+    if(request->allprop || request->propname) {
+        err = webdav_xattr_propfind_allprop(request, resource, a, pmap);
+    } else {
+        err = webdav_xattr_propfind_get_requested_properties(request, resource, a, pmap);
+    } 
+    
+    return err;
 }
 
 int webdav_xattr_propfind_finish(WebdavPropfindRequest *rq) {
     return 0;
 }
 
+// helper functions for propfind_do
+
+int webdav_xattr_propfind_get_requested_properties(
+        WebdavPropfindRequest *request,
+        WebdavResource *resource,
+        CxAllocator *a,
+        CxMap *pmap)
+{
+    WebdavPListIterator i = webdav_plist_iterator(&request->properties);
+    WebdavPList *cur;
+    while(webdav_plist_iterator_next(&i, &cur)) {
+        WebdavProperty *reqprop = cur->property;
+        
+        CxHashKey key = webdav_property_key_a(
+                a,
+                (const char*)reqprop->namespace->href,
+                (const char*)reqprop->name);
+        if(!key.data.str) {
+            return 1;
+        }
+        
+        WebdavProperty *prop = cxMapGet(pmap, key);
+        if(prop) {
+            if(resource->addproperty(resource, prop, 200)) {
+                return 1;
+            }
+        }
+    }
+    
+    return 0;
+}
+
+int webdav_xattr_propfind_allprop(
+        WebdavPropfindRequest *request,
+        WebdavResource *resource,
+        CxAllocator *a,
+        CxMap *pmap)
+{
+    CxIterator i = cxMapIteratorValues(pmap);
+    cx_foreach(WebdavProperty*, prop, i) {
+        if(request->propname) {
+            prop->vtype = WS_VALUE_NO_TYPE;
+        }
+        if(resource->addproperty(resource, prop, 200)) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+
 int webdav_xattr_proppatch_do(
             WebdavProppatchRequest *request,
             WebdavResource *response,
@@ -200,6 +267,15 @@
     
     WebdavXAttrBackend *xdav = request->dav->instance;
     WebdavXAttrRepository *repo = xdav->repo;
+
+    char *path = pblock_findkeyval(pb_key_path, rq->vars);
+    
+    // How xattr proppatch works:
+    // 1. get existing property data from the file's xattr
+    // 2. do set/remove operations to the existing data
+    // 3. write new property data to the xattr (webdav_xattr_proppatch_finish)
+    
+    // TODO: proppatch file lock (in-process userspace lock)
     
     XAttrProppatch *xprop = pool_malloc(sn->pool, sizeof(XAttrProppatch));
     if(!xprop) {
@@ -207,8 +283,6 @@
     }
     request->userdata = xprop;
     
-    char *path = pblock_findkeyval(pb_key_path, rq->vars);
-    
     // get existing property data
     ssize_t xattr_data_len = 0;
     char *xattr_data = xattr_get_alloc(
@@ -222,6 +296,7 @@
     CxMap *pmap;
     if(xattr_data) {
         pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path);
+        pool_free(sn->pool, xattr_data);
     } else {
         // empty map
         pmap = cxHashMapCreate(a, request->setcount + 8);
@@ -229,6 +304,7 @@
     if(!pmap) {
         return 1;
     }
+    xprop->properties = pmap;
     
     // remove properties
     WebdavPListIterator i = webdav_plist_iterator(removeInOut);
@@ -276,19 +352,7 @@
         webdav_plist_iterator_remove_current(&i);
     }
     
-    //printf("\n\n%.*s\n\n", (int)buf.size, buf.space);
-    //fflush(stdout);
-    
-    int ret = 0;
-    cxmutstr new_data = webdav_xattr_serialze_map(a, pmap);
-    if(new_data.ptr) {
-        xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length);
-    } else {
-        cxMapDestroy(pmap);
-        ret = 1;
-    }
-    
-    return ret;
+    return 0;
 }
 
 int webdav_xattr_proppatch_finish(
@@ -297,6 +361,29 @@
             VFSFile *file,
             WSBool commit)
 {
+    Session *sn = request->sn;
+    Request *rq = request->rq;
+    CxAllocator *a = pool_allocator(sn->pool);
+    
+    WebdavXAttrBackend *xdav = request->dav->instance;
+    WebdavXAttrRepository *repo = xdav->repo;
+    
+    XAttrProppatch *xprop = request->userdata;
+    
+    char *path = pblock_findkeyval(pb_key_path, rq->vars);
+    
+    int ret = 0;
+    if(commit) {
+        cxmutstr new_data = webdav_xattr_serialze_map(a, xprop->properties);
+        if(new_data.ptr) {
+            if(xattr_set(path, repo->xattr_name, new_data.ptr, new_data.length)) {
+                ret = 1;
+            }
+        } else {
+            ret = 1;
+        }
+    }
+    
     return 0;
 }
 
--- a/src/server/webdav/xattrbackend.h	Sat Mar 18 19:33:06 2023 +0100
+++ b/src/server/webdav/xattrbackend.h	Sun Mar 19 11:14:10 2023 +0100
@@ -91,6 +91,17 @@
             VFSFile *file,
             WSBool commit);
 
+int webdav_xattr_propfind_get_requested_properties(
+        WebdavPropfindRequest *request,
+        WebdavResource *resource,
+        CxAllocator *a,
+        CxMap *pmap);
+
+int webdav_xattr_propfind_allprop(
+        WebdavPropfindRequest *request,
+        WebdavResource *resource,
+        CxAllocator *a,
+        CxMap *pmap);
 
 /* properties xattr data */
 

mercurial