fix href in pg propfind response webdav

Mon, 25 Apr 2022 13:48:05 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Mon, 25 Apr 2022 13:48:05 +0200
branch
webdav
changeset 307
8787cb5ebab3
parent 306
e03737cea6e2
child 308
c3cad8f51a24

fix href in pg propfind response

src/server/plugins/postgresql/pgtest.c file | annotate | diff | comparison | revisions
src/server/plugins/postgresql/webdav.c file | annotate | diff | comparison | revisions
src/server/plugins/postgresql/webdav.h file | annotate | diff | comparison | revisions
src/server/public/webdav.h file | annotate | diff | comparison | revisions
src/server/test/webdav.c file | annotate | diff | comparison | revisions
src/server/test/webdav.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/plugins/postgresql/pgtest.c	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/plugins/postgresql/pgtest.c	Mon Apr 25 13:48:05 2022 +0200
@@ -457,7 +457,7 @@
     
     int ret;
     // Test 1
-    init_test_webdav_method(&sn, &rq, &st, &pb, "PROPFIND", "/propfind", PG_TEST_PROPFIND1);
+    init_test_webdav_method(&sn, &rq, &st, &pb, "PROPFIND", "/propfind/", PG_TEST_PROPFIND1);
     rq->davCollection = create_test_pgdav(sn, rq);
     
     ret = webdav_propfind(pb, sn, rq);
--- a/src/server/plugins/postgresql/webdav.c	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/plugins/postgresql/webdav.c	Mon Apr 25 13:48:05 2022 +0200
@@ -57,7 +57,7 @@
 // params: $1: resource_id
 static const char *sql_propfind_allprop_depth0 = "\
 select\n\
-    NULL as ppath,\n\
+    $2::text as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -76,7 +76,7 @@
 // params: $1: resource_id
 static const char *sql_propfind_depth0 = "\
 select\n\
-    NULL as ppath,\n\
+    $2::text as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -89,7 +89,7 @@
     p.pvalue\n\
 from Resource r\n\
 left join Property p on r.resource_id = p.resource_id\n\
-inner join (select unnest($2::text[]) as xmlns, unnest($3::text[]) as pname) n\n\
+inner join (select unnest($3::text[]) as xmlns, unnest($4::text[]) as pname) n\n\
    on ( p.xmlns = n.xmlns and p.pname = n.pname ) or p.property_id is null\n\
 where r.resource_id = $1;";
 
@@ -97,7 +97,9 @@
 // params: $1: resource_id
 static const char *sql_propfind_allprop_depth1 = "\
 select\n\
-    NULL ass ppath,\n\
+    case when r.resource_id = $1 then $2\n\
+         else $2 || '/' || r.nodename\n\
+    end as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -118,7 +120,9 @@
 // params: $1: resource_id
 static const char *sql_propfind_depth1 = "\
 select\n\
-    NULL as ppath,\n\
+    case when r.resource_id = $1 then $2\n\
+         else $2 || '/' || r.nodename\n\
+    end as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -131,7 +135,7 @@
     p.pvalue\n\
 from Resource r\n\
 left join Property p on r.resource_id = p.resource_id\n\
-inner join (select unnest($2::text[]) as xmlns, unnest($3::text[]) as pname) n\n\
+inner join (select unnest($3::text[]) as xmlns, unnest($4::text[]) as pname) n\n\
    on ( p.xmlns = n.xmlns and p.pname = n.pname ) or p.property_id is null\n\
 where r.resource_id = $1 or r.parent_id = $1\n\
 order by order by case when resource_id = $1 then 0 else 1 end, nodename, resource_id;";
@@ -153,7 +157,9 @@
     inner join resolvepath p on r.parent_id = p.resource_id\n\
     )\n\
 select\n\
-    r.ppath,\n\
+    case when r.resource_id = $1 then $2\n\
+         else $2 || r.ppath\n\
+    end as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -187,7 +193,9 @@
     inner join resolvepath p on r.parent_id = p.resource_id\n\
     )\n\
 select\n\
-    r.ppath,\n\
+    case when r.resource_id = $1 then $2\n\
+         else $2 || '/' || r.ppath\n\
+    end as ppath,\n\
     r.resource_id,\n\
     r.parent_id,\n\
     r.nodename,\n\
@@ -250,6 +258,7 @@
 int pg_dav_propfind_init(
         WebdavPropfindRequest *rq,
         const char *path,
+        const char *href,
         WebdavPList **outplist)
 {
     PgWebdavBackend *pgdav = rq->dav->instance;
@@ -295,17 +304,27 @@
     char resource_id_str[32];
     snprintf(resource_id_str, 32, "%" PRId64, resource_id);
     
-    const char* params[1] = { resource_id_str };
+    size_t href_len = strlen(href);
+    char *href_param = pool_malloc(rq->sn->pool, href_len + 1);
+    memcpy(href_param, href, href_len);
+    if(href_param[href_len-1] == '/') {
+        href_len--;
+    }
+    href_param[href_len] = '\0';
+    
+    
+    const char* params[2] = { resource_id_str, href_param };
     PGresult *result = PQexecParams(
             pgdav->connection,
             sql_propfind_allprop_recursive,
-            1,     // number of parameters
+            2,     // number of parameters
             NULL,
             params, // parameter value
             NULL,
             NULL,
             0);    // 0: result in text format
     int nrows = PQntuples(result);
+    pool_free(rq->sn->pool, href_param);
     if(nrows < 1) {
         PQclear(result);
         return 1;
@@ -353,6 +372,8 @@
         
         char *path = PQgetvalue(result, r, 0);
         char *res_id = PQgetvalue(result, r, 1);
+        char *iscollection_str = PQgetvalue(result, r, 4);
+        WSBool iscollection = iscollection_str && iscollection_str[0] == 't';
         int64_t resource_id;
         if(!util_strtoint(res_id, &resource_id)) {
             log_ereport(LOG_FAILURE, "pg_dav_propfind_do: cannot convert resource_id '%s' to int", res_id);
@@ -361,8 +382,22 @@
         
         char *nodename = PQgetvalue(result, r, 3);
         if(resource_id != current_resource_id) {
+            // create a href string for the new resource
+            // if the resource is a collection, it should have a trailing '/'
+            size_t pathlen = strlen(path);
+            if(pathlen == 0) {
+                log_ereport(LOG_FAILURE, "pg_dav_propfind_do: query returned invalid path");
+                return 1;
+            }
+            char *newres_href = pool_malloc(pool, pathlen+2);
+            memcpy(newres_href, path, pathlen);
+            if(iscollection && path[pathlen-1] != '/') {
+                newres_href[pathlen++] = '/';
+            }
+            newres_href[pathlen] = '\0';
+            
             // new resource
-            resource = response->addresource(response, nodename);
+            resource = response->addresource(response, newres_href);
             vfsprops_set = FALSE;
             current_resource_id = resource_id;
         }
@@ -370,8 +405,7 @@
         // standard webdav properties
         if(!vfsprops_set) {
             if(vfsprops.getresourcetype) {
-                char *iscollection = PQgetvalue(result, r, 4);
-                if(iscollection && iscollection[0] == 't') {
+                if(iscollection) {
                     resource->addproperty(resource, webdav_resourcetype_collection(), 200);
                 } else {
                     resource->addproperty(resource, webdav_resourcetype_empty(), 200);
@@ -406,8 +440,8 @@
             
             xmlNs *namespace = pool_malloc(pool, sizeof(xmlNs));
             memset(namespace, 0, sizeof(struct _xmlNs));
-            namespace->href = pool_strdup(pool, xmlns);
-            namespace->prefix = "zx1";
+            namespace->href = (xmlChar*)pool_strdup(pool, xmlns);
+            namespace->prefix = (xmlChar*)"zx1"; // TODO
             property->namespace = namespace;
             
             property->vtype = WS_VALUE_TEXT;
--- a/src/server/plugins/postgresql/webdav.h	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/plugins/postgresql/webdav.h	Mon Apr 25 13:48:05 2022 +0200
@@ -60,6 +60,7 @@
 int pg_dav_propfind_init(
         WebdavPropfindRequest *rq,
         const char *path,
+        const char *href,
         WebdavPList **outplist);
 
 int pg_dav_propfind_do(
--- a/src/server/public/webdav.h	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/public/webdav.h	Mon Apr 25 13:48:05 2022 +0200
@@ -272,6 +272,7 @@
      * int propfind_init(
      *     WebdavPropfindRequest *rq,
      *     const char *path,
+     *     const char *href,
      *     WebdavPList **outplist);
      * 
      * Initializes a propfind request. This is called once for each propfind
@@ -279,7 +280,7 @@
      * multistatus response.
      * 
      */
-    int (*propfind_init)(WebdavPropfindRequest *, const char *, WebdavPList **);
+    int (*propfind_init)(WebdavPropfindRequest *, const char *, const char *, WebdavPList **);
     
     /*
      * int propfind_do(
--- a/src/server/test/webdav.c	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/test/webdav.c	Mon Apr 25 13:48:05 2022 +0200
@@ -55,6 +55,7 @@
 static int backend2_propfind_init(
         WebdavPropfindRequest *propfind,
         const char *path,
+        const char *href,
         WebdavPList **outPList)
 {
     backend2_init_called = 1;
@@ -145,6 +146,7 @@
 static int backend1_propfind_init(
         WebdavPropfindRequest *propfind,
         const char *path,
+        const char *href,
         WebdavPList **outPList)
 {
     backend1_init_called = 1;
@@ -313,7 +315,7 @@
     UcxList *requests = NULL;
     
     // Initialize all Webdav Backends
-    if(webdav_propfind_init(&backend1, propfind, "/", &requests)) {
+    if(webdav_propfind_init(&backend1, propfind, "/", "/", &requests)) {
         return NULL;
     }
     
@@ -996,7 +998,7 @@
     UCX_TEST_ASSERT(!test_init(&sn, &rq, &propfind, TEST_PROPFIND1), "init failed");
     
     UcxList *requests = NULL;
-    int err = webdav_propfind_init(&backend1, propfind, "/", &requests);
+    int err = webdav_propfind_init(&backend1, propfind, "/", "/", &requests);
     
     UCX_TEST_ASSERT(!err, "webdav_propfind_init failed");
     UCX_TEST_ASSERT(requests, "request list is empty");
--- a/src/server/test/webdav.h	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/test/webdav.h	Mon Apr 25 13:48:05 2022 +0200
@@ -32,6 +32,8 @@
 #include "../public/nsapi.h"
 #include "../public/webdav.h"
 
+#include "testutils.h"
+
 #include <ucx/test.h>
 
 #ifdef __cplusplus
--- a/src/server/webdav/webdav.c	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/webdav/webdav.c	Mon Apr 25 13:48:05 2022 +0200
@@ -278,6 +278,7 @@
         WebdavBackend *dav,
         WebdavPropfindRequest *propfind,
         const char *path,
+        const char *uri,
         UcxList **out_req)
 {   
     pool_handle_t *pool = propfind->sn->pool;
@@ -317,7 +318,7 @@
         
         // run init: this can generate a new properties list (newProp)
         //           which will be passed to the next backend
-        if(davList->propfind_init(pReq, path, &newProp)) {
+        if(davList->propfind_init(pReq, path, uri, &newProp)) {
             return REQ_ABORTED;
         }
         
@@ -348,7 +349,7 @@
     UcxList *requestObjects = NULL;
     
     // Initialize all Webdav Backends
-    if(webdav_propfind_init(dav, propfind, path, &requestObjects)) {
+    if(webdav_propfind_init(dav, propfind, path, uri, &requestObjects)) {
         return REQ_ABORTED;
     }
     
@@ -765,6 +766,7 @@
 int default_propfind_init(
         WebdavPropfindRequest *rq,
         const char* path,
+        const char *href,
         WebdavPList **outplist)
 {
     DefaultWebdavData *data = pool_malloc(
--- a/src/server/webdav/webdav.h	Sun Apr 24 18:35:44 2022 +0200
+++ b/src/server/webdav/webdav.h	Mon Apr 25 13:48:05 2022 +0200
@@ -66,6 +66,7 @@
         WebdavBackend *dav,
         WebdavPropfindRequest *propfind,
         const char *path,
+        const char *uri,
         UcxList **out_req);
 
 int webdav_propfind_do(
@@ -93,7 +94,8 @@
 
 int default_propfind_init(
         WebdavPropfindRequest *rq,
-        const char* path,
+        const char *path,
+        const char *href,
         WebdavPList **outplist);
 int default_propfind_do(
         WebdavPropfindRequest *request,

mercurial