From 8b13c0762554f567fdd47a52bdcdd39a59d48fbe Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Tue, 27 Aug 2019 14:15:26 +0200
Subject: [PATCH] Fixed #893: empty contentType causing client crash in some
 Subsonic payloads

---
 api/funkwhale_api/subsonic/serializers.py | 10 +++++++++-
 api/tests/subsonic/test_serializers.py    | 23 +++++++++++++++++++++++
 changes/changelog.d/893.bugfix            |  1 +
 3 files changed, 33 insertions(+), 1 deletion(-)
 create mode 100644 changes/changelog.d/893.bugfix

diff --git a/api/funkwhale_api/subsonic/serializers.py b/api/funkwhale_api/subsonic/serializers.py
index 994ad682..85b969b7 100644
--- a/api/funkwhale_api/subsonic/serializers.py
+++ b/api/funkwhale_api/subsonic/serializers.py
@@ -5,6 +5,7 @@ from rest_framework import serializers
 
 from funkwhale_api.history import models as history_models
 from funkwhale_api.music import models as music_models
+from funkwhale_api.music import utils as music_utils
 
 
 def get_artist_data(artist_values):
@@ -71,7 +72,14 @@ def get_track_data(album, track, upload):
         "artist": album.artist.name,
         "track": track.position or 1,
         "discNumber": track.disc_number or 1,
-        "contentType": upload.mimetype,
+        # Ugly fallback to mp3 but some subsonic clients fail if the value is empty or null, and we don't always
+        # have the info on legacy uploads
+        "contentType": upload.mimetype
+        or (
+            music_utils.get_type_from_ext(upload.extension)
+            if upload.extension
+            else "audio/mpeg"
+        ),
         "suffix": upload.extension or "",
         "duration": upload.duration or 0,
         "created": track.creation_date,
diff --git a/api/tests/subsonic/test_serializers.py b/api/tests/subsonic/test_serializers.py
index 2c468a4f..d6025a90 100644
--- a/api/tests/subsonic/test_serializers.py
+++ b/api/tests/subsonic/test_serializers.py
@@ -1,3 +1,5 @@
+import pytest
+
 from funkwhale_api.music import models as music_models
 from funkwhale_api.subsonic import serializers
 
@@ -61,6 +63,27 @@ def test_get_artist_serializer(factories):
     assert serializers.GetArtistSerializer(artist).data == expected
 
 
+@pytest.mark.parametrize(
+    "mimetype, extension, expected",
+    [
+        ("audio/ogg", "noop", "audio/ogg"),
+        ("", "ogg", "audio/ogg"),
+        ("", "mp3", "audio/mpeg"),
+        ("", "", "audio/mpeg"),
+    ],
+)
+def test_get_track_data_content_type(mimetype, extension, expected, factories):
+    upload = factories["music.Upload"]()
+    upload.mimetype = mimetype
+    upload.audio_file = "test.{}".format(extension)
+
+    data = serializers.get_track_data(
+        album=upload.track.album, track=upload.track, upload=upload
+    )
+
+    assert data["contentType"] == expected
+
+
 def test_get_album_serializer(factories):
     artist = factories["music.Artist"]()
     album = factories["music.Album"](artist=artist)
diff --git a/changes/changelog.d/893.bugfix b/changes/changelog.d/893.bugfix
new file mode 100644
index 00000000..f37ae2a9
--- /dev/null
+++ b/changes/changelog.d/893.bugfix
@@ -0,0 +1 @@
+Fixed empty contentType causing client crash in some Subsonic payloads (#893)
-- 
GitLab