commit 0155ccf

Santtu Lakkala  ·  2025-02-05 22:47:23 +0000 UTC
parent de8fd83
Rewrite query string decoding
1 files changed,  +69, -34
+69, -34
  1@@ -11,6 +11,39 @@ xs_dict *xs_multipart_form_data(const char *payload, int p_size, const char *hea
  2 
  3 #ifdef XS_IMPLEMENTATION
  4 
  5+char *xs_url_dec_in(char *str, int qs)
  6+{
  7+    char *w = str;
  8+    char *r;
  9+
 10+    for (r = str; *r != '\0'; r++) {
 11+        switch (*r) {
 12+        case '%': {
 13+            unsigned hex;
 14+            if (!r[1] || !r[2])
 15+                return NULL;
 16+            if (sscanf(r + 1, "%2x", &hex) != 1)
 17+                return NULL;
 18+            *w++ = hex;
 19+            r += 2;
 20+            break;
 21+        }
 22+
 23+        case '+':
 24+            if (qs) {
 25+                *w++ = ' ';
 26+                break;
 27+            }
 28+            /* fall-through */
 29+        default:
 30+            *w++ = *r;
 31+        }
 32+    }
 33+
 34+    *w++ = '\0';
 35+    return str;
 36+}
 37+
 38 xs_str *xs_url_dec(const char *str)
 39 /* decodes an URL */
 40 {
 41@@ -76,42 +109,44 @@ xs_dict *xs_url_vars(const char *str)
 42     vars = xs_dict_new();
 43 
 44     if (xs_is_string(str)) {
 45-        /* split by arguments */
 46-        xs *args = xs_split(str, "&");
 47-
 48-        const xs_val *v;
 49-
 50-        xs_list_foreach(args, v) {
 51-            xs *dv = xs_url_dec(v);
 52-            xs *kv = xs_split_n(dv, "=", 1);
 53-
 54-            if (xs_list_len(kv) == 2) {
 55-                const char *key = xs_list_get(kv, 0);
 56-                const char *pv  = xs_dict_get(vars, key);
 57-
 58-                if (!xs_is_null(pv)) {
 59-                    /* there is a previous value: convert to a list and append */
 60-                    xs *vlist = NULL;
 61-                    if (xs_type(pv) == XSTYPE_LIST)
 62-                        vlist = xs_dup(pv);
 63-                    else {
 64-                        vlist = xs_list_new();
 65-                        vlist = xs_list_append(vlist, pv);
 66-                    }
 67-
 68-                    vlist = xs_list_append(vlist, xs_list_get(kv, 1));
 69-                    vars  = xs_dict_set(vars, key, vlist);
 70-                }
 71+        xs *dup = xs_dup(str);
 72+        char *k;
 73+        char *saveptr;
 74+        for (k = strtok_r(dup, "&", &saveptr);
 75+             k;
 76+             k = strtok_r(NULL, "&", &saveptr)) {
 77+            char *v = strchr(k, '=');
 78+            if (!v)
 79+                continue;
 80+            *v++ = '\0';
 81+            k = xs_url_dec_in(k, 1);
 82+            v = xs_url_dec_in(v, 1);
 83+            if (!xs_is_string(k) || !xs_is_string(v))
 84+                continue;
 85+
 86+            const char *pv  = xs_dict_get(vars, k);
 87+            if (!xs_is_null(pv)) {
 88+                /* there is a previous value: convert to a list and append */
 89+                xs *vlist = NULL;
 90+                if (xs_type(pv) == XSTYPE_LIST)
 91+                    vlist = xs_dup(pv);
 92                 else {
 93-                    /* ends with []? force to always be a list */
 94-                    if (xs_endswith(key, "[]")) {
 95-                        xs *vlist = xs_list_new();
 96-                        vlist = xs_list_append(vlist, xs_list_get(kv, 1));
 97-                        vars = xs_dict_append(vars, key, vlist);
 98-                    }
 99-                    else
100-                        vars = xs_dict_append(vars, key, xs_list_get(kv, 1));
101+                    vlist = xs_list_new();
102+                    vlist = xs_list_append(vlist, pv);
103+                }
104+
105+                vlist = xs_list_append(vlist, v);
106+                vars  = xs_dict_set(vars, k, vlist);
107+            }
108+            else {
109+                /* ends with []? force to always be a list */
110+                if (xs_endswith(k, "[]")) {
111+                    xs *vlist = xs_list_new();
112+                    vlist = xs_list_append(vlist, v);
113+                    vars = xs_dict_append(vars, k, vlist);
114                 }
115+                else
116+                    vars = xs_dict_append(vars, k, v);
117             }
118         }
119     }