From fa3b334ed0bcbfaae247d7d9ceee3aded7fdef07 Mon Sep 17 00:00:00 2001 From: Johannes Aalto Date: Fri, 24 Sep 2021 14:12:30 +0300 Subject: [PATCH 1/2] Add test for encoding local file links with special characters Add test to make sure Sphinx uses proper URL encoding for special characters in file names. Use test_html_download() since it test_html5_output() doesn't quite seem to have easy pattern to verify the contents of href attribute. Issue #3097 Signed-off-by: Johannes Aalto --- tests/roots/test-root/file_with_special_#_chars.xyz | 0 tests/roots/test-root/includes.txt | 1 + tests/test_build_html.py | 6 ++++++ 3 files changed, 7 insertions(+) create mode 100644 tests/roots/test-root/file_with_special_#_chars.xyz diff --git a/tests/roots/test-root/file_with_special_#_chars.xyz b/tests/roots/test-root/file_with_special_#_chars.xyz new file mode 100644 index 00000000000..e69de29bb2d diff --git a/tests/roots/test-root/includes.txt b/tests/roots/test-root/includes.txt index 5deec9864e3..19b98ae12c2 100644 --- a/tests/roots/test-root/includes.txt +++ b/tests/roots/test-root/includes.txt @@ -3,6 +3,7 @@ Testing downloadable files Download :download:`img.png` here. Download :download:`this ` there. +Download :download:`file with special characters `. Test file and literal inclusion =============================== diff --git a/tests/test_build_html.py b/tests/test_build_html.py index d295cf982cd..2e9a43f51cd 100644 --- a/tests/test_build_html.py +++ b/tests/test_build_html.py @@ -456,6 +456,12 @@ def test_html_download(app): assert (app.outdir / matched.group(1)).exists() assert matched.group(1) == filename + pattern = ('') + matched = re.search(pattern, result) + assert matched + assert (app.outdir / matched.group(1) / "file_with_special_#_chars.xyz").exists() + @pytest.mark.sphinx('html', testroot='roles-download') def test_html_download_role(app, status, warning): From b2bd115dc8359c7e396579789e90a9aea6f35e1b Mon Sep 17 00:00:00 2001 From: Johannes Aalto Date: Wed, 15 Sep 2021 09:30:04 +0300 Subject: [PATCH 2/2] Fix local file download by encoding URL Properly encode links to files with special characters for the user to actually be able to download them. The issue still remains for image files but the logic path is quite different than with other files fix might involve changes to docutils. Fixes sphinx-doc/sphinx#3097 Signed-off-by: Johannes Aalto --- sphinx/writers/html.py | 4 +++- sphinx/writers/html5.py | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 429369edce0..544ac184b38 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -12,6 +12,7 @@ import os import posixpath import re +import urllib.parse import warnings from typing import TYPE_CHECKING, Iterable, Tuple, cast @@ -589,7 +590,8 @@ def visit_download_reference(self, node: Element) -> None: self.context.append('') elif 'filename' in node: atts['class'] += ' internal' - atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + atts['href'] = posixpath.join(self.builder.dlpath, + urllib.parse.quote(node['filename'])) self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py index 84b963ee556..27139f066b2 100644 --- a/sphinx/writers/html5.py +++ b/sphinx/writers/html5.py @@ -11,6 +11,7 @@ import os import posixpath import re +import urllib.parse import warnings from typing import TYPE_CHECKING, Iterable, Tuple, cast @@ -529,7 +530,8 @@ def visit_download_reference(self, node: Element) -> None: self.context.append('') elif 'filename' in node: atts['class'] += ' internal' - atts['href'] = posixpath.join(self.builder.dlpath, node['filename']) + atts['href'] = posixpath.join(self.builder.dlpath, + urllib.parse.quote(node['filename'])) self.body.append(self.starttag(node, 'a', '', **atts)) self.context.append('') else: