summary refs log tree commit diff
diff options
context:
space:
mode:
authorwrmr2025-05-21 20:22:49 -0500
committerwrmr2025-05-21 20:22:49 -0500
commitd81f9712ebb68a197e8febcbcc2b08af9fc3cdc7 (patch)
tree4b3c830d331e11b51eb4f372b3a3b371c62f1a3e
parent5ad75fb7d06e95cc530ad836a0fa2979136753da (diff)
more stringent uri formatting stuff
-rw-r--r--main.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/main.c b/main.c
index 4755b62..27746d6 100644
--- a/main.c
+++ b/main.c
@@ -66,12 +66,33 @@ char to_xdigit(int x) {
 	}
 }
 
+int uri_ch_reserved(char c) {
+	return c == ':' || c == '/' || c == '?' || c == '#' || c == '[' || c == ']';
+}
+
+int uri_ch_unreserved(char c) {
+	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')
+		|| (c >= '0' && c <= '9') || c == '-' || c == '.'
+		|| c == '_' || c == '~';
+}
+
+int uri_ch_sub_delim(char c) {
+	return c == '!' || c == '$' || c == '&' || c == '\'' || c == '('
+		|| c == ')' || c == '*' || c == '+' || c == ',' || c == ';'
+		|| c == '=';
+}
+
+int uri_ch_allowed(char c) {
+	return uri_ch_reserved(c) || uri_ch_unreserved(c) || uri_ch_sub_delim(c)
+		|| c == '%';
+}
+
 void str_cat_uri_internal(Str *s, Str uri, Arena *a) {
 	for (isize i = 0; i < uri.n; i++) {
 		char c = uri.s[i];
-		if (c == '\'' || c == '%') {
+		if (c == '\'' || !uri_ch_allowed(c)) {
 			str_catc(s, '%', a);
-			str_catc(s, to_xdigit((c & 0xff) >> 4), a);
+			str_catc(s, to_xdigit((c >> 4) & 0xf), a);
 			str_catc(s, to_xdigit(c & 0xf), a);
 		} else {
 			str_catc(s, c, a);