summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDirk Engling <erdgeist@erdgeist.org>2026-10-24 05:48:37 +0200
committerDirk Engling <erdgeist@erdgeist.org>2026-10-24 05:48:37 +0200
commit185bee5366b26db3788d1486bb15e9b46f344771 (patch)
tree8e89cf0cf75889faa2e4f9c7b4416de49ff12fca
parent040c7eab81f8b1526841d3c8ce56e4912cae10f1 (diff)
Add a url escaper next to the scanner
-rw-r--r--scan_urlencoded_query.c28
-rw-r--r--scan_urlencoded_query.h8
2 files changed, 35 insertions, 1 deletions
diff --git a/scan_urlencoded_query.c b/scan_urlencoded_query.c
index 50aced3..cf0c5b1 100644
--- a/scan_urlencoded_query.c
+++ b/scan_urlencoded_query.c
@@ -20,7 +20,7 @@
20*/ 20*/
21 21
22/* This matrix holds for each ascii character the information, 22/* This matrix holds for each ascii character the information,
23 whether it is a non-terminating character for on of the three 23 whether it is a non-terminating character for one of the three
24 scan states we are in, that is 'path', 'param' and 'value' from 24 scan states we are in, that is 'path', 'param' and 'value' from
25 /path?param=value&param=value, it is encoded in bit 0, 1 and 2 25 /path?param=value&param=value, it is encoded in bit 0, 1 and 2
26 respectively 26 respectively
@@ -159,3 +159,29 @@ ssize_t scan_fixed_int(char *data, size_t len, int *tmp) {
159 *tmp = -*tmp; 159 *tmp = -*tmp;
160 return len; 160 return len;
161} 161}
162
163size_t fmt_urlencoded(char *dest, const uint8_t *src, size_t len) {
164 static const char safe[] = "$/.=~-_";
165 static const char hexdigit[] = "0123456789abcdef";
166 size_t written = 0, i;
167
168 for (i = 0; i < len; ++i) {
169 uint8_t c = src[i];
170
171 /* strchr would find the terminator, so a zero byte never counts as safe */
172 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c && strchr(safe, c))) {
173 if (dest)
174 dest[written] = (char)c;
175 ++written;
176 } else {
177 if (dest) {
178 dest[written] = '%';
179 dest[written + 1] = hexdigit[c >> 4];
180 dest[written + 2] = hexdigit[c & 15];
181 }
182 written += 3;
183 }
184 }
185
186 return written;
187}
diff --git a/scan_urlencoded_query.h b/scan_urlencoded_query.h
index 74246e7..6f12c03 100644
--- a/scan_urlencoded_query.h
+++ b/scan_urlencoded_query.h
@@ -6,6 +6,8 @@
6#ifndef SCAN_URLENCODED_QUERY_H__ 6#ifndef SCAN_URLENCODED_QUERY_H__
7#define SCAN_URLENCODED_QUERY_H__ 7#define SCAN_URLENCODED_QUERY_H__
8 8
9#include <stddef.h>
10#include <stdint.h>
9#include <sys/types.h> 11#include <sys/types.h>
10 12
11typedef struct { 13typedef struct {
@@ -52,4 +54,10 @@ void scan_urlencoded_skipvalue(char **string);
52 */ 54 */
53ssize_t scan_fixed_int(char *data, size_t len, int *number); 55ssize_t scan_fixed_int(char *data, size_t len, int *number);
54 56
57/* The other direction: percent encode len bytes from src into dest and return
58 how many characters were written, or how many would be needed when dest is
59 NULL. dest needs room for three times len.
60 */
61size_t fmt_urlencoded(char *dest, const uint8_t *src, size_t len);
62
55#endif 63#endif