ref: cf032667921f9b25f5b6f0b7ade743087dc64e5c
parent: c02f95fb0bb11858e16869d4f09fa5153aee7e34
author: Alex Musolino <alex@musolino.id.au>
date: Tue Jul 22 10:18:34 EDT 2025
paste.c: implement url encoding/decoding
--- a/bin/paste.c
+++ b/bin/paste.c
@@ -16,6 +16,96 @@
return c;
}
+static char hex[] = "0123456789abcdef";
+static char Hex[] = "0123456789ABCDEF";
+
+static int
+hexdigit(int c)
+{
+ char *p;
+
+ if(c > 0){
+ if((p = strchr(Hex, c)) != 0)
+ return p - Hex;
+ if((p = strchr(hex, c)) != 0)
+ return p - hex;
+ }
+ return -1;
+}
+
+static char*
+urldecode(char *dst, int len, char *src)
+{
+ char c;
+ char *p;
+
+ p = dst;
+ while((c = *src++) != 0){
+ if(len < 2)
+ return nil;
+ if(c == '%'){
+ int c1, c2, x1, x2;
+
+ if((c1 = *src++) == 0)
+ break;
+ if((x1 = hexdigit(c1)) < 0){
+ src--;
+ *p++ = c1;
+ len--;
+ continue;
+ }
+ if((c2 = *src++) == 0)
+ break;
+ if((x2 = hexdigit(c2)) < 0){
+ if(len < 3)
+ return nil;
+ src--;
+ *p++ = c;
+ *p++ = c1;
+ len -= 2;
+ continue;
+ }
+ c = x1<<4 | x2;
+ } else if(c == '+')
+ c = ' ';
+ *p++ = c;
+ len--;
+ }
+ *p = 0;
+ return dst;
+}
+
+static char*
+urlencode(char *dst, int len, char *src)
+{
+ char c;
+ char *p;
+
+ p = dst;
+ while((c = *src++) != 0){
+ if(len < 2)
+ return nil;
+ len--;
+ if(c>0 && strchr("/$-_@.!*'(),", c)
+ || 'a'<=c && c<='z'
+ || 'A'<=c && c<='Z'
+ || '0'<=c && c<='9')
+ *p++ = c;
+ else if(c == ' ')
+ *p++ = '+';
+ else {
+ *p++ = '%';
+ if(len < 3)
+ return nil;
+ len -= 2;
+ *p++ = Hex[c>>4];
+ *p++ = Hex[c&15];
+ }
+ }
+ *p = 0;
+ return dst;
+}
+
static void
error(int code, char *text)
{
@@ -51,9 +141,14 @@
static void
permredirect(char *location)
{
- fprint(1, "Status: 301 Moved Permanently\r\n");
- fprint(1, "Location: %s\r\n", location);
- fprint(1, "\r\n");
+ char buf[1024];
+
+ if(urlencode(buf, sizeof(buf), location) != nil){
+ fprint(1, "Status: 301 Moved Permanently\r\n");
+ fprint(1, "Location: %s\r\n", buf);
+ fprint(1, "\r\n");
+ }else
+ error500();
exits(0);
}
@@ -60,9 +155,14 @@
static void
postredirect(char *location)
{
- fprint(1, "Status: 303 See Other\r\n");
- fprint(1, "Location: %s\r\n", location);
- fprint(1, "\r\n");
+ char buf[1024];
+
+ if(urlencode(buf, sizeof(buf), location) != nil){
+ fprint(1, "Status: 303 See Other\r\n");
+ fprint(1, "Location: %s\r\n", buf);
+ fprint(1, "\r\n");
+ }else
+ error500();
exits(0);
}
@@ -501,6 +601,7 @@
static void
dirindex(int fd)
{
+ char url[1024];
long n;
Dir *d, *dirs;
@@ -519,7 +620,10 @@
d = dirs;
while(n-- > 0){
- fprint(1, "<a href=\"%s\">%s</a><br>\n", d->name, d->name);
+ if(urlencode(url, sizeof(url), d->name) != nil)
+ fprint(1, "<a href=\"%s\">%s</a><br>\n", url, d->name);
+ else
+ fprint(1, "%s<br>\n", d->name);
d++;
}
free(dirs);
@@ -544,6 +648,8 @@
}
fprint(1, "Status: 200 OK\r\n");
+ if(strcmp(d->name, "text") == 0)
+ fprint(1, "Content-type: text/plain; charset=utf-8\r\n");
fprint(1, "Content-length: %lld\r\n", d->length);
fprint(1, "\r\n");
@@ -572,6 +678,7 @@
void
main(int argc, char **argv)
{
+ char buf[1024];
char *requri;
ARGBEGIN{
@@ -585,6 +692,11 @@
fprint(2, "CGI variable REQUEST_URI not set!\n");
error500();
exits("missing REQUEST_URI");
+ }
+ requri = urldecode(buf, sizeof(buf), requri);
+ if(requri == nil){
+ error500();
+ exits(0);
}
if(strcmp(requri, "/") == 0)
permredirect("/index.html");
--
⑨