From e0fb308972baa81c5f94fc8203a65226bcf65d8e Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 9 Aug 2022 16:36:57 -0700 Subject: [PATCH] Decode percent encoded file paths and set charset Also, fix multiple file uploads from directory browser. Fixes #6646 --- .../shared/web_workflow/static/directory.js | 4 +- supervisor/shared/web_workflow/web_workflow.c | 38 +++++++++++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/supervisor/shared/web_workflow/static/directory.js b/supervisor/shared/web_workflow/static/directory.js index 91389343d6..b6ea1b09bb 100644 --- a/supervisor/shared/web_workflow/static/directory.js +++ b/supervisor/shared/web_workflow/static/directory.js @@ -149,10 +149,10 @@ async function upload(e) { ) if (response.ok) { refresh_list(); - files.value = ""; - upload_button.disabled = true; } } + files.value = ""; + upload_button.disabled = true; } async function del(e) { diff --git a/supervisor/shared/web_workflow/web_workflow.c b/supervisor/shared/web_workflow/web_workflow.c index bc76112ed3..e644a40f14 100644 --- a/supervisor/shared/web_workflow/web_workflow.c +++ b/supervisor/shared/web_workflow/web_workflow.c @@ -659,13 +659,13 @@ static void _reply_with_file(socketpool_socket_obj_t *socket, _request *request, mp_printf(&_socket_print, "Content-Length: %d\r\n", total_length); // TODO: Make this a table to save space. if (_endswith(filename, ".txt") || _endswith(filename, ".py")) { - _send_str(socket, "Content-Type: text/plain\r\n"); + _send_strs(socket, "Content-Type: text/plain", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".js")) { - _send_str(socket, "Content-Type: text/javascript\r\n"); + _send_strs(socket, "Content-Type: text/javascript", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".html")) { - _send_str(socket, "Content-Type: text/html\r\n"); + _send_strs(socket, "Content-Type: text/html", ";charset=UTF-8\r\n", NULL); } else if (_endswith(filename, ".json")) { - _send_str(socket, "Content-Type: application/json\r\n"); + _send_strs(socket, "Content-Type: application/json", ";charset=UTF-8\r\n", NULL); } else { _send_str(socket, "Content-Type: application/octet-stream\r\n"); } @@ -966,6 +966,16 @@ static void _reply_websocket_upgrade(socketpool_socket_obj_t *socket, _request * // socket is now closed and "disconnected". } +static uint8_t _hex2nibble(char h) { + if ('0' <= h && h <= '9') { + return h - '0'; + } else if ('A' <= h && h <= 'F') { + return h - 'A' + 0xa; + } + // Shouldn't usually use lower case. + return h - 'a' + 0xa; +} + static bool _reply(socketpool_socket_obj_t *socket, _request *request) { if (request->redirect) { _reply_redirect(socket, request, request->path); @@ -983,6 +993,26 @@ static bool _reply(socketpool_socket_obj_t *socket, _request *request) { _reply_forbidden(socket, request); } } else { + // Decode any percent encoded bytes so that we're left with UTF-8. + // We only do this on /fs/ paths and after redirect so that any + // path echoing we do stays encoded. + size_t o = 0; + size_t i = 0; + while (i < strlen(request->path)) { + if (request->path[i] == '%') { + request->path[o] = _hex2nibble(request->path[i + 1]) << 4 | _hex2nibble(request->path[i + 2]); + i += 3; + } else { + if (i != o) { + request->path[o] = request->path[i]; + } + i += 1; + } + o += 1; + } + if (o < i) { + request->path[o] = '\0'; + } char *path = request->path + 3; size_t pathlen = strlen(path); FATFS *fs = filesystem_circuitpy();