From 380f44c30119f11c0a7d78c712406355fbe3e44e Mon Sep 17 00:00:00 2001
From: Simon Goldschmidt <goldsimon@gmx.de>
Date: Thu, 12 Jul 2018 20:34:19 +0200
Subject: [PATCH] Try to fix bug #54244: httpd should return '/dir/index.html'
 for URI '/dir'

But doesn't work: when opening '/dir' which returns '/dir/index.html', all relative links are relative to '/', not to '/dir/'
---
 src/apps/http/httpd.c | 111 +++++++++++++++++++++++++++++++++-----------------
 1 file changed, 73 insertions(+), 38 deletions(-)

diff --git a/src/apps/http/httpd.c b/src/apps/http/httpd.c
index 35e28aa4..d6f06c36 100644
--- a/src/apps/http/httpd.c
+++ b/src/apps/http/httpd.c
@@ -2163,6 +2163,58 @@ http_uri_is_ssi(struct fs_file *file, const char *uri)
 }
 #endif /* LWIP_HTTPD_SSI */
 
+/* Have we been asked for the default file (in root or a directory) ? */
+static struct fs_file *
+http_find_default_file(struct http_state *hs, char *uri, size_t uri_len, size_t uri_buf_len,
+                       const char **uri_out, u8_t *tag_check)
+{
+  struct fs_file *file;
+  size_t loop;
+  err_t err;
+
+#if !LWIP_HTTPD_MAX_REQUEST_URI_LEN
+  LWIP_UNUSED_ARG(uri);
+  LWIP_UNUSED_ARG(uri_len);
+  LWIP_UNUSED_ARG(uri_buf_len);
+#endif
+
+  /* Try each of the configured default filenames until we find one
+      that exists. */
+  for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
+    const char *file_name;
+#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
+    if (uri_len > 0) {
+      size_t len_left = uri_buf_len - uri_len - 1;
+      if (len_left > 0) {
+        size_t name_len = strlen(httpd_default_filenames[loop].name);
+        size_t name_copy_len = LWIP_MIN(len_left, name_len);
+        MEMCPY(&uri[uri_len], httpd_default_filenames[loop].name, name_copy_len);
+        uri[uri_len + name_copy_len] = 0;
+      }
+      file_name = uri;
+    } else
+#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
+    {
+      file_name = httpd_default_filenames[loop].name;
+    }
+    LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name));
+    err = fs_open(&hs->file_handle, file_name);
+    if (err == ERR_OK) {
+      *uri_out = file_name;
+      file = &hs->file_handle;
+      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n"));
+#if LWIP_HTTPD_SSI
+      *tag_check = httpd_default_filenames[loop].shtml;
+#else /* LWIP_HTTPD_SSI */
+      LWIP_UNUSED_ARG(tag_check);
+#endif /* LWIP_HTTPD_SSI */
+      return file;
+    }
+  }
+
+  return NULL;
+}
+
 /** Try to find the file specified by uri and, if found, initialize hs
  * accordingly.
  *
@@ -2175,20 +2227,15 @@ http_uri_is_ssi(struct fs_file *file, const char *uri)
 static err_t
 http_find_file(struct http_state *hs, const char *uri, int is_09)
 {
-  size_t loop;
   struct fs_file *file = NULL;
   char *params = NULL;
   err_t err;
 #if LWIP_HTTPD_CGI
   int i;
 #endif /* LWIP_HTTPD_CGI */
-#if !LWIP_HTTPD_SSI
-  const
-#endif /* !LWIP_HTTPD_SSI */
   /* By default, assume we will not be processing server-side-includes tags */
   u8_t tag_check = 0;
 
-  /* Have we been asked for the default file (in root or a directory) ? */
 #if LWIP_HTTPD_MAX_REQUEST_URI_LEN
   size_t uri_len = strlen(uri);
   if ((uri_len > 0) && (uri[uri_len - 1] == '/') &&
@@ -2198,41 +2245,13 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
       MEMCPY(http_uri_buf, uri, copy_len);
       http_uri_buf[copy_len] = 0;
     }
+    file = http_find_default_file(hs, http_uri_buf, copy_len, sizeof(http_uri_buf), &uri, &tag_check);
+  }
 #else /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
   if ((uri[0] == '/') &&  (uri[1] == 0)) {
-#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
-    /* Try each of the configured default filenames until we find one
-       that exists. */
-    for (loop = 0; loop < NUM_DEFAULT_FILENAMES; loop++) {
-      const char *file_name;
-#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
-      if (copy_len > 0) {
-        size_t len_left = sizeof(http_uri_buf) - copy_len - 1;
-        if (len_left > 0) {
-          size_t name_len = strlen(httpd_default_filenames[loop].name);
-          size_t name_copy_len = LWIP_MIN(len_left, name_len);
-          MEMCPY(&http_uri_buf[copy_len], httpd_default_filenames[loop].name, name_copy_len);
-          http_uri_buf[copy_len + name_copy_len] = 0;
-        }
-        file_name = http_uri_buf;
-      } else
-#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
-      {
-        file_name = httpd_default_filenames[loop].name;
-      }
-      LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Looking for %s...\n", file_name));
-      err = fs_open(&hs->file_handle, file_name);
-      if (err == ERR_OK) {
-        uri = file_name;
-        file = &hs->file_handle;
-        LWIP_DEBUGF(HTTPD_DEBUG | LWIP_DBG_TRACE, ("Opened.\n"));
-#if LWIP_HTTPD_SSI
-        tag_check = httpd_default_filenames[loop].shtml;
-#endif /* LWIP_HTTPD_SSI */
-        break;
-      }
-    }
+    file = http_find_default_file(hs, NULL, 0, 0, &uri, &tag_check);
   }
+#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
   if (file == NULL) {
     /* No - we've been asked for a specific file. */
     /* First, isolate the base URI (without any parameters) */
@@ -2268,7 +2287,21 @@ http_find_file(struct http_state *hs, const char *uri, int is_09)
     if (err == ERR_OK) {
       file = &hs->file_handle;
     } else {
-      file = http_get_404_file(hs, &uri);
+#if LWIP_HTTPD_MAX_REQUEST_URI_LEN
+      /* check if uri is a directory name */
+      if (uri != http_uri_buf) {
+        size_t copy_len = LWIP_MIN(sizeof(http_uri_buf) - 1, uri_len);
+        if (copy_len > 0) {
+          MEMCPY(http_uri_buf, uri, copy_len);
+          http_uri_buf[copy_len] = 0;
+        }
+        file = http_find_default_file(hs, http_uri_buf, copy_len, sizeof(http_uri_buf), &uri, &tag_check);
+      }
+      if (file == NULL)
+#endif /* LWIP_HTTPD_MAX_REQUEST_URI_LEN */
+      {
+        file = http_get_404_file(hs, &uri);
+      }
     }
 #if LWIP_HTTPD_SSI
     if (file != NULL) {
@@ -2305,6 +2338,8 @@ static err_t
 http_init_file(struct http_state *hs, struct fs_file *file, int is_09, const char *uri,
                u8_t tag_check, char *params)
 {
+  printf("http_init_file(%s)\n", uri);
+
 #if !LWIP_HTTPD_SUPPORT_V09
   LWIP_UNUSED_ARG(is_09);
 #endif
-- 
2.11.0.windows.1

