From 906972973e5ff849cfea2e786b6d304057dfc529 Mon Sep 17 00:00:00 2001 From: Max Kellermann Date: Thu, 2 Aug 2018 10:38:20 +0200 Subject: [PATCH] case-insensitive URI scheme comparison Required according to RFC 3986: > An implementation should accept uppercase letters as equivalent to > lowercase in scheme names Closes #330 --- NEWS | 1 + src/LocateUri.cxx | 4 ++-- src/input/InputStream.cxx | 6 +++--- src/input/plugins/AlsaInputPlugin.cxx | 4 ++-- src/input/plugins/CdioParanoiaInputPlugin.cxx | 4 ++-- src/input/plugins/CurlInputPlugin.cxx | 4 ++-- src/input/plugins/FfmpegInputPlugin.cxx | 14 +++++++------- src/input/plugins/MmsInputPlugin.cxx | 10 +++++----- src/input/plugins/NfsInputPlugin.cxx | 6 ++---- src/input/plugins/SmbclientInputPlugin.cxx | 4 ++-- src/lib/nfs/FileReader.cxx | 4 ++-- src/ls.cxx | 4 ++-- src/playlist/plugins/SoundCloudPlaylistPlugin.cxx | 5 +++-- src/storage/plugins/CurlStorage.cxx | 5 +++-- src/storage/plugins/NfsStorage.cxx | 6 +++--- src/storage/plugins/SmbclientStorage.cxx | 3 ++- src/util/UriUtil.cxx | 4 ++-- 17 files changed, 45 insertions(+), 43 deletions(-) diff --git a/NEWS b/NEWS index 2c68bfa10..4f1acfbc4 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,7 @@ ver 0.20.21 (not yet released) - simple: allow .mpdignore comments only at start of line * output - httpd: remove broken DLNA support code +* URI schemes are case insensitive ver 0.20.20 (2018/05/22) * protocol diff --git a/src/LocateUri.cxx b/src/LocateUri.cxx index 3c0a88584..0c16921a0 100644 --- a/src/LocateUri.cxx +++ b/src/LocateUri.cxx @@ -23,7 +23,7 @@ #include "fs/AllocatedPath.hxx" #include "ls.hxx" #include "util/UriUtil.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #ifdef ENABLE_DATABASE #include "storage/StorageInterface.hxx" @@ -83,7 +83,7 @@ LocateUri(const char *uri, const Client *client ) { /* skip the obsolete "file://" prefix */ - const char *path_utf8 = StringAfterPrefix(uri, "file://"); + const char *path_utf8 = StringAfterPrefixCaseASCII(uri, "file://"); if (path_utf8 != nullptr) { if (!PathTraitsUTF8::IsAbsolute(path_utf8)) throw std::runtime_error("Malformed file:// URI"); diff --git a/src/input/InputStream.cxx b/src/input/InputStream.cxx index d17a95f1e..5e43c9a40 100644 --- a/src/input/InputStream.cxx +++ b/src/input/InputStream.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "InputStream.hxx" #include "thread/Cond.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include @@ -77,8 +77,8 @@ gcc_pure static bool ExpensiveSeeking(const char *uri) noexcept { - return StringStartsWith(uri, "http://") || - StringStartsWith(uri, "https://"); + return StringStartsWithCaseASCII(uri, "http://") || + StringStartsWithCaseASCII(uri, "https://"); } bool diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index d38fcc5f8..c1620ff27 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -33,7 +33,7 @@ #include "util/RuntimeError.hxx" #include "util/StringCompare.hxx" #include "util/ReusableArray.hxx" - +#include "util/ASCII.hxx" #include "Log.hxx" #include "event/MultiSocketMonitor.hxx" #include "event/DeferredMonitor.hxx" @@ -147,7 +147,7 @@ private: inline InputStream * AlsaInputStream::Create(const char *uri, Mutex &mutex, Cond &cond) { - const char *device = StringAfterPrefix(uri, "alsa://"); + const char *device = StringAfterPrefixCaseASCII(uri, "alsa://"); if (device == nullptr) return nullptr; diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index e5a63a8d6..595b0d875 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -26,7 +26,7 @@ #include "../InputStream.hxx" #include "../InputPlugin.hxx" #include "util/StringUtil.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include "util/RuntimeError.hxx" #include "util/Domain.hxx" #include "system/ByteOrder.hxx" @@ -128,7 +128,7 @@ struct cdio_uri { static bool parse_cdio_uri(struct cdio_uri *dest, const char *src) { - if (!StringStartsWith(src, "cdda://")) + if (!StringStartsWithCaseASCII(src, "cdda://")) return false; src += 7; diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index d9887727f..d865c9b7a 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -458,8 +458,8 @@ CurlInputStream::Open(const char *url, Mutex &mutex, Cond &cond) static InputStream * input_curl_open(const char *url, Mutex &mutex, Cond &cond) { - if (strncmp(url, "http://", 7) != 0 && - strncmp(url, "https://", 8) != 0) + if (!StringStartsWithCaseASCII(url, "http://") && + !StringStartsWithCaseASCII(url, "https://")) return nullptr; return CurlInputStream::Open(url, mutex, cond); diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index 9ca16aa67..5a55d6e1d 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -28,7 +28,7 @@ #include "../InputStream.hxx" #include "../InputPlugin.hxx" #include "PluginUnavailable.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" extern "C" { #include @@ -85,12 +85,12 @@ static InputStream * input_ffmpeg_open(const char *uri, Mutex &mutex, Cond &cond) { - if (!StringStartsWith(uri, "gopher://") && - !StringStartsWith(uri, "rtp://") && - !StringStartsWith(uri, "rtsp://") && - !StringStartsWith(uri, "rtmp://") && - !StringStartsWith(uri, "rtmpt://") && - !StringStartsWith(uri, "rtmps://")) + if (!StringStartsWithCaseASCII(uri, "gopher://") && + !StringStartsWithCaseASCII(uri, "rtp://") && + !StringStartsWithCaseASCII(uri, "rtsp://") && + !StringStartsWithCaseASCII(uri, "rtmp://") && + !StringStartsWithCaseASCII(uri, "rtmpt://") && + !StringStartsWithCaseASCII(uri, "rtmps://")) return nullptr; AVIOContext *h; diff --git a/src/input/plugins/MmsInputPlugin.cxx b/src/input/plugins/MmsInputPlugin.cxx index 5f420af05..64e25860d 100644 --- a/src/input/plugins/MmsInputPlugin.cxx +++ b/src/input/plugins/MmsInputPlugin.cxx @@ -22,7 +22,7 @@ #include "input/ThreadInputStream.hxx" #include "input/InputPlugin.hxx" #include "system/Error.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include @@ -74,10 +74,10 @@ static InputStream * input_mms_open(const char *url, Mutex &mutex, Cond &cond) { - if (!StringStartsWith(url, "mms://") && - !StringStartsWith(url, "mmsh://") && - !StringStartsWith(url, "mmst://") && - !StringStartsWith(url, "mmsu://")) + if (!StringStartsWithCaseASCII(url, "mms://") && + !StringStartsWithCaseASCII(url, "mmsh://") && + !StringStartsWithCaseASCII(url, "mmst://") && + !StringStartsWithCaseASCII(url, "mmsu://")) return nullptr; auto m = new MmsInputStream(url, mutex, cond); diff --git a/src/input/plugins/NfsInputPlugin.cxx b/src/input/plugins/NfsInputPlugin.cxx index 470cf0282..aeee03a29 100644 --- a/src/input/plugins/NfsInputPlugin.cxx +++ b/src/input/plugins/NfsInputPlugin.cxx @@ -23,9 +23,7 @@ #include "../InputPlugin.hxx" #include "lib/nfs/Glue.hxx" #include "lib/nfs/FileReader.hxx" -#include "util/StringCompare.hxx" - -#include +#include "util/ASCII.hxx" /** * Do not buffer more than this number of bytes. It should be a @@ -219,7 +217,7 @@ static InputStream * input_nfs_open(const char *uri, Mutex &mutex, Cond &cond) { - if (!StringStartsWith(uri, "nfs://")) + if (!StringStartsWithCaseASCII(uri, "nfs://")) return nullptr; NfsInputStream *is = new NfsInputStream(uri, mutex, cond); diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx index 80d406692..57c828943 100644 --- a/src/input/plugins/SmbclientInputPlugin.cxx +++ b/src/input/plugins/SmbclientInputPlugin.cxx @@ -25,7 +25,7 @@ #include "../InputPlugin.hxx" #include "PluginUnavailable.hxx" #include "system/Error.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include @@ -87,7 +87,7 @@ static InputStream * input_smbclient_open(const char *uri, Mutex &mutex, Cond &cond) { - if (!StringStartsWith(uri, "smb://")) + if (!StringStartsWithCaseASCII(uri, "smb://")) return nullptr; const std::lock_guard protect(smbclient_mutex); diff --git a/src/lib/nfs/FileReader.cxx b/src/lib/nfs/FileReader.cxx index 4bf7a43da..1d030a28f 100644 --- a/src/lib/nfs/FileReader.cxx +++ b/src/lib/nfs/FileReader.cxx @@ -24,7 +24,7 @@ #include "Connection.hxx" #include "event/Call.hxx" #include "IOThread.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include @@ -93,7 +93,7 @@ NfsFileReader::Open(const char *uri) { assert(state == State::INITIAL); - if (!StringStartsWith(uri, "nfs://")) + if (!StringStartsWithCaseASCII(uri, "nfs://")) throw std::runtime_error("Malformed nfs:// URI"); uri += 6; diff --git a/src/ls.cxx b/src/ls.cxx index 72754dd7f..2f3cda603 100644 --- a/src/ls.cxx +++ b/src/ls.cxx @@ -20,7 +20,7 @@ #include "config.h" #include "ls.hxx" #include "client/Response.hxx" -#include "util/StringCompare.hxx" +#include "util/ASCII.hxx" #include "util/UriUtil.hxx" #include @@ -97,7 +97,7 @@ uri_supported_scheme(const char *uri) noexcept assert(uri_has_scheme(uri)); while (*urlPrefixes) { - if (StringStartsWith(uri, *urlPrefixes)) + if (StringStartsWithCaseASCII(uri, *urlPrefixes)) return true; urlPrefixes++; } diff --git a/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx index 88a9606c5..4b97376a8 100644 --- a/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx +++ b/src/playlist/plugins/SoundCloudPlaylistPlugin.cxx @@ -24,6 +24,7 @@ #include "config/Block.hxx" #include "input/InputStream.hxx" #include "tag/TagBuilder.hxx" +#include "util/ASCII.hxx" #include "util/StringCompare.hxx" #include "util/Alloc.hxx" #include "util/Domain.hxx" @@ -68,7 +69,7 @@ soundcloud_resolve(const char* uri) { char *u, *ru; - if (StringStartsWith(uri, "https://")) { + if (StringStartsWithCaseASCII(uri, "https://")) { u = xstrdup(uri); } else if (StringStartsWith(uri, "soundcloud.com")) { u = xstrcatdup("https://", uri); @@ -273,7 +274,7 @@ try { static SongEnumerator * soundcloud_open_uri(const char *uri, Mutex &mutex, Cond &cond) { - assert(strncmp(uri, "soundcloud://", 13) == 0); + assert(StringEqualsCaseASCII(uri, "soundcloud://", 13)); uri += 13; char *u = nullptr; diff --git a/src/storage/plugins/CurlStorage.cxx b/src/storage/plugins/CurlStorage.cxx index c077b8bb2..8e99f5c56 100644 --- a/src/storage/plugins/CurlStorage.cxx +++ b/src/storage/plugins/CurlStorage.cxx @@ -33,6 +33,7 @@ #include "event/DeferredMonitor.hxx" #include "thread/Mutex.hxx" #include "thread/Cond.hxx" +#include "util/ASCII.hxx" #include "util/RuntimeError.hxx" #include "util/StringCompare.hxx" #include "util/StringFormat.hxx" @@ -590,8 +591,8 @@ CurlStorage::OpenDirectory(const char *uri_utf8) static Storage * CreateCurlStorageURI(EventLoop &event_loop, const char *uri) { - if (strncmp(uri, "http://", 7) != 0 && - strncmp(uri, "https://", 8) != 0) + if (!StringStartsWithCaseASCII(uri, "http://") && + !StringStartsWithCaseASCII(uri, "https://")) return nullptr; return new CurlStorage(event_loop, uri); diff --git a/src/storage/plugins/NfsStorage.cxx b/src/storage/plugins/NfsStorage.cxx index 6ef6266aa..b2eec24ff 100644 --- a/src/storage/plugins/NfsStorage.cxx +++ b/src/storage/plugins/NfsStorage.cxx @@ -35,6 +35,7 @@ #include "event/Call.hxx" #include "event/DeferredMonitor.hxx" #include "event/TimeoutMonitor.hxx" +#include "util/ASCII.hxx" #include "util/StringCompare.hxx" extern "C" { @@ -401,11 +402,10 @@ NfsStorage::OpenDirectory(const char *uri_utf8) static Storage * CreateNfsStorageURI(EventLoop &event_loop, const char *base) { - if (strncmp(base, "nfs://", 6) != 0) + const char *p = StringAfterPrefixCaseASCII(base, "nfs://"); + if (p == nullptr) return nullptr; - const char *p = base + 6; - const char *mount = strchr(p, '/'); if (mount == nullptr) throw std::runtime_error("Malformed nfs:// URI"); diff --git a/src/storage/plugins/SmbclientStorage.cxx b/src/storage/plugins/SmbclientStorage.cxx index 67d8c3bca..8c279f300 100644 --- a/src/storage/plugins/SmbclientStorage.cxx +++ b/src/storage/plugins/SmbclientStorage.cxx @@ -27,6 +27,7 @@ #include "fs/Traits.hxx" #include "thread/Mutex.hxx" #include "system/Error.hxx" +#include "util/ASCII.hxx" #include "util/StringCompare.hxx" #include "util/ScopeExit.hxx" @@ -182,7 +183,7 @@ SmbclientDirectoryReader::GetInfo(gcc_unused bool follow) static Storage * CreateSmbclientStorageURI(gcc_unused EventLoop &event_loop, const char *base) { - if (strncmp(base, "smb://", 6) != 0) + if (!StringStartsWithCaseASCII(base, "smb://")) return nullptr; SmbclientInit(); diff --git a/src/util/UriUtil.cxx b/src/util/UriUtil.cxx index 61b90da29..bf663cfcd 100644 --- a/src/util/UriUtil.cxx +++ b/src/util/UriUtil.cxx @@ -18,7 +18,7 @@ */ #include "UriUtil.hxx" -#include "StringCompare.hxx" +#include "ASCII.hxx" #include "CharUtil.hxx" #include @@ -169,7 +169,7 @@ SkipUriScheme(const char *uri) noexcept { const char *const schemes[] = { "http://", "https://", "ftp://" }; for (auto scheme : schemes) { - auto result = StringAfterPrefix(uri, scheme); + auto result = StringAfterPrefixCaseASCII(uri, scheme); if (result != nullptr) return result; }