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;