From 626b32402c82674d69d23e1f68e4ee19e65940f3 Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Sat, 3 Dec 2022 20:49:59 -0600 Subject: [PATCH] Add httpd -v, fix ? in static URLs, and very start of CGI plumbing. --- lib/lib.h | 2 +- lib/net.c | 11 ++++++--- toys/net/httpd.c | 60 ++++++++++++++++++++++++++++++------------------ 3 files changed, 47 insertions(+), 26 deletions(-) diff --git a/lib/lib.h b/lib/lib.h index f7d723e5..f27ed204 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -352,7 +352,7 @@ char *ntop(struct sockaddr *sa); void xsendto(int sockfd, void *buf, size_t len, struct sockaddr *dest); int xrecvwait(int fd, char *buf, int len, union socksaddr *sa, int timeout); char *escape_url(char *str, char *and); -void unescape_url(char *str); +char *unescape_url(char *str); // password.c int get_salt(char *salt, char * algo); diff --git a/lib/net.c b/lib/net.c index 8d3a6775..533df286 100644 --- a/lib/net.c +++ b/lib/net.c @@ -197,18 +197,23 @@ char *escape_url(char *str, char *and) } // Convert %XX escapes to character (in place) -void unescape_url(char *str) +char *unescape_url(char *str) { - char *to; + char *to, *cut = strchr(str, '?'); int i; for (to = str;;) { if (*str!='%' || !isxdigit(str[1]) || !isxdigit(str[2])) { - if (!(*to++ = *str++)) break; + if (str==cut) { + *to++ = 0; + str++; + } else if (!(*to++ = *str++)) break; } else { sscanf(++str, "%2x", &i); *to++ = i; str += 2; } } + + return cut; } diff --git a/toys/net/httpd.c b/toys/net/httpd.c index f4dc4645..2460deae 100644 --- a/toys/net/httpd.c +++ b/toys/net/httpd.c @@ -12,17 +12,22 @@ * -ifv -p [IP:]PORT -u [USER][:GRP] -c CFGFILE * cgi: SERVER_PORT SERVER_NAME REMOTE_ADDR REMOTE_HOST REQUEST_METHOD -USE_HTTPD(NEWTOY(httpd, ">1", TOYFLAG_USR|TOYFLAG_BIN)) +USE_HTTPD(NEWTOY(httpd, ">1v", TOYFLAG_USR|TOYFLAG_BIN)) config HTTPD bool "httpd" default y help - usage: httpd [DIR] + usage: httpd [-e STR] [DIR] Serve contents of directory as static web pages. + + -e Escape STR as URL, printing result and exiting. + -d Decode escaped STR, printing result and exiting. + -v Verbose */ +#define FOR_httpd #include "toys.h" char *rfc1123(char *buf, time_t t) @@ -32,23 +37,6 @@ char *rfc1123(char *buf, time_t t) return buf; } -// Stop: header time. -void header_time(int stat, char *str, char *more) -{ - char buf[64]; - - xprintf("HTTP/1.1 %d %s\r\nServer: toybox httpd/%s\r\nDate: %s\r\n%s" - "Connection: close\r\n\r\n", stat, str, TOYBOX_VERSION, - rfc1123(buf, time(0)), more ? : ""); -} - -void error_time(int stat, char *str) -{ - header_time(stat, str, 0); - xprintf("%d %s" - "

%d %s

", stat, str, stat, str); -} - // She never told me... char *mime(char *file) { @@ -80,6 +68,25 @@ char *mime(char *file) return toybuf; } +// Stop: header time. +static void header_time(int stat, char *str, char *more) +{ + char buf[64]; + + if (!more) more = ""; + if (FLAG(v)) dprintf(2, "REPLY: %d %s\n%s\n", stat, str, more); + xprintf("HTTP/1.1 %d %s\r\nServer: toybox httpd/%s\r\nDate: %s\r\n%s" + "Connection: close\r\n\r\n", stat, str, TOYBOX_VERSION, + rfc1123(buf, time(0)), more); +} + +static void error_time(int stat, char *str) +{ + header_time(stat, str, 0); + xprintf("%d %s" + "

%d %s

", stat, str, stat, str); +} + static int isunder(char *file, char *dir) { char *s1 = xabspath(dir, ABS_FILE), *s2 = xabspath(file, 0), *ss = s2; @@ -95,8 +102,15 @@ static int isunder(char *file, char *dir) void handle(int infd, int outfd) { FILE *fp = fdopen(infd, "r"); - char *s = xgetline(fp), *ss, *esc, *path, *word[3]; - int i, fd; + char *s = xgetline(fp), *cut, *ss, *esc, *path, *word[3]; + int i = sizeof(toybuf), fd; + + if (!s) return; + + if (!getsockname(0, (void *)&toybuf, &i)) { + if (FLAG(v)) + dprintf(2, "Hello %s\n%s\n", ntop((void *)toybuf), s); + } // Split line into method/path/protocol for (i = 0, ss = s;;) { @@ -110,6 +124,7 @@ void handle(int infd, int outfd) // Process additional http/1.1 lines while ((ss = xgetline(fp))) { i = *chomp(ss); + if (FLAG(v)) dprintf(2, "%s\n", ss); // TODO: any of //User-Agent: Wget/1.20.1 (linux-gnu) - do we want to log anything? //Accept: */* - 406 Too Snobbish @@ -123,10 +138,11 @@ void handle(int infd, int outfd) if (!strcasecmp(word[0], "get")) { struct stat st; + if (*(ss = word[1])!='/') error_time(400, "Bad Request"); while (*ss=='/') ss++; if (!*ss) ss = "./"; - else unescape_url(ss); + else cut = unescape_url(ss); // TODO domain.com:/path/to/blah domain2.com:/path/to/that if (!isunder(ss, ".") || stat(ss, &st)) error_time(404, "Not Found"); -- 2.39.2