From b9b906ab208cf0243b3be3f61af279cd4c9d0483 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 7 Oct 2019 12:24:01 +0200 Subject: [PATCH 01/14] increment version number to 0.21.16 --- 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 96fd78924..faf11c231 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,5 @@ +ver 0.21.16 (not yet released) + ver 0.21.15 (2019/09/25) * decoder - dsdiff, dsf: fix displayed bit rate diff --git a/android/AndroidManifest.xml b/android/AndroidManifest.xml index 282707c61..e6bf686a9 100644 --- a/android/AndroidManifest.xml +++ b/android/AndroidManifest.xml @@ -2,8 +2,8 @@ + android:versionCode="39" + android:versionName="0.21.16"> diff --git a/doc/conf.py b/doc/conf.py index 196a52719..660300aa7 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.15' +version = '0.21.16' # The full version, including alpha/beta/rc tags. release = version diff --git a/meson.build b/meson.build index 602bf23f6..df45a688b 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'mpd', ['c', 'cpp'], - version: '0.21.15', + version: '0.21.16', meson_version: '>= 0.49.0', default_options: [ 'c_std=c99', From 23d08820a2bec1182c838de34cc2c6687dc95558 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 7 Oct 2019 12:23:58 +0200 Subject: [PATCH 02/14] db/update/Walk: fix crash when music_directory is not a directory Add a runtime sanity check to avoid the assertion failure. Closes https://github.com/MusicPlayerDaemon/MPD/issues/660 --- NEWS | 2 ++ src/db/update/Walk.cxx | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/NEWS b/NEWS index faf11c231..334cce603 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.16 (not yet released) +* update + - fix crash when music_directory is not a directory ver 0.21.15 (2019/09/25) * decoder diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index c13d6fd40..e2c9b7a8c 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -493,6 +493,12 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) noexcept if (!GetInfo(storage, "", info)) return false; + if (!info.IsDirectory()) { + FormatError(update_domain, "Not a directory: %s", + storage.MapUTF8("").c_str()); + return false; + } + ExcludeList exclude_list; UpdateDirectory(root, exclude_list, info); From dcc5ce67925ac9fb456f5d5e707a09f5ab931285 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Mon, 7 Oct 2019 12:44:48 +0200 Subject: [PATCH 03/14] storage/curl: request the "resourcetype" property to fix update Without requesting the property, "good" WebDAV servers would not send it, and so MPD could never recognize a directory, failing the database update. Closes https://github.com/MusicPlayerDaemon/MPD/issues/660 --- NEWS | 2 ++ src/storage/plugins/CurlStorage.cxx | 1 + 2 files changed, 3 insertions(+) diff --git a/NEWS b/NEWS index 334cce603..7aaaf90de 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.16 (not yet released) +* storage + - curl: request the "resourcetype" property to fix database update * update - fix crash when music_directory is not a directory diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index b8ec0c78b..0c9293b10 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -277,6 +277,7 @@ public: request.SetOption(CURLOPT_POSTFIELDS, "\n" "" + "" "" "" ""); From 96a9670c69bb21a9f12643b118d06e27c73f8fbd Mon Sep 17 00:00:00 2001 From: Andre Heider Date: Sun, 29 Sep 2019 20:57:04 +0200 Subject: [PATCH 04/14] lib/icu: fix build with iconv() --- NEWS | 1 + src/lib/icu/meson.build | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 7aaaf90de..276fe027d 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,7 @@ ver 0.21.16 (not yet released) - curl: request the "resourcetype" property to fix database update * update - fix crash when music_directory is not a directory +* fix build with iconv() instead of ICU ver 0.21.15 (2019/09/25) * decoder diff --git a/src/lib/icu/meson.build b/src/lib/icu/meson.build index 3232266ec..5386a62b4 100644 --- a/src/lib/icu/meson.build +++ b/src/lib/icu/meson.build @@ -20,7 +20,7 @@ if icu_dep.found() elif not get_option('iconv').disabled() have_iconv = compiler.has_function('iconv') conf.set('HAVE_ICONV', have_iconv) - if get_option('iconv').enabled() + if not have_iconv and get_option('iconv').enabled() error('iconv() not available') endif endif From 0eb113e7c6c5177178377051f61c3419a68f43e5 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 13:13:39 +0200 Subject: [PATCH 05/14] lib/curl/String: OO wrapper for allocated strings returned from CURL --- src/lib/curl/Easy.hxx | 6 ++- src/lib/curl/Form.cxx | 9 ++-- src/lib/curl/String.hxx | 77 +++++++++++++++++++++++++++++ src/storage/plugins/CurlStorage.cxx | 6 +-- 4 files changed, 88 insertions(+), 10 deletions(-) create mode 100644 src/lib/curl/String.hxx diff --git a/src/lib/curl/Easy.hxx b/src/lib/curl/Easy.hxx index a2f134a77..4d813511e 100644 --- a/src/lib/curl/Easy.hxx +++ b/src/lib/curl/Easy.hxx @@ -30,6 +30,8 @@ #ifndef CURL_EASY_HXX #define CURL_EASY_HXX +#include "String.hxx" + #include #include @@ -88,8 +90,8 @@ public: throw std::runtime_error(curl_easy_strerror(code)); } - char *Escape(const char *string, int length=0) const noexcept { - return curl_easy_escape(handle, string, length); + CurlString Escape(const char *string, int length=0) const noexcept { + return CurlString(curl_easy_escape(handle, string, length)); } }; diff --git a/src/lib/curl/Form.cxx b/src/lib/curl/Form.cxx index 7e9d84753..65430641d 100644 --- a/src/lib/curl/Form.cxx +++ b/src/lib/curl/Form.cxx @@ -28,6 +28,7 @@ */ #include "Form.hxx" +#include "String.hxx" std::string EncodeForm(CURL *curl, @@ -43,12 +44,10 @@ EncodeForm(CURL *curl, result.push_back('='); if (!i.second.empty()) { - char *value = curl_easy_escape(curl, i.second.data(), - i.second.length()); - if (value != nullptr) { + CurlString value(curl_easy_escape(curl, i.second.data(), + i.second.length())); + if (value) result.append(value); - curl_free(value); - } } } diff --git a/src/lib/curl/String.hxx b/src/lib/curl/String.hxx new file mode 100644 index 000000000..f39c28992 --- /dev/null +++ b/src/lib/curl/String.hxx @@ -0,0 +1,77 @@ +/* + * Copyright 2019 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_STRING_HXX +#define CURL_STRING_HXX + +#include + +#include + +/** + * An OO wrapper for an allocated string to be freed with curl_free(). + */ +class CurlString { + char *p = nullptr; + +public: + CurlString() noexcept = default; + CurlString(std::nullptr_t) noexcept {} + + explicit CurlString(char *_p) noexcept + :p(_p) {} + + CurlString(CurlString &&src) noexcept + :p(std::exchange(src.p, nullptr)) {} + + ~CurlString() noexcept { + if (p != nullptr) + curl_free(p); + } + + CurlString &operator=(CurlString &&src) noexcept { + using std::swap; + swap(p, src.p); + return *this; + } + + operator bool() const noexcept { + return p != nullptr; + } + + operator const char *() const noexcept { + return p; + } + + const char *c_str() const noexcept { + return p; + } +}; + +#endif diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 0c9293b10..0e6f45a81 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -25,6 +25,7 @@ #include "lib/curl/Init.hxx" #include "lib/curl/Global.hxx" #include "lib/curl/Slist.hxx" +#include "lib/curl/String.hxx" #include "lib/curl/Request.hxx" #include "lib/curl/Handler.hxx" #include "lib/expat/ExpatParser.hxx" @@ -81,11 +82,10 @@ CurlStorage::MapUTF8(const char *uri_utf8) const noexcept std::string path_esc; for (auto elt: IterableSplitString(uri_utf8, '/')) { - char *elt_esc = easy.Escape(elt.data, elt.size); + const auto elt_esc = easy.Escape(elt.data, elt.size); if (!path_esc.empty()) path_esc.push_back('/'); - path_esc += elt_esc; - curl_free(elt_esc); + path_esc += elt_esc.c_str(); } return PathTraitsUTF8::Build(base.c_str(), path_esc.c_str()); From a8f4d2b6fc3f7a616ee8f4e0a920a9cc6475f3bd Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 13:24:06 +0200 Subject: [PATCH 06/14] storage/curl: move code to EscapeUriPath() --- src/lib/curl/Escape.cxx | 55 +++++++++++++++++++++++++++++ src/lib/curl/Escape.hxx | 45 +++++++++++++++++++++++ src/lib/curl/meson.build | 1 + src/storage/plugins/CurlStorage.cxx | 13 ++----- 4 files changed, 103 insertions(+), 11 deletions(-) create mode 100644 src/lib/curl/Escape.cxx create mode 100644 src/lib/curl/Escape.hxx diff --git a/src/lib/curl/Escape.cxx b/src/lib/curl/Escape.cxx new file mode 100644 index 000000000..765de3b94 --- /dev/null +++ b/src/lib/curl/Escape.cxx @@ -0,0 +1,55 @@ +/* + * Copyright (C) 2018 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "Escape.hxx" +#include "Easy.hxx" +#include "String.hxx" +#include "util/IterableSplitString.hxx" + +std::string +CurlEscapeUriPath(CURL *curl, StringView src) noexcept +{ + std::string dest; + + for (const auto i : IterableSplitString(src, '/')) { + CurlString escaped(curl_easy_escape(curl, i.data, i.size)); + if (!dest.empty()) + dest.push_back('/'); + dest += escaped.c_str(); + } + + return dest; +} + +std::string +CurlEscapeUriPath(StringView src) noexcept +{ + CurlEasy easy; + return CurlEscapeUriPath(easy.Get(), src); +} diff --git a/src/lib/curl/Escape.hxx b/src/lib/curl/Escape.hxx new file mode 100644 index 000000000..e09ed8fed --- /dev/null +++ b/src/lib/curl/Escape.hxx @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2018 Max Kellermann + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef CURL_ESCAPE_HXX +#define CURL_ESCAPE_HXX + +#include + +#include + +struct StringView; + +std::string +CurlEscapeUriPath(CURL *curl, StringView src) noexcept; + +std::string +CurlEscapeUriPath(StringView src) noexcept; + +#endif diff --git a/src/lib/curl/meson.build b/src/lib/curl/meson.build index f66663a01..4d9f534e9 100644 --- a/src/lib/curl/meson.build +++ b/src/lib/curl/meson.build @@ -11,6 +11,7 @@ curl = static_library( 'Init.cxx', 'Global.cxx', 'Request.cxx', + 'Escape.cxx', 'Form.cxx', include_directories: inc, dependencies: [ diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 0e6f45a81..803e471d3 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -28,6 +28,7 @@ #include "lib/curl/String.hxx" #include "lib/curl/Request.hxx" #include "lib/curl/Handler.hxx" +#include "lib/curl/Escape.hxx" #include "lib/expat/ExpatParser.hxx" #include "fs/Traits.hxx" #include "event/Call.hxx" @@ -36,7 +37,6 @@ #include "thread/Cond.hxx" #include "util/ASCII.hxx" #include "util/ChronoUtil.hxx" -#include "util/IterableSplitString.hxx" #include "util/RuntimeError.hxx" #include "util/StringCompare.hxx" #include "util/StringFormat.hxx" @@ -78,16 +78,7 @@ CurlStorage::MapUTF8(const char *uri_utf8) const noexcept if (StringIsEmpty(uri_utf8)) return base; - CurlEasy easy; - std::string path_esc; - - for (auto elt: IterableSplitString(uri_utf8, '/')) { - const auto elt_esc = easy.Escape(elt.data, elt.size); - if (!path_esc.empty()) - path_esc.push_back('/'); - path_esc += elt_esc.c_str(); - } - + std::string path_esc = CurlEscapeUriPath(uri_utf8); return PathTraitsUTF8::Build(base.c_str(), path_esc.c_str()); } From 364acc8949115597752889e8c556cf2162533361 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 13:39:02 +0200 Subject: [PATCH 07/14] lib/curl/Escape: add CurlUnescape() --- src/lib/curl/Escape.cxx | 16 ++++++++++++++++ src/lib/curl/Escape.hxx | 6 ++++++ 2 files changed, 22 insertions(+) diff --git a/src/lib/curl/Escape.cxx b/src/lib/curl/Escape.cxx index 765de3b94..ab832eac9 100644 --- a/src/lib/curl/Escape.cxx +++ b/src/lib/curl/Escape.cxx @@ -53,3 +53,19 @@ CurlEscapeUriPath(StringView src) noexcept CurlEasy easy; return CurlEscapeUriPath(easy.Get(), src); } + +std::string +CurlUnescape(CURL *curl, StringView src) noexcept +{ + int outlength; + CurlString tmp(curl_easy_unescape(curl, src.data, src.size, + &outlength)); + return std::string(tmp.c_str(), outlength); +} + +std::string +CurlUnescape(StringView src) noexcept +{ + CurlEasy easy; + return CurlUnescape(easy.Get(), src); +} diff --git a/src/lib/curl/Escape.hxx b/src/lib/curl/Escape.hxx index e09ed8fed..1a7c9ab70 100644 --- a/src/lib/curl/Escape.hxx +++ b/src/lib/curl/Escape.hxx @@ -42,4 +42,10 @@ CurlEscapeUriPath(CURL *curl, StringView src) noexcept; std::string CurlEscapeUriPath(StringView src) noexcept; +std::string +CurlUnescape(CURL *curl, StringView src) noexcept; + +std::string +CurlUnescape(StringView src) noexcept; + #endif From ead208987ddf27f97bac7ccf7887e318a2550be7 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 13:30:29 +0200 Subject: [PATCH 08/14] storage/curl: unescape URI in MapToRelativeUTF8() --- src/storage/plugins/CurlStorage.cxx | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 803e471d3..8f2dea64f 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -85,9 +85,8 @@ CurlStorage::MapUTF8(const char *uri_utf8) const noexcept const char * CurlStorage::MapToRelativeUTF8(const char *uri_utf8) const noexcept { - // TODO: escape/unescape? - - return PathTraitsUTF8::Relative(base.c_str(), uri_utf8); + return PathTraitsUTF8::Relative(base.c_str(), + CurlUnescape(uri_utf8).c_str()); } class BlockingHttpRequest : protected CurlResponseHandler { From 56cc42b7522c46d616c88db0a6261578b121dc9d Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 16:12:01 +0200 Subject: [PATCH 09/14] storage/curl: use MapUTF8() to reuse existing escaping code Commit 29f78b18b1d continued. Closes https://github.com/MusicPlayerDaemon/MPD/issues/662 --- NEWS | 1 + src/storage/plugins/CurlStorage.cxx | 9 ++------- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 276fe027d..c0d175464 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ ver 0.21.16 (not yet released) * storage - curl: request the "resourcetype" property to fix database update + - curl: URL-encode more paths * update - fix crash when music_directory is not a directory * fix build with iconv() instead of ICU diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 8f2dea64f..3790cc5a8 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -445,9 +445,7 @@ CurlStorage::GetInfo(const char *uri_utf8, gcc_unused bool follow) { // TODO: escape the given URI - std::string uri = base; - uri += uri_utf8; - + const auto uri = MapUTF8(uri_utf8); return HttpGetInfoOperation(*curl, uri.c_str()).Perform(); } @@ -537,10 +535,7 @@ protected: std::unique_ptr CurlStorage::OpenDirectory(const char *uri_utf8) { - // TODO: escape the given URI - - std::string uri = base; - uri += uri_utf8; + std::string uri = MapUTF8(uri_utf8); /* collection URIs must end with a slash */ if (uri.back() != '/') From e98d4670b84a604c7ab967e7fcd0a1e35bbc8229 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 16:22:02 +0200 Subject: [PATCH 10/14] storage/curl: work around different case in hex digits --- src/storage/plugins/CurlStorage.cxx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 3790cc5a8..13150d920 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -492,7 +492,11 @@ private: if (path == nullptr) return nullptr; - path = StringAfterPrefix(path, base_path.c_str()); + /* kludge: ignoring case in this comparison to avoid + false negatives if the web server uses a different + case in hex digits in escaped characters; TODO: + implement properly */ + path = StringAfterPrefixIgnoreCase(path, base_path.c_str()); if (path == nullptr || *path == 0) return nullptr; From f0386459ee5759fe1ff54eacc34525b03901ba6b Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 16:42:39 +0200 Subject: [PATCH 11/14] storage/curl: follow redirects for collections without trailing slash --- NEWS | 1 + src/storage/plugins/CurlStorage.cxx | 2 ++ 2 files changed, 3 insertions(+) diff --git a/NEWS b/NEWS index c0d175464..48a489178 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,7 @@ ver 0.21.16 (not yet released) * storage - curl: request the "resourcetype" property to fix database update - curl: URL-encode more paths + - curl: follow redirects for collections without trailing slash * update - fix crash when music_directory is not a directory * fix build with iconv() instead of ICU diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 13150d920..581a0cca4 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -259,6 +259,8 @@ public: CommonExpatParser(ExpatNamespaceSeparator{'|'}) { request.SetOption(CURLOPT_CUSTOMREQUEST, "PROPFIND"); + request.SetOption(CURLOPT_FOLLOWLOCATION, 1l); + request.SetOption(CURLOPT_MAXREDIRS, 1l); request_headers.Append(StringFormat<40>("depth: %u", depth)); From 0b9435858b7bfc68b9a73d6b26eb6c8c5c0d7f13 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 16:49:17 +0200 Subject: [PATCH 12/14] storage/curl: unescape file names from PROPFIND This is the last missing piece for https://github.com/MusicPlayerDaemon/MPD/issues/662 --- src/storage/plugins/CurlStorage.cxx | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index 581a0cca4..ee1c00845 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -122,6 +122,10 @@ public: std::rethrow_exception(postponed_error); } + CURL *GetEasy() noexcept { + return request.Get(); + } + protected: void SetDone() { assert(!done); @@ -277,6 +281,7 @@ public: // TODO: send request body } + using BlockingHttpRequest::GetEasy; using BlockingHttpRequest::Wait; protected: @@ -524,10 +529,7 @@ protected: if (escaped_name.IsNull()) return; - // TODO: unescape - const auto name = escaped_name; - - entries.emplace_front(std::string(name.data, name.size)); + entries.emplace_front(CurlUnescape(GetEasy(), escaped_name)); auto &info = entries.front().info; info = StorageFileInfo(r.collection From 12a86c49759f36c20dbd61317fd4bc2508eb30eb Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Tue, 15 Oct 2019 17:00:16 +0200 Subject: [PATCH 13/14] queue/PlaylistEdit: fix relative destination offset when moving a range Commit 13208bf5a7c91a6406195139f1068f173ccdac94 added range support to the `move` command, but applied the wrong offset to the `to` variable. When the source range is before the current song, and the song thus gets decremented by the range size, then the final destination offset must also be decremented by the range size. Closes https://github.com/MusicPlayerDaemon/MPD/issues/663 --- NEWS | 2 ++ src/queue/PlaylistEdit.cxx | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 48a489178..92d8df17f 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.21.16 (not yet released) +* queue + - fix relative destination offset when moving a range * storage - curl: request the "resourcetype" property to fix database update - curl: URL-encode more paths diff --git a/src/queue/PlaylistEdit.cxx b/src/queue/PlaylistEdit.cxx index a0e504f44..9a2b37eed 100644 --- a/src/queue/PlaylistEdit.cxx +++ b/src/queue/PlaylistEdit.cxx @@ -353,7 +353,7 @@ playlist::MoveRange(PlayerControl &pc, unsigned start, unsigned end, int to) return; to = (currentSong + abs(to)) % GetLength(); if (start < (unsigned)to) - to--; + to -= end - start; } queue.MoveRange(start, end, to); From 9b95e65bd9ba9d49e1d29f42c64abede7a9b2a92 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Wed, 16 Oct 2019 11:58:36 +0200 Subject: [PATCH 14/14] release v0.21.16 --- NEWS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 92d8df17f..3e1e32a25 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,4 @@ -ver 0.21.16 (not yet released) +ver 0.21.16 (2019/10/16) * queue - fix relative destination offset when moving a range * storage