Module Name: src Committed By: mrg Date: Thu Jul 19 09:53:06 UTC 2012
Modified Files: src/libexec/httpd: CHANGES bozohttpd.c bozohttpd.h dir-index-bozo.c Log Message: when generating URIs escape various characters as specified in RFC 3986. this makes, among other things, files/dirs with "?" work with dir indexing. To generate a diff of this commit: cvs rdiff -u -r1.11 -r1.12 src/libexec/httpd/CHANGES cvs rdiff -u -r1.31 -r1.32 src/libexec/httpd/bozohttpd.c cvs rdiff -u -r1.22 -r1.23 src/libexec/httpd/bozohttpd.h cvs rdiff -u -r1.14 -r1.15 src/libexec/httpd/dir-index-bozo.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/libexec/httpd/CHANGES diff -u src/libexec/httpd/CHANGES:1.11 src/libexec/httpd/CHANGES:1.12 --- src/libexec/httpd/CHANGES:1.11 Fri Nov 18 09:51:31 2011 +++ src/libexec/httpd/CHANGES Thu Jul 19 09:53:06 2012 @@ -1,5 +1,8 @@ $eterna: CHANGES,v 1.78 2011/11/18 01:25:11 mrg Exp $ +changes since bozohttpd 20111118: + o properly escape generated URIs + changes since bozohttpd 20100920: o add -P <pidfile> option, from j...@netbsd.org o avoid crashes with http basic auth, from po...@netbsd.org Index: src/libexec/httpd/bozohttpd.c diff -u src/libexec/httpd/bozohttpd.c:1.31 src/libexec/httpd/bozohttpd.c:1.32 --- src/libexec/httpd/bozohttpd.c:1.31 Mon Feb 20 09:26:56 2012 +++ src/libexec/httpd/bozohttpd.c Thu Jul 19 09:53:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: bozohttpd.c,v 1.31 2012/02/20 09:26:56 elric Exp $ */ +/* $NetBSD: bozohttpd.c,v 1.32 2012/07/19 09:53:06 mrg Exp $ */ /* $eterna: bozohttpd.c,v 1.178 2011/11/18 09:21:15 mrg Exp $ */ @@ -847,6 +847,67 @@ parse_http_date(const char *val, time_t } /* + * given an url, encode it ala rfc 3986. ie, escape ? and friends. + * note that this function returns a static buffer, and thus needs + * to be updated for any sort of parallel processing. + */ +char * +escape_rfc3986(bozohttpd_t *httpd, const char *url) +{ + static char *buf; + static size_t buflen = 0; + size_t len; + const char *s; + char *d; + + len = strlen(url); + if (buflen < len * 3 + 1) { + buflen = len * 3 + 1; + buf = bozorealloc(httpd, buf, buflen); + } + + if (url == NULL) { + buf[0] = 0; + return buf; + } + + for (s = url, d = buf; *s;) { + if (*s & 0x80) + goto encode_it; + switch (*s) { + case ':': + case '/': + case '?': + case '#': + case '[': + case ']': + case '@': + case '!': + case '$': + case '&': + case '\'': + case '(': + case ')': + case '*': + case '+': + case ',': + case ';': + case '=': + encode_it: + snprintf(d, 4, "%%%2X", *s++); + d += 3; + len += 3; + default: + *d++ = *s++; + len++; + } + } + buf[len] = 0; + + return buf; +} + +/* * checks to see if this request has a valid .bzdirect file. returns * 0 on failure and 1 on success. */ @@ -898,10 +959,10 @@ handle_redirect(bozo_httpreq_t *request, url = urlbuf; } else urlbuf = NULL; + url = escape_rfc3986(request->hr_httpd, url); - if (request->hr_query && strlen(request->hr_query)) { + if (request->hr_query && strlen(request->hr_query)) query = 1; - } if (request->hr_serverport && strcmp(request->hr_serverport, "80") != 0) snprintf(portbuf, sizeof(portbuf), ":%s", @@ -918,9 +979,9 @@ handle_redirect(bozo_httpreq_t *request, if (absolute == 0) bozo_printf(httpd, "%s%s", httpd->virthostname, portbuf); if (query) { - bozo_printf(httpd, "%s?%s\r\n", url, request->hr_query); + bozo_printf(httpd, "%s?%s\r\n", url, request->hr_query); } else { - bozo_printf(httpd, "%s\r\n", url); + bozo_printf(httpd, "%s\r\n", url); } } bozo_printf(httpd, "\r\n"); @@ -930,16 +991,17 @@ handle_redirect(bozo_httpreq_t *request, bozo_printf(httpd, "<body><h1>Document Moved</h1>\n"); bozo_printf(httpd, "This document had moved <a href=\"http://"); if (query) { - if (absolute) - bozo_printf(httpd, "%s?%s", url, request->hr_query); - else - bozo_printf(httpd, "%s%s%s?%s", httpd->virthostname, portbuf, url, - request->hr_query); - } else { - if (absolute) - bozo_printf(httpd, "%s", url); - else - bozo_printf(httpd, "%s%s%s", httpd->virthostname, portbuf, url); + if (absolute) + bozo_printf(httpd, "%s?%s", url, request->hr_query); + else + bozo_printf(httpd, "%s%s%s?%s", httpd->virthostname, + portbuf, url, request->hr_query); + } else { + if (absolute) + bozo_printf(httpd, "%s", url); + else + bozo_printf(httpd, "%s%s%s", httpd->virthostname, + portbuf, url); } bozo_printf(httpd, "\">here</a>\n"); bozo_printf(httpd, "</body></html>\n"); Index: src/libexec/httpd/bozohttpd.h diff -u src/libexec/httpd/bozohttpd.h:1.22 src/libexec/httpd/bozohttpd.h:1.23 --- src/libexec/httpd/bozohttpd.h:1.22 Wed Mar 14 23:47:19 2012 +++ src/libexec/httpd/bozohttpd.h Thu Jul 19 09:53:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: bozohttpd.h,v 1.22 2012/03/14 23:47:19 joerg Exp $ */ +/* $NetBSD: bozohttpd.h,v 1.23 2012/07/19 09:53:06 mrg Exp $ */ /* $eterna: bozohttpd.h,v 1.39 2011/11/18 09:21:15 mrg Exp $ */ @@ -186,6 +186,7 @@ int bozo_http_error(bozohttpd_t *, int, int bozo_check_special_files(bozo_httpreq_t *, const char *); char *bozo_http_date(char *, size_t); void bozo_print_header(bozo_httpreq_t *, struct stat *, const char *, const char *); +char *escape_rfc3986(bozohttpd_t *httpd, const char *url); char *bozodgetln(bozohttpd_t *, int, ssize_t *, ssize_t (*)(bozohttpd_t *, int, void *, size_t)); char *bozostrnsep(char **, const char *, ssize_t *); Index: src/libexec/httpd/dir-index-bozo.c diff -u src/libexec/httpd/dir-index-bozo.c:1.14 src/libexec/httpd/dir-index-bozo.c:1.15 --- src/libexec/httpd/dir-index-bozo.c:1.14 Wed Feb 29 23:38:46 2012 +++ src/libexec/httpd/dir-index-bozo.c Thu Jul 19 09:53:06 2012 @@ -1,4 +1,4 @@ -/* $NetBSD: dir-index-bozo.c,v 1.14 2012/02/29 23:38:46 joerg Exp $ */ +/* $NetBSD: dir-index-bozo.c,v 1.15 2012/07/19 09:53:06 mrg Exp $ */ /* $eterna: dir-index-bozo.c,v 1.20 2011/11/18 09:21:15 mrg Exp $ */ @@ -127,6 +127,7 @@ bozo_dir_index(bozo_httpreq_t *request, j--; de++) { int nostat = 0; char *name = (*de)->d_name; + char *urlname; if (strcmp(name, ".") == 0 || (strcmp(name, "..") != 0 && @@ -139,18 +140,19 @@ bozo_dir_index(bozo_httpreq_t *request, l = 0; + urlname = escape_rfc3986(httpd, name); if (strcmp(name, "..") == 0) { bozo_printf(httpd, "<a href=\"../\">"); l += bozo_printf(httpd, "Parent Directory"); } else if (S_ISDIR(sb.st_mode)) { - bozo_printf(httpd, "<a href=\"%s/\">", name); + bozo_printf(httpd, "<a href=\"%s/\">", urlname); l += bozo_printf(httpd, "%s/", name); } else if (strchr(name, ':') != NULL) { /* RFC 3986 4.2 */ - bozo_printf(httpd, "<a href=\"./%s\">", name); + bozo_printf(httpd, "<a href=\"./%s\">", urlname); l += bozo_printf(httpd, "%s", name); } else { - bozo_printf(httpd, "<a href=\"%s\">", name); + bozo_printf(httpd, "<a href=\"%s\">", urlname); l += bozo_printf(httpd, "%s", name); } bozo_printf(httpd, "</a>");