change error handling in case webdav_xattr_parse_data fails: set response to 500 instead of failig the entire multistatus response

Wed, 25 Jun 2025 20:45:21 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Wed, 25 Jun 2025 20:45:21 +0200
changeset 611
b446daba6839
parent 610
447e6d9ba8a4
child 612
d647ba7f0db6

change error handling in case webdav_xattr_parse_data fails: set response to 500 instead of failig the entire multistatus response

src/server/public/webdav.h file | annotate | diff | comparison | revisions
src/server/webdav/multistatus.c file | annotate | diff | comparison | revisions
src/server/webdav/operation.c file | annotate | diff | comparison | revisions
src/server/webdav/xattrbackend.c file | annotate | diff | comparison | revisions
--- a/src/server/public/webdav.h	Wed Jun 18 09:38:29 2025 +0200
+++ b/src/server/public/webdav.h	Wed Jun 25 20:45:21 2025 +0200
@@ -253,6 +253,8 @@
     
     int err;
     
+    int status;
+    
     /*
      * int addprop(WebdavResource *res, WebdavProperty *property, int status);
      * 
--- a/src/server/webdav/multistatus.c	Wed Jun 18 09:38:29 2025 +0200
+++ b/src/server/webdav/multistatus.c	Wed Jun 25 20:45:21 2025 +0200
@@ -264,6 +264,26 @@
     return out->error;
 }
 
+static void write_status_str(Writer *out, int status) {
+    char statuscode[8];
+    int sclen = snprintf(statuscode, 8, "%d ", status);
+    if(sclen > 4) {
+        statuscode[0] = '5';
+        statuscode[1] = '0';
+        statuscode[2] = '0';
+        statuscode[3] = ' ';
+        sclen = 4;
+    }
+    writer_put_lit(out, "HTTP/1.1 ");
+    writer_put(out, statuscode, sclen);
+    const char *status_msg = protocol_status_message(status);
+    if(status_msg) {
+        writer_put(out, status_msg, strlen(status_msg));
+    } else {
+        writer_put_lit(out, "Server Error");
+    }
+}
+
 static int send_response_tag(Multistatus *ms, MSResponse *rp, Writer *out) {
     writer_put_lit(out, " <D:response>\n"
                         "  <D:href>");
@@ -272,64 +292,56 @@
     
     WSBool writeContent = ms->proppatch ? FALSE : TRUE;
     
-    if(rp->plist_begin) {
-        writer_put_lit(out, "  <D:propstat>\n"
-                            "   <D:prop>\n");
-        // send properties
-        PropertyOkList *p = rp->plist_begin;
-        while(p) {
-            writer_put_lit(out, "    ");
-            if(send_property(ms, p->property, p->nsdef, writeContent, out)) {
-                return out->error;
-            }
-            writer_put_lit(out, "\n");
-            p = p->next;
-        }
-        
-        writer_put_lit(out, "   </D:prop>\n"
-                            "   <D:status>HTTP/1.1 200 OK</D:status>\n"
-                            "  </D:propstat>\n");
-    }
-    
-    // send error properties
-    PropertyErrorList *error = rp->errors;
-    while(error) {
-        writer_put_lit(out, "  <D:propstat>\n"
-                            "   <D:prop>\n");
+    if(rp->resource.status >= 300) {
+        writer_put_lit(out, "  <D:status>");
+        write_status_str(out, rp->resource.status);
+        writer_put_lit(out, "</D:status>\n");
         
-        WebdavPList *errprop = error->begin;
-        while(errprop) {
-            writer_put_lit(out, "    ");
-            if(send_property(ms, errprop->property, NULL, FALSE, out)) {
-                return out->error;
+    } else {
+        if(rp->plist_begin) {
+            writer_put_lit(out, "  <D:propstat>\n"
+                                "   <D:prop>\n");
+            // send properties
+            PropertyOkList *p = rp->plist_begin;
+            while(p) {
+                writer_put_lit(out, "    ");
+                if(send_property(ms, p->property, p->nsdef, writeContent, out)) {
+                    return out->error;
+                }
+                writer_put_lit(out, "\n");
+                p = p->next;
             }
-            writer_putc(out, '\n');
-            errprop = errprop->next;
+
+            writer_put_lit(out, "   </D:prop>\n"
+                                "   <D:status>HTTP/1.1 200 OK</D:status>\n"
+                                "  </D:propstat>\n");
         }
-        
-        char statuscode[8];
-        int sclen = snprintf(statuscode, 8, "%d ", error->status);
-        if(sclen > 4) {
-            statuscode[0] = '5';
-            statuscode[1] = '0';
-            statuscode[2] = '0';
-            statuscode[3] = ' ';
-            sclen = 4;
+
+        // send error properties
+        PropertyErrorList *error = rp->errors;
+        while(error) {
+            writer_put_lit(out, "  <D:propstat>\n"
+                                "   <D:prop>\n");
+
+            WebdavPList *errprop = error->begin;
+            while(errprop) {
+                writer_put_lit(out, "    ");
+                if(send_property(ms, errprop->property, NULL, FALSE, out)) {
+                    return out->error;
+                }
+                writer_putc(out, '\n');
+                errprop = errprop->next;
+            }
+            
+            writer_put_lit(out, "   </D:prop>\n"
+                                "   <D:status>");
+            write_status_str(out, error->status);
+            writer_put_lit(out, "</D:status>\n"
+                                "  </D:propstat>\n");
+
+
+            error = error->next;
         }
-        writer_put_lit(out, "   </D:prop>\n"
-                            "   <D:status>HTTP/1.1 ");
-        writer_put(out, statuscode, sclen);
-        const char *status_msg = protocol_status_message(error->status);
-        if(status_msg) {
-            writer_put(out, status_msg, strlen(status_msg));
-        } else {
-            writer_put_lit(out, "Server Error");
-        }
-        writer_put_lit(out, "</D:status>\n"
-                            "  </D:propstat>\n");
-        
-        
-        error = error->next;
     }
     
     // end response tag
--- a/src/server/webdav/operation.c	Wed Jun 18 09:38:29 2025 +0200
+++ b/src/server/webdav/operation.c	Wed Jun 25 20:45:21 2025 +0200
@@ -214,6 +214,14 @@
         {
             ret = REQ_ABORTED;
         }
+        if(dav->next && resource->status >= 299) {
+            log_ereport(
+                    LOG_FAILURE,
+                    "webdav: error %d for resource %s: skip remaining backend",
+                    resource->status,
+                    resource->href);
+            break;
+        }
         
         dav = dav->next;
         request = request->next;
--- a/src/server/webdav/xattrbackend.c	Wed Jun 18 09:38:29 2025 +0200
+++ b/src/server/webdav/xattrbackend.c	Wed Jun 25 20:45:21 2025 +0200
@@ -184,17 +184,18 @@
     
     CxMap *pmap = webdav_xattr_parse_data(a, xattr_data, xattr_data_len, path);
     pool_free(sn->pool, xattr_data);
+    int err = 0;
     if(!pmap) {
-        return 1;
+        // TODO: should we set all requested properties to status 500 instead?
+        resource->status = 500;
+    } else {
+        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);
+        }
     }
     
-    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;
 }
 

mercurial