From 185bee5366b26db3788d1486bb15e9b46f344771 Mon Sep 17 00:00:00 2001 From: Dirk Engling Date: Sat, 24 Oct 2026 05:48:37 +0200 Subject: Add a url escaper next to the scanner --- scan_urlencoded_query.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'scan_urlencoded_query.c') 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 @@ */ /* This matrix holds for each ascii character the information, - whether it is a non-terminating character for on of the three + whether it is a non-terminating character for one of the three scan states we are in, that is 'path', 'param' and 'value' from /path?param=value¶m=value, it is encoded in bit 0, 1 and 2 respectively @@ -159,3 +159,29 @@ ssize_t scan_fixed_int(char *data, size_t len, int *tmp) { *tmp = -*tmp; return len; } + +size_t fmt_urlencoded(char *dest, const uint8_t *src, size_t len) { + static const char safe[] = "$/.=~-_"; + static const char hexdigit[] = "0123456789abcdef"; + size_t written = 0, i; + + for (i = 0; i < len; ++i) { + uint8_t c = src[i]; + + /* strchr would find the terminator, so a zero byte never counts as safe */ + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || (c && strchr(safe, c))) { + if (dest) + dest[written] = (char)c; + ++written; + } else { + if (dest) { + dest[written] = '%'; + dest[written + 1] = hexdigit[c >> 4]; + dest[written + 2] = hexdigit[c & 15]; + } + written += 3; + } + } + + return written; +} -- cgit v1.3