Prepend files or directories containing ":" with "./" in directory
authorflorian <florian@openbsd.org>
Sat, 25 Apr 2015 14:40:35 +0000 (14:40 +0000)
committerflorian <florian@openbsd.org>
Sat, 25 Apr 2015 14:40:35 +0000 (14:40 +0000)
indexes as per RFC 3986:
A path segment that contains a colon character (e.g., "this:that")
cannot be used as the first segment of a relative-path reference, as
it would be mistaken for a scheme name.  Such a segment must be
preceded by a dot-segment (e.g., "./this:that") to make a relative-
path reference.

While here add a "/" to the end of directory names, this saves us one
redirect round trip.

Found the hard way & "functionality wise, OK" ajacoutot@
RFC pointer & OK benno@

usr.sbin/httpd/server_file.c

index f697504..3580bbb 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: server_file.c,v 1.51 2015/02/12 10:05:29 reyk Exp $   */
+/*     $OpenBSD: server_file.c,v 1.52 2015/04/25 14:40:35 florian Exp $        */
 
 /*
  * Copyright (c) 2006 - 2015 Reyk Floeter <reyk@openbsd.org>
@@ -352,13 +352,15 @@ server_file_index(struct httpd *env, struct client *clt, struct stat *st)
                } else if (S_ISDIR(st->st_mode)) {
                        namewidth -= 1; /* trailing slash */
                        if (evbuffer_add_printf(evb,
-                           "<a href=\"%s\">%s/</a>%*s%s%20s\n",
+                           "<a href=\"%s%s/\">%s/</a>%*s%s%20s\n",
+                           strchr(escapeduri, ':') != NULL ? "./" : "",
                            escapeduri, escapedhtml,
                            MAXIMUM(namewidth, 0), " ", tmstr, "-") == -1)
                                skip = 1;
                } else if (S_ISREG(st->st_mode)) {
                        if (evbuffer_add_printf(evb,
-                           "<a href=\"%s\">%s</a>%*s%s%20llu\n",
+                           "<a href=\"%s%s\">%s</a>%*s%s%20llu\n",
+                           strchr(escapeduri, ':') != NULL ? "./" : "",
                            escapeduri, escapedhtml,
                            MAXIMUM(namewidth, 0), " ",
                            tmstr, st->st_size) == -1)