commit 164a9b9
Merge pull request 'Rewrite query string decoding' (#299) from inz/snac2:qs-parse into master Reviewed-on: https://codeberg.org/grunfink/snac2/pulls/299
1 files changed,
+69,
-34
M
xs_url.h
M
xs_url.h
+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 }