diff --git a/darkhttpd.c b/darkhttpd.c index f49df02..62670c3 100644 --- a/darkhttpd.c +++ b/darkhttpd.c @@ -1861,7 +1861,35 @@ static void urlencode(const char *src, char *dest) { dest[j] = '\0'; } -static void generate_dir_listing(struct connection *conn, const char *path) { +/* Escape < > & ' " into HTML entities. */ +static void append_escaped(struct apbuf *dst, const char *src) { + int pos = 0; + while (src[pos] != '\0') { + switch (src[pos]) { + case '<': + append(dst, "<"); + break; + case '>': + append(dst, ">"); + break; + case '&': + append(dst, "&"); + break; + case '\'': + append(dst, "'"); + break; + case '"': + append(dst, """); + break; + default: + appendl(dst, src+pos, 1); + } + pos++; + } +} + +static void generate_dir_listing(struct connection *conn, const char *path, + const char *decoded_url) { char date[DATE_LEN], *spaces; struct dlent **list; ssize_t listsize; @@ -1883,13 +1911,13 @@ static void generate_dir_listing(struct connection *conn, const char *path) { } listing = make_apbuf(); - append(listing, "\n\n "); - append(listing, conn->url); + append(listing, "<html>\n<head>\n<title>"); + append_escaped(listing, decoded_url); append(listing, "\n" "\n" "\n\n

"); - append(listing, conn->url); + append_escaped(listing, decoded_url); append(listing, "

\n
\n");
 
     spaces = xmalloc(maxlen);
@@ -1906,7 +1934,7 @@ static void generate_dir_listing(struct connection *conn, const char *path) {
         append(listing, "");
-        append(listing, list[i]->name);
+        append_escaped(listing, list[i]->name);
         append(listing, "");
 
         if (list[i]->is_dir)
@@ -2012,7 +2040,7 @@ static void process_get(struct connection *conn) {
                 return;
             }
             xasprintf(&target, "%s%s", wwwroot, decoded_url);
-            generate_dir_listing(conn, target);
+            generate_dir_listing(conn, target, decoded_url);
             free(target);
             free(decoded_url);
             return;