1# Copyright 2014-2016 OpenMarket Ltd 2# Copyright 2020-2021 The Matrix.org Foundation C.I.C. 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15import logging 16from typing import TYPE_CHECKING 17 18from synapse.http.server import DirectServeJsonResource, set_cors_headers 19from synapse.http.servlet import parse_boolean 20from synapse.http.site import SynapseRequest 21 22from ._base import parse_media_id, respond_404 23 24if TYPE_CHECKING: 25 from synapse.rest.media.v1.media_repository import MediaRepository 26 from synapse.server import HomeServer 27 28logger = logging.getLogger(__name__) 29 30 31class DownloadResource(DirectServeJsonResource): 32 isLeaf = True 33 34 def __init__(self, hs: "HomeServer", media_repo: "MediaRepository"): 35 super().__init__() 36 self.media_repo = media_repo 37 self.server_name = hs.hostname 38 39 async def _async_render_GET(self, request: SynapseRequest) -> None: 40 set_cors_headers(request) 41 request.setHeader( 42 b"Content-Security-Policy", 43 b"sandbox;" 44 b" default-src 'none';" 45 b" script-src 'none';" 46 b" plugin-types application/pdf;" 47 b" style-src 'unsafe-inline';" 48 b" media-src 'self';" 49 b" object-src 'self';", 50 ) 51 # Limited non-standard form of CSP for IE11 52 request.setHeader(b"X-Content-Security-Policy", b"sandbox;") 53 request.setHeader( 54 b"Referrer-Policy", 55 b"no-referrer", 56 ) 57 server_name, media_id, name = parse_media_id(request) 58 if server_name == self.server_name: 59 await self.media_repo.get_local_media(request, media_id, name) 60 else: 61 allow_remote = parse_boolean(request, "allow_remote", default=True) 62 if not allow_remote: 63 logger.info( 64 "Rejecting request for remote media %s/%s due to allow_remote", 65 server_name, 66 media_id, 67 ) 68 respond_404(request) 69 return 70 71 await self.media_repo.get_remote_media(request, server_name, media_id, name) 72