summary refs log tree commit diff
path: root/synapse
diff options
context:
space:
mode:
authorWill Hunt <will@half-shot.uk>2023-09-29 12:19:38 +0100
committerGitHub <noreply@github.com>2023-09-29 07:19:38 -0400
commit79eb6c0cdc15ccb5083368c923653862a4d2d23a (patch)
treecab766d8cf3a9447953e39f78b17a3255d1c2de6 /synapse
parentRemove warnings from the docs about using message retention. (#16382) (diff)
downloadsynapse-79eb6c0cdc15ccb5083368c923653862a4d2d23a.tar.xz
Support rendering some media downloads as inline (#15988)
Use an `inline` Content-Disposition header when the media is
"safe" to display inline (some known text, image, video, audio
formats).
Diffstat (limited to 'synapse')
-rw-r--r--synapse/media/_base.py42
1 files changed, 40 insertions, 2 deletions
diff --git a/synapse/media/_base.py b/synapse/media/_base.py
index 20cb8b9010..80c448de2b 100644
--- a/synapse/media/_base.py
+++ b/synapse/media/_base.py
@@ -50,6 +50,39 @@ TEXT_CONTENT_TYPES = [
     "text/xml",
 ]
 
+# A list of all content types that are "safe" to be rendered inline in a browser.
+INLINE_CONTENT_TYPES = [
+    "text/css",
+    "text/plain",
+    "text/csv",
+    "application/json",
+    "application/ld+json",
+    # We allow some media files deemed as safe, which comes from the matrix-react-sdk.
+    # https://github.com/matrix-org/matrix-react-sdk/blob/a70fcfd0bcf7f8c85986da18001ea11597989a7c/src/utils/blobs.ts#L51
+    # SVGs are *intentionally* omitted.
+    "image/jpeg",
+    "image/gif",
+    "image/png",
+    "image/apng",
+    "image/webp",
+    "image/avif",
+    "video/mp4",
+    "video/webm",
+    "video/ogg",
+    "video/quicktime",
+    "audio/mp4",
+    "audio/webm",
+    "audio/aac",
+    "audio/mpeg",
+    "audio/ogg",
+    "audio/wave",
+    "audio/wav",
+    "audio/x-wav",
+    "audio/x-pn-wav",
+    "audio/flac",
+    "audio/x-flac",
+]
+
 
 def parse_media_id(request: Request) -> Tuple[str, str, Optional[str]]:
     """Parses the server name, media ID and optional file name from the request URI
@@ -153,8 +186,13 @@ def add_file_headers(
 
     request.setHeader(b"Content-Type", content_type.encode("UTF-8"))
 
-    # Use a Content-Disposition of attachment to force download of media.
-    disposition = "attachment"
+    # A strict subset of content types is allowed to be inlined  so that they may
+    # be viewed directly in a browser. Other file types are forced to be downloads.
+    if media_type.lower() in INLINE_CONTENT_TYPES:
+        disposition = "inline"
+    else:
+        disposition = "attachment"
+
     if upload_name:
         # RFC6266 section 4.1 [1] defines both `filename` and `filename*`.
         #