From 9abb686eebfa0a512a45586d3ff3d46b4da8ecff Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sun, 16 Feb 2020 20:48:46 +0100 Subject: [PATCH 01/16] increment version number to 0.21.21 --- NEWS | 2 ++ android/AndroidManifest.xml | 4 ++-- doc/conf.py | 2 +- meson.build | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index b6e6dff7b..4e35fd90a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +ver 0.21.21 (not yet released) + ver 0.21.20 (2020/02/16) * decoder - audiofile, ffmpeg, sndfile: handle MIME type "audio/wav" diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index a7ea8a550..83286b0b7 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="44" + android:versionName="0.21.21"> diff --git a/doc/conf.py b/doc/conf.py index 836c2b58c..a0d4b393f 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -38,7 +38,7 @@ author = 'Max Kellermann' # built documents. # # The short X.Y version. -version = '0.21.20' +version = '0.21.21' # The full version, including alpha/beta/rc tags. release = version diff --git a/meson.build b/meson.build index 49bb534c9..d6d0412ec 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'mpd', ['c', 'cpp'], - version: '0.21.20', + version: '0.21.21', meson_version: '>= 0.49.0', default_options: [ 'c_std=c99', From 976372ff6334db52e2e2beef24794cd4549de592 Mon Sep 17 00:00:00 2001 From: John Regan Date: Tue, 18 Feb 2020 15:06:52 -0500 Subject: [PATCH 02/16] gme: check for empty metadata strings instead of nullptr Using libgme 0.6.2 on macOS, it appears that gme_info_t strings can be empty, which creates weird track titles: (001/050) This adds an additional check for an empty string. --- NEWS | 2 ++ src/decoder/plugins/GmeDecoderPlugin.cxx | 11 ++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/NEWS b/NEWS index 4e35fd90a..4648d09a0 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.21 (not yet released) +* decoder + - gme: ignore empty tags ver 0.21.20 (2020/02/16) * decoder diff --git a/src/decoder/plugins/GmeDecoderPlugin.cxx b/src/decoder/plugins/GmeDecoderPlugin.cxx index 64f0a1ad4..fcea526af 100644 --- a/src/decoder/plugins/GmeDecoderPlugin.cxx +++ b/src/decoder/plugins/GmeDecoderPlugin.cxx @@ -28,6 +28,7 @@ #include "fs/AllocatedPath.hxx" #include "fs/FileSystem.hxx" #include "util/ScopeExit.hxx" +#include "util/StringCompare.hxx" #include "util/StringFormat.hxx" #include "util/UriUtil.hxx" #include "util/Domain.hxx" @@ -222,7 +223,7 @@ ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count, if (track_count > 1) handler.OnTag(TAG_TRACK, StringFormat<16>("%u", song_num + 1)); - if (info.song != nullptr) { + if (!StringIsEmpty(info.song)) { if (track_count > 1) { /* start numbering subtunes from 1 */ const auto tag_title = @@ -234,16 +235,16 @@ ScanGmeInfo(const gme_info_t &info, unsigned song_num, int track_count, handler.OnTag(TAG_TITLE, info.song); } - if (info.author != nullptr) + if (!StringIsEmpty(info.author)) handler.OnTag(TAG_ARTIST, info.author); - if (info.game != nullptr) + if (!StringIsEmpty(info.game)) handler.OnTag(TAG_ALBUM, info.game); - if (info.comment != nullptr) + if (!StringIsEmpty(info.comment)) handler.OnTag(TAG_COMMENT, info.comment); - if (info.copyright != nullptr) + if (!StringIsEmpty(info.copyright)) handler.OnTag(TAG_DATE, info.copyright); } From d5468dfe89acb85885d2f8017a66bdecdfcbb758 Mon Sep 17 00:00:00 2001 From: Thomas Klausner Date: Sat, 29 Feb 2020 09:55:13 +0100 Subject: [PATCH 03/16] Add missing header. Fixes ../src/time/ISO8601.cxx:67:24: error: use of undeclared identifier 'strtoul' unsigned long value = strtoul(s, &endptr, 10); ^ ../src/time/ISO8601.cxx:77:14: error: use of undeclared identifier 'strtoul' minutes = strtoul(s, &endptr, 10); ^ on NetBSD with clang 9.0.0. --- src/time/ISO8601.cxx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/time/ISO8601.cxx b/src/time/ISO8601.cxx index 725215ea6..336ddcd5b 100644 --- a/src/time/ISO8601.cxx +++ b/src/time/ISO8601.cxx @@ -37,6 +37,7 @@ #include #include +#include StringBuffer<64> FormatISO8601(const struct tm &tm) noexcept From 7a68b1e71fd2f29478b95a5116ab0792f218f9ff Mon Sep 17 00:00:00 2001 From: Thomas Klausner Date: Sat, 29 Feb 2020 09:56:10 +0100 Subject: [PATCH 04/16] Adapt SolarisOutputPlugin.cxx to be usable on NetBSD. --- NEWS | 2 ++ src/output/plugins/SolarisOutputPlugin.cxx | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 4648d09a0..741938b37 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.21.21 (not yet released) * decoder - gme: ignore empty tags +* output + - solaris: port to NetBSD ver 0.21.20 (2020/02/16) * decoder diff --git a/src/output/plugins/SolarisOutputPlugin.cxx b/src/output/plugins/SolarisOutputPlugin.cxx index d6323d5aa..5176f7ac4 100644 --- a/src/output/plugins/SolarisOutputPlugin.cxx +++ b/src/output/plugins/SolarisOutputPlugin.cxx @@ -22,22 +22,23 @@ #include "system/FileDescriptor.hxx" #include "system/Error.hxx" +#include #include #include #include #include #include -#ifdef __sun +#if defined(__sun) #include #include +#elif defined(__NetBSD__) +#include #else /* some fake declarations that allow build this plugin on systems other than Solaris, just to see if it compiles */ -#include - #ifndef I_FLUSH #define I_FLUSH 0 #endif @@ -147,7 +148,11 @@ SolarisOutput::Play(const void *chunk, size_t size) void SolarisOutput::Cancel() noexcept { +#if defined(AUDIO_FLUSH) + ioctl(fd.Get(), AUDIO_FLUSH); +#elif defined(I_FLUSH) ioctl(fd.Get(), I_FLUSH); +#endif } const struct AudioOutputPlugin solaris_output_plugin = { From 5fe70a3417267910317b7ecf5d5439497e8262af Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:30:33 +0100 Subject: [PATCH 05/16] .travis.yml: rename "matrix" to "jobs" Travis has changed the canonical name for this a while ago. From 5faf76051d3a99c637653c76d0fc762e75b87bd5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:29:45 +0100 Subject: [PATCH 06/16] .travis.yml: force updating homebrew on OSX Workaround for Travis failures as described in https://travis-ci.community/t/macos-build-fails-because-of-homebrew-bundle-unknown-command/7296/18 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index c62d7e244..f780cb785 100644 --- a/.travis.yml +++ b/.travis.yml @@ -126,6 +126,7 @@ matrix: packages: - ccache - meson + update: true env: - MATRIX_EVAL="export PATH=/usr/local/opt/ccache/libexec:$PATH HOMEBREW_NO_ANALYTICS=1" From b7ce4523083d5c98b4d944045a318b6a3e590a46 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:02:02 +0100 Subject: [PATCH 07/16] fs/Traits: add IsSpecialFilename() Merge some duplicate code in a central library. --- src/db/update/InotifyUpdate.cxx | 4 ++-- src/db/update/Walk.cxx | 2 +- src/fs/Traits.hxx | 12 ++++++++++++ src/storage/plugins/LocalStorage.cxx | 11 +---------- 4 files changed, 16 insertions(+), 13 deletions(-) diff --git a/src/db/update/InotifyUpdate.cxx b/src/db/update/InotifyUpdate.cxx index 374a1ea04..0885aa435 100644 --- a/src/db/update/InotifyUpdate.cxx +++ b/src/db/update/InotifyUpdate.cxx @@ -24,6 +24,7 @@ #include "storage/StorageInterface.hxx" #include "fs/AllocatedPath.hxx" #include "fs/FileInfo.hxx" +#include "fs/Traits.hxx" #include "Log.hxx" #include @@ -146,8 +147,7 @@ WatchDirectory::GetUriFS() const noexcept /* we don't look at "." / ".." nor files with newlines in their name */ static bool skip_path(const char *path) { - return (path[0] == '.' && path[1] == 0) || - (path[0] == '.' && path[1] == '.' && path[2] == 0) || + return PathTraitsFS::IsSpecialFilename(path) || strchr(path, '\n') != nullptr; } diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index e2c9b7a8c..eb853fcb8 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -237,7 +237,7 @@ try { LogError(std::current_exception()); } -/* we don't look at "." / ".." nor files with newlines in their name */ +/* we don't look at files with newlines in their name */ gcc_pure static bool skip_path(const char *name_utf8) noexcept diff --git a/src/fs/Traits.hxx b/src/fs/Traits.hxx index 6a7e31f0c..735ec6c9e 100644 --- a/src/fs/Traits.hxx +++ b/src/fs/Traits.hxx @@ -108,6 +108,12 @@ struct PathTraitsFS { return IsSeparator(*p); } + gcc_pure gcc_nonnull_all + static bool IsSpecialFilename(const_pointer_type name) noexcept { + return (name[0] == '.' && name[1] == 0) || + (name[0] == '.' && name[1] == '.' && name[2] == 0); + } + gcc_pure gcc_nonnull_all static size_t GetLength(const_pointer_type p) noexcept { return StringLength(p); @@ -216,6 +222,12 @@ struct PathTraitsUTF8 { return IsSeparator(*p); } + gcc_pure gcc_nonnull_all + static bool IsSpecialFilename(const_pointer_type name) noexcept { + return (name[0] == '.' && name[1] == 0) || + (name[0] == '.' && name[1] == '.' && name[2] == 0); + } + gcc_pure gcc_nonnull_all static size_t GetLength(const_pointer_type p) noexcept { return StringLength(p); diff --git a/src/storage/plugins/LocalStorage.cxx b/src/storage/plugins/LocalStorage.cxx index 562e0937a..662f8801e 100644 --- a/src/storage/plugins/LocalStorage.cxx +++ b/src/storage/plugins/LocalStorage.cxx @@ -144,21 +144,12 @@ LocalStorage::OpenDirectory(const char *uri_utf8) return std::make_unique(MapFSOrThrow(uri_utf8)); } -gcc_pure -static bool -SkipNameFS(PathTraitsFS::const_pointer_type name_fs) noexcept -{ - return name_fs[0] == '.' && - (name_fs[1] == 0 || - (name_fs[1] == '.' && name_fs[2] == 0)); -} - const char * LocalDirectoryReader::Read() noexcept { while (reader.ReadEntry()) { const Path name_fs = reader.GetEntry(); - if (SkipNameFS(name_fs.c_str())) + if (PathTraitsFS::IsSpecialFilename(name_fs.c_str())) continue; try { From 73a1f078a6bb0a2228f7d9e7a48a53382707ec35 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:15:54 +0100 Subject: [PATCH 08/16] archive/iso9660: use IsSpecialFilename() --- src/archive/plugins/Iso9660ArchivePlugin.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index a27230728..50cea2aef 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -93,7 +93,8 @@ Iso9660ArchiveFile::Visit(char *path, size_t length, size_t capacity, auto *statbuf = (iso9660_stat_t *) _cdio_list_node_data(entnode); const char *filename = statbuf->filename; - if (strcmp(filename, ".") == 0 || strcmp(filename, "..") == 0) + if (PathTraitsUTF8::IsSpecialFilename(filename)) + /* skip special names like "." and ".." */ continue; size_t filename_length = strlen(filename); From 8d34a1cfc6e5e6e1a5f958160edc78c141854b18 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:16:37 +0100 Subject: [PATCH 09/16] archive/iso9660: skip empty filenames Aparently, libcdio sometimes returns empty filenames, causing MPD crashes. This shouldn't really happen, and I consider this a libcdio bug - but if it happens, people blame MPD, so let's add a check. Closes https://github.com/MusicPlayerDaemon/MPD/issues/776 --- NEWS | 2 ++ src/archive/plugins/Iso9660ArchivePlugin.cxx | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 741938b37..c8742f395 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.21 (not yet released) +* archive + - iso9660: skip empty file names to work around libcdio bug * decoder - gme: ignore empty tags * output diff --git a/src/archive/plugins/Iso9660ArchivePlugin.cxx b/src/archive/plugins/Iso9660ArchivePlugin.cxx index 50cea2aef..6cb307bd4 100644 --- a/src/archive/plugins/Iso9660ArchivePlugin.cxx +++ b/src/archive/plugins/Iso9660ArchivePlugin.cxx @@ -28,6 +28,7 @@ #include "input/InputStream.hxx" #include "fs/Path.hxx" #include "util/RuntimeError.hxx" +#include "util/StringCompare.hxx" #include @@ -93,7 +94,9 @@ Iso9660ArchiveFile::Visit(char *path, size_t length, size_t capacity, auto *statbuf = (iso9660_stat_t *) _cdio_list_node_data(entnode); const char *filename = statbuf->filename; - if (PathTraitsUTF8::IsSpecialFilename(filename)) + if (StringIsEmpty(filename) || + PathTraitsUTF8::IsSpecialFilename(filename)) + /* skip empty names (libcdio bug?) */ /* skip special names like "." and ".." */ continue; From cd364023ae2e8cc824692289bc6c169e6c67594c Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Sat, 7 Mar 2020 09:31:46 +0100 Subject: [PATCH 10/16] .travis.yml: rename "matrix" to "jobs" Travis has changed the canonical name for this a while ago. (Now really. The last commit for this was empty.) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index f780cb785..38b72d547 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,6 @@ language: cpp -matrix: +jobs: include: # Ubuntu Bionic (18.04) with GCC 7 - os: linux From acb29f792f937f41f82be0949457513ec46aed4e Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Mar 2020 20:34:02 +0100 Subject: [PATCH 11/16] tag/Mask: fix yet another typo, this time in Unset() Similar to commits e8f2f980488318fb0e37c1fe6bc1300e97327b6e and ff1ff1e54a25ed80abdca9e7e63b36db150ec766 Closes https://github.com/MusicPlayerDaemon/MPD/issues/783 --- NEWS | 2 ++ src/tag/Mask.hxx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index c8742f395..7f9d25bc3 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.21 (not yet released) +* configuration + - fix bug in "metadata_to_use" setting * archive - iso9660: skip empty file names to work around libcdio bug * decoder diff --git a/src/tag/Mask.hxx b/src/tag/Mask.hxx index 4b6126bc5..e7de5dd54 100644 --- a/src/tag/Mask.hxx +++ b/src/tag/Mask.hxx @@ -89,7 +89,7 @@ public: } void Unset(TagType tag) { - *this |= ~TagMask(tag); + *this &= ~TagMask(tag); } }; From 98a7d8da6cd88ddb335fbc375ef546a09ae8ea16 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Mar 2020 20:51:10 +0100 Subject: [PATCH 12/16] playlist/xspf: use C++11 initializer --- src/playlist/plugins/XspfPlaylistPlugin.cxx | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index b266830f9..4a4b240bf 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -45,7 +45,7 @@ struct XspfParser { enum { ROOT, PLAYLIST, TRACKLIST, TRACK, LOCATION, - } state; + } state = ROOT; /** * The current tag within the "track" element. This is only @@ -60,9 +60,6 @@ struct XspfParser { std::string location; TagBuilder tag_builder; - - XspfParser() - :state(ROOT) {} }; static void XMLCALL From 51b1dd867207fdc69d83556fa32742198847b31a Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Mar 2020 20:51:47 +0100 Subject: [PATCH 13/16] playlist/xspf: use tag_table to convert element name to TagType --- src/playlist/plugins/XspfPlaylistPlugin.cxx | 29 ++++++++++++--------- 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index 4a4b240bf..b084725fe 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -23,6 +23,7 @@ #include "song/DetachedSong.hxx" #include "input/InputStream.hxx" #include "tag/Builder.hxx" +#include "tag/Table.hxx" #include "util/StringView.hxx" #include "lib/expat/ExpatParser.hxx" #include "Log.hxx" @@ -62,6 +63,19 @@ struct XspfParser { TagBuilder tag_builder; }; +static constexpr struct tag_table xspf_tag_elements[] = { + { "title", TAG_TITLE }, + + /* TAG_COMPOSER would be more correct according to the XSPF + spec */ + { "creator", TAG_ARTIST }, + + { "annotation", TAG_COMMENT }, + { "album", TAG_ALBUM }, + { "trackNum", TAG_TRACK }, + { nullptr, TAG_NUM_OF_ITEM_TYPES } +}; + static void XMLCALL xspf_start_element(void *user_data, const XML_Char *element_name, gcc_unused const XML_Char **atts) @@ -93,18 +107,9 @@ xspf_start_element(void *user_data, const XML_Char *element_name, case XspfParser::TRACK: if (strcmp(element_name, "location") == 0) parser->state = XspfParser::LOCATION; - else if (strcmp(element_name, "title") == 0) - parser->tag_type = TAG_TITLE; - else if (strcmp(element_name, "creator") == 0) - /* TAG_COMPOSER would be more correct - according to the XSPF spec */ - parser->tag_type = TAG_ARTIST; - else if (strcmp(element_name, "annotation") == 0) - parser->tag_type = TAG_COMMENT; - else if (strcmp(element_name, "album") == 0) - parser->tag_type = TAG_ALBUM; - else if (strcmp(element_name, "trackNum") == 0) - parser->tag_type = TAG_TRACK; + else + parser->tag_type = tag_table_lookup(xspf_tag_elements, + element_name); break; From 3e9705815108dd25b2f9f77fbd77bbcbb3340d69 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Mar 2020 20:54:53 +0100 Subject: [PATCH 14/16] playlist/xspf: move location.empty() check to _start_element() --- src/playlist/plugins/XspfPlaylistPlugin.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index b084725fe..f32dc35d4 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -107,7 +107,7 @@ xspf_start_element(void *user_data, const XML_Char *element_name, case XspfParser::TRACK: if (strcmp(element_name, "location") == 0) parser->state = XspfParser::LOCATION; - else + else if (!parser->location.empty()) parser->tag_type = tag_table_lookup(xspf_tag_elements, element_name); @@ -169,8 +169,7 @@ xspf_char_data(void *user_data, const XML_Char *s, int len) break; case XspfParser::TRACK: - if (!parser->location.empty() && - parser->tag_type != TAG_NUM_OF_ITEM_TYPES) + if (parser->tag_type != TAG_NUM_OF_ITEM_TYPES) parser->tag_builder.AddItem(parser->tag_type, StringView(s, len)); From e0a8fd398c7ee1479fd5c3eed9828c098f87666b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 12 Mar 2020 08:00:54 +0100 Subject: [PATCH 15/16] playlist/xspf: add State::TAG --- src/playlist/plugins/XspfPlaylistPlugin.cxx | 22 +++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index f32dc35d4..9ed5a8544 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -45,7 +45,7 @@ struct XspfParser { */ enum { ROOT, PLAYLIST, TRACKLIST, TRACK, - LOCATION, + TAG, LOCATION, } state = ROOT; /** @@ -99,7 +99,6 @@ xspf_start_element(void *user_data, const XML_Char *element_name, if (strcmp(element_name, "track") == 0) { parser->state = XspfParser::TRACK; parser->location.clear(); - parser->tag_type = TAG_NUM_OF_ITEM_TYPES; } break; @@ -107,12 +106,16 @@ xspf_start_element(void *user_data, const XML_Char *element_name, case XspfParser::TRACK: if (strcmp(element_name, "location") == 0) parser->state = XspfParser::LOCATION; - else if (!parser->location.empty()) + else if (!parser->location.empty()) { parser->tag_type = tag_table_lookup(xspf_tag_elements, element_name); + if (parser->tag_type != TAG_NUM_OF_ITEM_TYPES) + parser->state = XspfParser::TAG; + } break; + case XspfParser::TAG: case XspfParser::LOCATION: break; } @@ -146,11 +149,11 @@ xspf_end_element(void *user_data, const XML_Char *element_name) parser->tag_builder.Commit()); parser->state = XspfParser::TRACKLIST; - } else - parser->tag_type = TAG_NUM_OF_ITEM_TYPES; + } break; + case XspfParser::TAG: case XspfParser::LOCATION: parser->state = XspfParser::TRACK; break; @@ -166,13 +169,12 @@ xspf_char_data(void *user_data, const XML_Char *s, int len) case XspfParser::ROOT: case XspfParser::PLAYLIST: case XspfParser::TRACKLIST: + case XspfParser::TRACK: break; - case XspfParser::TRACK: - if (parser->tag_type != TAG_NUM_OF_ITEM_TYPES) - parser->tag_builder.AddItem(parser->tag_type, - StringView(s, len)); - + case XspfParser::TAG: + parser->tag_builder.AddItem(parser->tag_type, + StringView(s, len)); break; case XspfParser::LOCATION: From c45f1138560b526649bf6e6433fa7d9ba8a6564b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 11 Mar 2020 20:44:16 +0100 Subject: [PATCH 16/16] playlist/xspf: concatenate multiple CharacterData fragments Closes https://github.com/MusicPlayerDaemon/MPD/issues/781 --- NEWS | 2 ++ src/playlist/plugins/XspfPlaylistPlugin.cxx | 21 +++++++++++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/NEWS b/NEWS index 7f9d25bc3..7cf1248d3 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,8 @@ ver 0.21.21 (not yet released) * configuration - fix bug in "metadata_to_use" setting +* playlist + - xspf: fix corrupt tags in the presence of XML entities * archive - iso9660: skip empty file names to work around libcdio bug * decoder diff --git a/src/playlist/plugins/XspfPlaylistPlugin.cxx b/src/playlist/plugins/XspfPlaylistPlugin.cxx index 9ed5a8544..851c7ba83 100644 --- a/src/playlist/plugins/XspfPlaylistPlugin.cxx +++ b/src/playlist/plugins/XspfPlaylistPlugin.cxx @@ -61,6 +61,8 @@ struct XspfParser { std::string location; TagBuilder tag_builder; + + std::string value; }; static constexpr struct tag_table xspf_tag_elements[] = { @@ -81,6 +83,7 @@ xspf_start_element(void *user_data, const XML_Char *element_name, gcc_unused const XML_Char **atts) { XspfParser *parser = (XspfParser *)user_data; + parser->value.clear(); switch (parser->state) { case XspfParser::ROOT: @@ -154,10 +157,21 @@ xspf_end_element(void *user_data, const XML_Char *element_name) break; case XspfParser::TAG: + if (!parser->value.empty()) + parser->tag_builder.AddItem(parser->tag_type, + StringView(parser->value.data(), + parser->value.length())); + + parser->state = XspfParser::TRACK; + break; + case XspfParser::LOCATION: + parser->location = std::move(parser->value); parser->state = XspfParser::TRACK; break; } + + parser->value.clear(); } static void XMLCALL @@ -173,13 +187,8 @@ xspf_char_data(void *user_data, const XML_Char *s, int len) break; case XspfParser::TAG: - parser->tag_builder.AddItem(parser->tag_type, - StringView(s, len)); - break; - case XspfParser::LOCATION: - parser->location.assign(s, len); - + parser->value.append(s, len); break; } }