diff --git a/Makefile.am b/Makefile.am index b6223f529..bb60218d5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -406,6 +406,7 @@ libutil_a_SOURCES = \ src/util/UTF8.cxx src/util/UTF8.hxx \ src/util/CharUtil.hxx \ src/util/NumberParser.hxx \ + src/util/MimeType.cxx src/util/MimeType.hxx \ src/util/StringPointer.hxx \ src/util/StringView.cxx src/util/StringView.hxx \ src/util/AllocatedString.cxx src/util/AllocatedString.hxx \ @@ -2108,6 +2109,7 @@ test_test_util_SOURCES = \ test/DivideStringTest.hxx \ test/SplitStringTest.hxx \ test/UriUtilTest.hxx \ + test/MimeTypeTest.hxx \ test/TestCircularBuffer.hxx \ test/test_util.cxx test_test_util_CPPFLAGS = $(AM_CPPFLAGS) $(CPPUNIT_CFLAGS) -DCPPUNIT_HAVE_RTTI=0 diff --git a/src/TagStream.cxx b/src/TagStream.cxx index 81e4d7679..1ffeac128 100644 --- a/src/TagStream.cxx +++ b/src/TagStream.cxx @@ -22,6 +22,7 @@ #include "tag/Generic.hxx" #include "tag/TagHandler.hxx" #include "tag/TagBuilder.hxx" +#include "util/MimeType.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" #include "decoder/DecoderList.hxx" @@ -51,11 +52,15 @@ tag_stream_scan(InputStream &is, const TagHandler &handler, void *ctx) UriSuffixBuffer suffix_buffer; const char *const suffix = uri_get_suffix(is.GetURI(), suffix_buffer); - const char *const mime = is.GetMimeType(); + const char *mime = is.GetMimeType(); if (suffix == nullptr && mime == nullptr) return false; + std::string mime_base; + if (mime != nullptr) + mime = (mime_base = GetMimeTypeBase(mime)).c_str(); + return decoder_plugins_try([suffix, mime, &is, &handler, ctx](const DecoderPlugin &plugin){ is.LockRewind(IgnoreError()); diff --git a/src/decoder/DecoderThread.cxx b/src/decoder/DecoderThread.cxx index a99d73472..e393ae8d6 100644 --- a/src/decoder/DecoderThread.cxx +++ b/src/decoder/DecoderThread.cxx @@ -32,6 +32,7 @@ #include "input/InputStream.hxx" #include "input/LocalOpen.hxx" #include "DecoderList.hxx" +#include "util/MimeType.hxx" #include "util/UriUtil.hxx" #include "util/Error.hxx" #include "util/Domain.hxx" @@ -180,7 +181,8 @@ decoder_check_plugin_mime(const DecoderPlugin &plugin, const InputStream &is) assert(plugin.stream_decode != nullptr); const char *mime_type = is.GetMimeType(); - return mime_type != nullptr && plugin.SupportsMimeType(mime_type); + return mime_type != nullptr && + plugin.SupportsMimeType(GetMimeTypeBase(mime_type).c_str()); } gcc_pure diff --git a/src/playlist/PlaylistRegistry.cxx b/src/playlist/PlaylistRegistry.cxx index aca1d271a..6e8330f10 100644 --- a/src/playlist/PlaylistRegistry.cxx +++ b/src/playlist/PlaylistRegistry.cxx @@ -31,6 +31,7 @@ #include "plugins/CuePlaylistPlugin.hxx" #include "plugins/EmbeddedCuePlaylistPlugin.hxx" #include "input/InputStream.hxx" +#include "util/MimeType.hxx" #include "util/UriUtil.hxx" #include "util/StringUtil.hxx" #include "util/Error.hxx" @@ -253,7 +254,7 @@ playlist_list_open_stream(InputStreamPtr &&is, const char *uri) const char *const mime = is->GetMimeType(); if (mime != nullptr) { auto playlist = playlist_list_open_stream_mime(std::move(is), - mime); + GetMimeTypeBase(mime).c_str()); if (playlist != nullptr) return playlist; } diff --git a/src/util/MimeType.cxx b/src/util/MimeType.cxx new file mode 100644 index 000000000..64822555b --- /dev/null +++ b/src/util/MimeType.cxx @@ -0,0 +1,31 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "MimeType.hxx" + +#include + +std::string +GetMimeTypeBase(const char *s) +{ + const char *semicolon = strchr(s, ';'); + return semicolon != nullptr + ? std::string(s, semicolon) + : std::string(s); +} diff --git a/src/util/MimeType.hxx b/src/util/MimeType.hxx new file mode 100644 index 000000000..fe8f385b2 --- /dev/null +++ b/src/util/MimeType.hxx @@ -0,0 +1,33 @@ +/* + * Copyright 2003-2016 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#ifndef MPD_MIME_TYPE_HXX +#define MPD_MIME_TYPE_HXX + +#include + +/** + * Extract the part of the MIME type before the parameters, i.e. the + * part before the semicolon. If there is no semicolon, it returns + * the string as-is. + */ +std::string +GetMimeTypeBase(const char *s); + +#endif diff --git a/test/MimeTypeTest.hxx b/test/MimeTypeTest.hxx new file mode 100644 index 000000000..0e243e6ba --- /dev/null +++ b/test/MimeTypeTest.hxx @@ -0,0 +1,28 @@ +/* + * Unit tests for src/util/ + */ + +#include "check.h" +#include "util/MimeType.hxx" + +#include +#include + +#include + +class MimeTypeTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(MimeTypeTest); + CPPUNIT_TEST(TestBase); + CPPUNIT_TEST_SUITE_END(); + +public: + void TestBase() { + CPPUNIT_ASSERT("" == GetMimeTypeBase("")); + CPPUNIT_ASSERT("" == GetMimeTypeBase(";")); + CPPUNIT_ASSERT("foo" == GetMimeTypeBase("foo")); + CPPUNIT_ASSERT("foo/bar" == GetMimeTypeBase("foo/bar")); + CPPUNIT_ASSERT("foo/bar" == GetMimeTypeBase("foo/bar;")); + CPPUNIT_ASSERT("foo/bar" == GetMimeTypeBase("foo/bar; x=y")); + CPPUNIT_ASSERT("foo/bar" == GetMimeTypeBase("foo/bar;x=y")); + } +}; diff --git a/test/test_util.cxx b/test/test_util.cxx index c2d73d7d9..37e352678 100644 --- a/test/test_util.cxx +++ b/test/test_util.cxx @@ -6,6 +6,7 @@ #include "DivideStringTest.hxx" #include "SplitStringTest.hxx" #include "UriUtilTest.hxx" +#include "MimeTypeTest.hxx" #include "TestCircularBuffer.hxx" #include @@ -18,6 +19,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION(DivideStringTest); CPPUNIT_TEST_SUITE_REGISTRATION(SplitStringTest); CPPUNIT_TEST_SUITE_REGISTRATION(UriUtilTest); +CPPUNIT_TEST_SUITE_REGISTRATION(MimeTypeTest); CPPUNIT_TEST_SUITE_REGISTRATION(TestCircularBuffer); int