diff --git a/src/protocol/common.c b/src/protocol/common.c index 0c985ba17..d22fd84b1 100644 --- a/src/protocol/common.c +++ b/src/protocol/common.c @@ -47,12 +47,14 @@ enum connection_state init_directory_listing(struct string *page, struct uri *uri) { struct string dirpath = NULL_STRING; + struct string decoded = NULL_STRING; struct string location = NULL_STRING; unsigned char *info; int local = (uri->protocol == PROTOCOL_FILE); if (!init_string(page) || !init_string(&dirpath) + || !init_string(&decoded) || !init_string(&location) || !add_uri_to_string(&dirpath, uri, URI_DATA) || !add_uri_to_string(&location, uri, URI_DIR_LOCATION)) @@ -63,8 +65,12 @@ init_directory_listing(struct string *page, struct uri *uri) && !add_char_to_string(&dirpath, local ? CHAR_DIR_SEP : '/')) goto out_of_memory; - /* Decode uri for displaying. */ - decode_uri_string(&dirpath); + /* Decode uri for displaying. Do not use + * add_string_to_string, because it for some reason returns + * NULL if the second string is empty. */ + if (!add_bytes_to_string(&decoded, dirpath.source, dirpath.length)) + goto out_of_memory; + decode_uri_string(&decoded); if (!local && !add_char_to_string(&location, '/')) goto out_of_memory; @@ -72,23 +78,15 @@ init_directory_listing(struct string *page, struct uri *uri) if (!add_to_string(page, "\n")) goto out_of_memory; - if (!local && !add_string_to_string(page, &location)) + if (!local && !add_html_to_string(page, location.source, location.length)) goto out_of_memory; - if (!add_html_to_string(page, dirpath.source, dirpath.length) + if (!add_html_to_string(page, decoded.source, decoded.length) || !add_to_string(page, "\n\n\n\n

")) goto out_of_memory; @@ -122,20 +120,24 @@ init_directory_listing(struct string *page, struct uri *uri) /* Make the directory path with links to each subdir. */ { - unsigned char *slash = dirpath.source; - unsigned char *pslash = slash; - unsigned char sep = local ? CHAR_DIR_SEP : '/'; + const unsigned char *slash = dirpath.source; + const unsigned char *pslash = slash; + const unsigned char sep = local ? CHAR_DIR_SEP : '/'; + + while ((slash = strchr(slash, sep)) != NULL) { + done_string(&decoded); + if (!init_string(&decoded) + || !add_bytes_to_string(&decoded, pslash, slash - pslash)) + goto out_of_memory; + decode_uri_string(&decoded); - while ((slash = strchr(slash, sep))) { - /* FIXME: htmlesc? At least we should escape quotes. --pasky */ if (!add_to_string(page, "") - || !add_html_to_string(page, pslash, slash - pslash) + || !add_html_to_string(page, decoded.source, decoded.length) || !add_to_string(page, "") - || !add_char_to_string(page, sep)) + || !add_html_to_string(page, &sep, 1)) goto out_of_memory; pslash = ++slash; @@ -148,6 +150,7 @@ out_of_memory: } done_string(&dirpath); + done_string(&decoded); done_string(&location); return page->length > 0 ? S_OK : S_OUT_OF_MEM;