urlencode resource href in webdav multistatus response

Thu, 07 Sep 2023 10:06:04 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Thu, 07 Sep 2023 10:06:04 +0200
changeset 509
2e29d0c2fb3b
parent 508
fb1a51e7954f
child 510
379fe1856800

urlencode resource href in webdav multistatus response

src/server/webdav/multistatus.c file | annotate | diff | comparison | revisions
--- a/src/server/webdav/multistatus.c	Wed Sep 06 22:48:08 2023 +0200
+++ b/src/server/webdav/multistatus.c	Thu Sep 07 10:06:04 2023 +0200
@@ -93,6 +93,9 @@
     writer_putc   (out, '\"');
 }
 
+
+// html escape
+/*
 static void send_string_escaped(Writer *out, cxmutstr str) {
     char *begin = str.ptr;
     char *end = begin;
@@ -102,7 +105,6 @@
         char c = str.ptr[i];
         end = str.ptr + i;
         switch(c) {
-            /*
             case '"': {
                 escape = "&quot;";
                 esclen = 6;
@@ -128,17 +130,6 @@
                 esclen = 4;
                 break;
             }
-            */
-            case ' ': {
-                escape = "%20";
-                esclen = 3;
-                break;
-            }
-            case '&': {
-                escape = "%26";
-                esclen = 3;
-                break;
-            }
             default: continue;
         }
         ptrdiff_t len = end - begin;
@@ -154,6 +145,52 @@
         begin = end + 1;
     }
 }
+*/
+
+static const char hex_ch[] = "0123456789ABCDEF";
+
+static void send_string_escaped(Writer *out, cxmutstr str) {
+    char *begin = str.ptr;
+    char *end = begin;
+    
+    char escape[4];
+    escape[0] = '%';
+    
+    for(size_t i=0;i<str.length;i++) {
+        unsigned char c = (unsigned char)str.ptr[i];
+        end = str.ptr + i;
+        
+        // check if the character must be escaped
+        if(     (c >= 'A' && c <= 'Z') ||
+                (c >= 'a' && c <= 'z') ||
+                (c >= '/' && c <= '9') ||
+                (strchr("_.\\-~", c) != NULL))
+        {
+            continue;
+        }
+        
+        // convert char to hex number, escape[0] always contains '%'
+        escape[1] = hex_ch[(c >> 4) & 0x0F];
+        escape[2] = hex_ch[c & 0x0F];
+        
+        // write previous unescaped chars, if available
+        ptrdiff_t len = end - begin;
+        if(len > 0) {
+            writer_put(out, begin, len);
+        }
+        
+        // write escaped char
+        writer_put(out, escape, 3);
+        
+        // begin next chunk
+        begin = end + 1;
+    }
+    ptrdiff_t len = end - begin;
+    if(len > 0) {
+        writer_put(out, begin, len + 1);
+        begin = end + 1;
+    }
+}
 
 static int send_property(
         Multistatus *ms,

mercurial