From 6b9a3c656d3cb00ba748e3c4a62078dde7562ea6 Mon Sep 17 00:00:00 2001 From: Vladimir Poleh Date: Wed, 19 May 2021 23:36:46 +0300 Subject: [PATCH] app: Fixed download for the files with non-ASCII characters in name. Replace non-ASCII characters with "?" and add escaped unicode version of the file name to the "Content-Disposition" header to fix problems with thumbnails and downloading for the gcode file with non-ASCII characters in filename. Signed-off-by: Uladzimir Palekh --- moonraker/app.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/moonraker/app.py b/moonraker/app.py index 57b8d9e..58ba9b9 100644 --- a/moonraker/app.py +++ b/moonraker/app.py @@ -11,6 +11,7 @@ import logging import json import datetime import traceback +import urllib.parse import tornado import tornado.iostream import tornado.httputil @@ -530,8 +531,11 @@ class FileRequestHandler(AuthorizedFileHandler): # a file assert isinstance(self.absolute_path, str) basename = os.path.basename(self.absolute_path) + ascii_basename = self._escape_filename_to_ascii(basename) + utf8_basename = self._escape_filename_to_utf8(basename) self.set_header( - "Content-Disposition", f"attachment; filename={basename}") + "Content-Disposition", f"attachment; filename={ascii_basename}; " + f"filename*=UTF-8\'\'{utf8_basename}") async def delete(self, path: str) -> None: path = self.request.path.lstrip("/").split("/", 2)[-1] @@ -633,6 +637,12 @@ class FileRequestHandler(AuthorizedFileHandler): else: assert self.request.method == "HEAD" + def _escape_filename_to_ascii(self, basename: str) -> str: + return basename.encode("ascii", "replace").decode() + + def _escape_filename_to_utf8(self, basename: str) -> str: + return urllib.parse.quote(basename, encoding="utf-8") + @classmethod def _get_cached_version(cls, abs_path: str) -> Optional[str]: with cls._lock: