diff --git a/swh/web/browse/utils.py b/swh/web/browse/utils.py
--- a/swh/web/browse/utils.py
+++ b/swh/web/browse/utils.py
@@ -21,6 +21,7 @@
reverse,
format_utc_iso_date,
rst_to_html,
+ browsers_supported_image_mimes,
)
from swh.web.config import get_config
@@ -241,19 +242,6 @@
return content_data
-_browsers_supported_image_mimes = set(
- [
- "image/gif",
- "image/png",
- "image/jpeg",
- "image/bmp",
- "image/webp",
- "image/svg",
- "image/svg+xml",
- ]
-)
-
-
def prepare_content_for_display(content_data, mime_type, path):
"""Function that prepares a content for HTML display.
@@ -288,10 +276,8 @@
mime_type = mime_type.replace("application/", "text/")
if mime_type.startswith("image/"):
- if mime_type in _browsers_supported_image_mimes:
+ if mime_type in browsers_supported_image_mimes:
content_data = base64.b64encode(content_data).decode("ascii")
- else:
- content_data = None
if mime_type.startswith("image/svg"):
mime_type = "image/svg+xml"
diff --git a/swh/web/common/utils.py b/swh/web/common/utils.py
--- a/swh/web/common/utils.py
+++ b/swh/web/common/utils.py
@@ -241,6 +241,19 @@
return ip
+browsers_supported_image_mimes = set(
+ [
+ "image/gif",
+ "image/png",
+ "image/jpeg",
+ "image/bmp",
+ "image/webp",
+ "image/svg",
+ "image/svg+xml",
+ ]
+)
+
+
def context_processor(request):
"""
Django context processor used to inject variables
@@ -260,6 +273,7 @@
"available_languages": None,
"swh_client_config": config["client_config"],
"oidc_enabled": bool(config["keycloak"]["server_url"]),
+ "browsers_supported_image_mimes": browsers_supported_image_mimes,
}
diff --git a/swh/web/templates/includes/content-display.html b/swh/web/templates/includes/content-display.html
--- a/swh/web/templates/includes/content-display.html
+++ b/swh/web/templates/includes/content-display.html
@@ -28,7 +28,7 @@
- {% elif "image/" in mimetype and content %}
+ {% elif mimetype in browsers_supported_image_mimes and content %}
{% elif "application/pdf" == mimetype %}
@@ -40,8 +40,7 @@
{% elif content %}
- Content with mime type {{ mimetype }} and encoding
- {{ encoding }} cannot be displayed.
+ Content with mime type {{ mimetype }} and encoding {{ encoding }} cannot be displayed.
{% else %}
{% include "includes/http-error.html" %}
{% endif %}
diff --git a/swh/web/tests/browse/views/test_content.py b/swh/web/tests/browse/views/test_content.py
--- a/swh/web/tests/browse/views/test_content.py
+++ b/swh/web/tests/browse/views/test_content.py
@@ -27,6 +27,7 @@
content_text_non_utf8,
content_text_no_highlight,
content_image_type,
+ content_unsupported_image_type_rendering,
content_text,
invalid_sha1,
unknown_content,
@@ -139,6 +140,26 @@
assert_contains(resp, url_raw)
+@given(content_unsupported_image_type_rendering())
+def test_content_view_image_no_rendering(client, archive_data, content):
+ url = reverse("browse-content", url_args={"query_string": content["sha1"]})
+
+ resp = client.get(url)
+
+ mimetype = content["mimetype"]
+ encoding = content["encoding"]
+
+ assert resp.status_code == 200
+ assert_template_used(resp, "browse/content.html")
+ assert_contains(
+ resp,
+ (
+ f"Content with mime type {mimetype} and encoding {encoding} "
+ "cannot be displayed."
+ ),
+ )
+
+
@given(content_text())
def test_content_view_text_with_path(client, archive_data, content):
path = content["path"]
diff --git a/swh/web/tests/data.py b/swh/web/tests/data.py
--- a/swh/web/tests/data.py
+++ b/swh/web/tests/data.py
@@ -12,6 +12,7 @@
from swh.indexer.mimetype import MimetypeIndexer
from swh.indexer.ctags import CtagsIndexer
from swh.indexer.storage import get_indexer_storage
+from swh.model.model import Content
from swh.model.hashutil import hash_to_hex, hash_to_bytes, DEFAULT_ALGORITHMS
from swh.model.model import Directory, Origin
from swh.loader.git.from_disk import GitLoaderFromArchive
@@ -137,6 +138,24 @@
_contents = {}
+def _add_extra_contents(storage, contents):
+ pbm_image_data = b"""P1
+# PBM example
+24 7
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0
+0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0
+0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0
+0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0
+0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0
+0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0"""
+
+ # add file with mimetype image/x-portable-bitmap in the archive content
+ pbm_content = Content.from_data(pbm_image_data)
+ storage.content_add([pbm_content])
+ contents.add(pbm_content.sha1)
+
+
# Tests data initialization
def _init_tests_data():
# To hold reference to the memory storage
@@ -209,38 +228,44 @@
dir_id = rev["directory"]
directories.add(hash_to_hex(dir_id))
for entry in dir_iterator(storage, dir_id):
- content_path[entry["sha1"]] = "/".join(
- [hash_to_hex(dir_id), entry["path"].decode("utf-8")]
- )
if entry["type"] == "file":
contents.add(entry["sha1"])
+ content_path[entry["sha1"]] = "/".join(
+ [hash_to_hex(dir_id), entry["path"].decode("utf-8")]
+ )
elif entry["type"] == "dir":
directories.add(hash_to_hex(entry["target"]))
+ _add_extra_contents(storage, contents)
+
# Get all checksums for each content
result = storage.content_get_metadata(contents)
contents = []
for sha1, contents_metadata in result.items():
- for content_metadata in contents_metadata:
- contents.append(
- {
- algo: hash_to_hex(content_metadata[algo])
- for algo in DEFAULT_ALGORITHMS
- }
- )
+ sha1 = contents_metadata[0]["sha1"]
+ content_metadata = {
+ algo: hash_to_hex(contents_metadata[0][algo]) for algo in DEFAULT_ALGORITHMS
+ }
+
+ path = ""
+ if sha1 in content_path:
path = content_path[sha1]
- cnt = next(storage.content_get([sha1]))
- mimetype, encoding = get_mimetype_and_encoding_for_content(cnt["data"])
- _, _, cnt["data"] = _re_encode_content(mimetype, encoding, cnt["data"])
- content_display_data = prepare_content_for_display(
- cnt["data"], mimetype, path
- )
- contents[-1]["path"] = path
- contents[-1]["mimetype"] = mimetype
- contents[-1]["encoding"] = encoding
- contents[-1]["hljs_language"] = content_display_data["language"]
- contents[-1]["data"] = content_display_data["content_data"]
- _contents[contents[-1]["sha1"]] = contents[-1]
+ cnt = next(storage.content_get([sha1]))
+ mimetype, encoding = get_mimetype_and_encoding_for_content(cnt["data"])
+ _, _, cnt["data"] = _re_encode_content(mimetype, encoding, cnt["data"])
+ content_display_data = prepare_content_for_display(cnt["data"], mimetype, path)
+
+ content_metadata.update(
+ {
+ "path": path,
+ "mimetype": mimetype,
+ "encoding": encoding,
+ "hljs_language": content_display_data["language"],
+ "data": content_display_data["content_data"],
+ }
+ )
+ _contents[hash_to_hex(sha1)] = content_metadata
+ contents.append(content_metadata)
# Create indexer storage instance that will be shared by indexers
idx_storage = get_indexer_storage("memory", {})
diff --git a/swh/web/tests/strategies.py b/swh/web/tests/strategies.py
--- a/swh/web/tests/strategies.py
+++ b/swh/web/tests/strategies.py
@@ -29,6 +29,7 @@
origins as new_origin_strategy,
snapshots as new_snapshot,
)
+from swh.web.common.utils import browsers_supported_image_mimes
from swh.web.tests.data import get_tests_data
# Module dedicated to the generation of input data for tests through
@@ -129,7 +130,18 @@
Hypothesis strategy returning random image contents ingested
into the test archive.
"""
- return content().filter(lambda c: c["mimetype"].startswith("image/"))
+ return content().filter(lambda c: c["mimetype"] in browsers_supported_image_mimes)
+
+
+def content_unsupported_image_type_rendering():
+ """
+ Hypothesis strategy returning random image contents ingested
+ into the test archive that can not be rendered by browsers.
+ """
+ return content().filter(
+ lambda c: c["mimetype"].startswith("image/")
+ and c["mimetype"] not in browsers_supported_image_mimes
+ )
def content_utf8_detected_as_binary():