-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
Support rendering previews with data: URLs in them #11767
Changes from 1 commit
ff7c377
5b09001
fb448dd
9b98fea
f07df94
6cd9b5b
88917c0
b9a1c66
116015f
3b38444
e042244
deeec27
5124a94
d38a07c
043b4c1
2042da1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -23,6 +23,7 @@ | |
| import traceback | ||
| from typing import TYPE_CHECKING, BinaryIO, Iterable, Optional, Tuple | ||
| from urllib import parse as urlparse | ||
| from urllib.request import urlopen | ||
|
|
||
| import attr | ||
|
|
||
|
|
@@ -417,6 +418,38 @@ async def _download_url( | |
|
|
||
| return length, uri, code, media_type, download_name, expires, etag | ||
|
|
||
| async def _parse_data_url( | ||
| self, url: str, output_stream: BinaryIO | ||
| ) -> Tuple[int, str, int, str, Optional[str], int, Optional[str]]: | ||
| """ | ||
| Parses a data: URL and stores it. | ||
| """ | ||
| try: | ||
| logger.debug("Trying to parse data url '%s'", url) | ||
| with urlopen(url) as url_info: | ||
| # TODO Can this be more efficient. | ||
| output_stream.write(url_info.read()) | ||
| except Exception as e: | ||
| logger.warning("Error parsing data: URL %s: %r", url, e) | ||
|
|
||
| raise SynapseError( | ||
| 500, | ||
| "Failed to parse data URL: %s" | ||
| % (traceback.format_exception_only(sys.exc_info()[0], e),), | ||
| Codes.UNKNOWN, | ||
| ) | ||
|
|
||
| length = output_stream.seek(1) | ||
clokep marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| media_type = url_info.headers.get_content_type() | ||
|
||
|
|
||
| # Some features are not supported by data: URLs. | ||
| download_name = None | ||
| expires = ONE_HOUR | ||
| etag = None | ||
|
|
||
| return length, url, 200, media_type, download_name, expires, etag | ||
|
|
||
| async def _handle_url(self, url: str, user: UserID) -> MediaInfo: | ||
| """ | ||
| Fetches remote content and parses the headers to generate a MediaInfo. | ||
|
|
@@ -441,15 +474,27 @@ async def _handle_url(self, url: str, user: UserID) -> MediaInfo: | |
| file_info = FileInfo(server_name=None, file_id=file_id, url_cache=True) | ||
|
|
||
| with self.media_storage.store_into_file(file_info) as (f, fname, finish): | ||
| ( | ||
| length, | ||
| uri, | ||
| code, | ||
| media_type, | ||
| download_name, | ||
| expires, | ||
| etag, | ||
| ) = await self._download_url(url, f) | ||
| if url.startswith("data:"): | ||
| ( | ||
| length, | ||
| uri, | ||
| code, | ||
| media_type, | ||
| download_name, | ||
| expires, | ||
| etag, | ||
| ) = await self._parse_data_url(url, f) | ||
| else: | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We might want to assert HTTP(S) schemes here as additional error checking.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah I feel like I'd be happier having a few select allowed protocols rather than singling out
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yep, note that those will fail right now (we won't try them), but it would be better to be explicit, I think!
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this might actually be tougher to get correct than I initially though since we seem to support previewing scheme-less URLs. I'm not sure it makes sense to refactor that as part of this.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, fair enough. |
||
| ( | ||
| length, | ||
| uri, | ||
| code, | ||
| media_type, | ||
| download_name, | ||
| expires, | ||
| etag, | ||
| ) = await self._download_url(url, f) | ||
|
|
||
| await finish() | ||
|
|
||
| try: | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.