diff --git a/api/funkwhale_api/music/models.py b/api/funkwhale_api/music/models.py index 309eb1266dd5fd8db1446ff8981a89de4a1fecf9..cf6a0b7ba310cbbe7354a20072de3a6f352333e4 100644 --- a/api/funkwhale_api/music/models.py +++ b/api/funkwhale_api/music/models.py @@ -870,7 +870,14 @@ class UploadVersion(models.Model): @property def filename(self): - return self.upload.filename + try: + return ( + self.upload.track.full_name + + "." + + utils.MIMETYPE_TO_EXTENSION[self.mimetype] + ) + except KeyError: + return self.upload.filename @property def audio_file_path(self): diff --git a/api/funkwhale_api/music/views.py b/api/funkwhale_api/music/views.py index 391a4b333fe45628626383c4479d4a952c9df4b5..4f8f35ced2b2e7a0f6319b568fad511fb48dd711 100644 --- a/api/funkwhale_api/music/views.py +++ b/api/funkwhale_api/music/views.py @@ -285,6 +285,11 @@ def should_transcode(upload, format, max_bitrate=None): return format_need_transcoding or bitrate_need_transcoding +def get_content_disposition(filename): + filename = "filename*=UTF-8''{}".format(urllib.parse.quote(filename)) + return "attachment; {}".format(filename) + + def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True): f = upload # we update the accessed_date @@ -342,8 +347,7 @@ def handle_serve(upload, user, format=None, max_bitrate=None, proxy_media=True): mapping = {"nginx": "X-Accel-Redirect", "apache2": "X-Sendfile"} file_header = mapping[settings.REVERSE_PROXY_TYPE] response[file_header] = file_path - filename = "filename*=UTF-8''{}".format(urllib.parse.quote(filename)) - response["Content-Disposition"] = "attachment; {}".format(filename) + response["Content-Disposition"] = get_content_disposition(filename) if mt: response["Content-Type"] = mt diff --git a/api/tests/music/test_views.py b/api/tests/music/test_views.py index 102b5a790a82d8d6fc174df72b414d0bf64033bf..25845e738b228b1b1e969c04070f2de134d454eb 100644 --- a/api/tests/music/test_views.py +++ b/api/tests/music/test_views.py @@ -1,6 +1,7 @@ import io import magic import os +import urllib.parse import pytest from django.urls import reverse @@ -412,7 +413,7 @@ def test_handle_serve_create_mp3_version(factories, now): user = factories["users.User"]() upload = factories["music.Upload"](bitrate=42) response = views.handle_serve(upload, user, format="mp3") - + expected_filename = upload.track.full_name + ".mp3" version = upload.versions.latest("id") assert version.mimetype == "audio/mpeg" @@ -421,7 +422,9 @@ def test_handle_serve_create_mp3_version(factories, now): assert version.audio_file_path.endswith(".mp3") assert version.size == version.audio_file.size assert magic.from_buffer(version.audio_file.read(), mime=True) == "audio/mpeg" - + assert response["Content-Disposition"] == "attachment; filename*=UTF-8''{}".format( + urllib.parse.quote(expected_filename) + ) assert response.status_code == 200 diff --git a/changes/changelog.d/848.bugfix b/changes/changelog.d/848.bugfix new file mode 100644 index 0000000000000000000000000000000000000000..478a8d42cc1fc6dbcf217a0bdb1721146c6744a4 --- /dev/null +++ b/changes/changelog.d/848.bugfix @@ -0,0 +1 @@ +Fixed invalid file extension for transcoded tracks (#848)