From a0581a926bb841ca6f2e1299d47206e67ee780f9 Mon Sep 17 00:00:00 2001
From: Andy Green <andy@warmcat.com>
Date: Sat, 24 Feb 2018 08:14:17 +0800
Subject: [PATCH] esp32: map basic auth to nvs

---
 READMEs/README.esp32.md     | 12 ++++++++++++
 lib/misc/romfs.c            |  6 ++++++
 lib/plat/lws-plat-esp32.c   | 30 ++++++++++++++++++++++++++++++
 lib/private-libwebsockets.h |  5 +++++
 lib/server/server.c         |  3 ++-
 5 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/READMEs/README.esp32.md b/READMEs/README.esp32.md
index df792d00c..1abcfb6d9 100644
--- a/READMEs/README.esp32.md
+++ b/READMEs/README.esp32.md
@@ -23,3 +23,15 @@ Factory Reset or Uninitialized|Factory|AP: ESP_012345|80|http://192.168.4.1|fact
 User configuration|Factory|AP: config-model-serial|443|https://192.168.4.1|index.html - user set up his AP information
 Operation|OTA|Station only|443|https://model-serial.local|OTA application
 
+## Basic Auth
+
+The lws-esp32-test-server-demos app also demos basic auth.
+
+On a normal platform this is done by binding a mount to a text file somewhere in the filesystem, which
+contains user:password information one per line.
+
+On ESP32 there is not necessarily any generic VFS in use.  So instead, the basic auth lookup is bound to
+a given nvs domain, where the username is the key and the password the value.  main/main.c in the test
+demos app shows how to both make the mount use basic auth, and how to set a user:password combination
+using nvs.
+
diff --git a/lib/misc/romfs.c b/lib/misc/romfs.c
index 540382e65..099bf7d03 100644
--- a/lib/misc/romfs.c
+++ b/lib/misc/romfs.c
@@ -142,6 +142,9 @@ romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path)
 			cp++;
 		}
 
+		while (*p && *p == '/' && p[1] == '/')
+			p++;
+
 		if (!*cp && (!*p || *p == '/') &&
 		    (ntohl(next_be) & 7) == RFST_HARDLINK) {
 			set_cache(i, sizeof(*i));
@@ -162,6 +165,9 @@ romfs_lookup(romfs_t romfs, romfs_inode_t start, const char *path)
 		if (!*p && *cp == '/')
 			return NULL;
 
+		while (*p && *p == '/' && p[1] == '/')
+			p++;
+
 		if (*p == '/' && !*cp) {
 			set_cache(i, sizeof(*i));
 			switch (ntohl(ci->next) & 7) {
diff --git a/lib/plat/lws-plat-esp32.c b/lib/plat/lws-plat-esp32.c
index 5e5c8d08d..4892576e9 100644
--- a/lib/plat/lws-plat-esp32.c
+++ b/lib/plat/lws-plat-esp32.c
@@ -633,6 +633,36 @@ LWS_VISIBLE void esp32_uvtimer_cb(TimerHandle_t t)
 	p->cb(p->t);
 }
 
+int
+lws_find_string_in_file(const char *filename, const char *string, int stringlen)
+{
+	nvs_handle nvh;
+	size_t s;
+	int n;
+	char buf[64], result[64];
+	const char *p = strchr(string, ':'), *q;
+
+	if (!p)
+		return 1;
+
+	q = string;
+	n = 0;
+	while (n < sizeof(buf) - 1 && q != p)
+		buf[n++] = *q++;
+	buf[n] = '\0';
+
+	ESP_ERROR_CHECK(nvs_open(filename, NVS_READWRITE, &nvh));
+
+	s = sizeof(result) - 1;
+	n = nvs_get_str(nvh, buf, result, &s);
+	nvs_close(nvh);
+
+	if (n != ESP_OK)
+		return 2;
+
+	return !strcmp(p + 1, result);
+}
+
 /* helper functionality */
 
 #include "misc/romfs.h"
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index 209adddfb..5b915793a 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -1305,6 +1305,11 @@ LWS_EXTERN void lws_feature_status_libevent(struct lws_context_creation_info *in
 #endif
 
 
+#if defined(LWS_WITH_ESP32)
+LWS_EXTERN int
+lws_find_string_in_file(const char *filename, const char *string, int stringlen);
+#endif
+
 #ifdef LWS_WITH_IPV6
 #define LWS_IPV6_ENABLED(vh) \
 	(!lws_check_opt(vh->context->options, LWS_SERVER_OPTION_DISABLE_IPV6) && \
diff --git a/lib/server/server.c b/lib/server/server.c
index 48f5a2ad0..1b5b3b511 100644
--- a/lib/server/server.c
+++ b/lib/server/server.c
@@ -607,7 +607,7 @@ lws_find_mount(struct lws *wsi, const char *uri_ptr, int uri_len)
 }
 
 #if LWS_POSIX
-
+#if !defined(LWS_WITH_ESP32)
 static int
 lws_find_string_in_file(const char *filename, const char *string, int stringlen)
 {
@@ -651,6 +651,7 @@ lws_find_string_in_file(const char *filename, const char *string, int stringlen)
 
 	return hit;
 }
+#endif
 
 static int
 lws_unauthorised_basic_auth(struct lws *wsi)