diff options
author | Max Kellermann <max@musicpd.org> | 2019-07-01 09:48:33 +0200 |
---|---|---|
committer | Max Kellermann <max@musicpd.org> | 2019-07-01 09:48:33 +0200 |
commit | 44aaf5134556c29fa675169bb3ae3b07efc7a665 (patch) | |
tree | 002e381ce5eebc49ba60629470362c81796bb366 | |
parent | 5b013733568786cf0f508a7935769e9bef7fb2e1 (diff) | |
parent | 4e2a551f30c1e1db13933d15c44d9186a2f37959 (diff) |
Merge branch 'runtime_enumeration' of git://github.com/eugene2k/MPD
-rw-r--r-- | src/input/InputPlugin.cxx | 51 | ||||
-rw-r--r-- | src/input/InputPlugin.hxx | 27 | ||||
-rw-r--r-- | src/input/plugins/AlsaInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/CdioParanoiaInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/CurlInputPlugin.cxx | 21 | ||||
-rw-r--r-- | src/input/plugins/FfmpegInputPlugin.cxx | 36 | ||||
-rw-r--r-- | src/input/plugins/MmsInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/NfsInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/QobuzInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/SmbclientInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/input/plugins/TidalInputPlugin.cxx | 1 | ||||
-rw-r--r-- | src/ls.cxx | 27 |
12 files changed, 137 insertions, 32 deletions
diff --git a/src/input/InputPlugin.cxx b/src/input/InputPlugin.cxx index 9af8a6ca8..3b6b58cbe 100644 --- a/src/input/InputPlugin.cxx +++ b/src/input/InputPlugin.cxx @@ -21,15 +21,54 @@ #include "util/StringCompare.hxx" #include <assert.h> +#include <algorithm> +#include <iterator> bool InputPlugin::SupportsUri(const char *uri) const noexcept { - assert(prefixes != nullptr); - - for (auto i = prefixes; *i != nullptr; ++i) - if (StringStartsWithIgnoreCase(uri, *i)) - return true; - + assert(prefixes || protocols); + if (prefixes != nullptr) { + for (auto i = prefixes; *i != nullptr; ++i) + if (StringStartsWithIgnoreCase(uri, *i)) + return true; + } else { + for (auto schema : protocols()) { + if (StringStartsWithIgnoreCase(uri, schema.c_str())){ + return true; + } + } + } return false; } + +// Note: The whitelist has to be ordered alphabetically +constexpr static const char *whitelist[] = { + "ftp", + "ftps", + "gopher", + "http", + "https", + "mmsh", + "mmst", + "rtmp", + "rtmpe", + "rtmps", + "rtmpt", + "rtmpte", + "rtmpts", + "rtp", + "scp", + "sftp", + "smb", + "srtp", +}; + +bool +protocol_is_whitelisted(const char *proto) { + auto begin = std::begin(whitelist); + auto end = std::end(whitelist); + return std::binary_search(begin, end, proto, [](const char* a, const char* b) { + return strcasecmp(a,b) < 0; + }); +}
\ No newline at end of file diff --git a/src/input/InputPlugin.hxx b/src/input/InputPlugin.hxx index 7834b181a..92aa1ee77 100644 --- a/src/input/InputPlugin.hxx +++ b/src/input/InputPlugin.hxx @@ -23,6 +23,9 @@ #include "Ptr.hxx" #include "thread/Mutex.hxx" #include "util/Compiler.h" +#include <assert.h> +#include <set> +#include <string> struct ConfigBlock; class EventLoop; @@ -63,6 +66,11 @@ struct InputPlugin { InputStreamPtr (*open)(const char *uri, Mutex &mutex); /** + * return a set of supported protocols + */ + std::set<std::string> (*protocols)(); + + /** * Prepare a #RemoteTagScanner. The operation must be started * using RemoteTagScanner::Start(). Returns nullptr if the * plugin does not support this URI. @@ -76,6 +84,25 @@ struct InputPlugin { gcc_pure bool SupportsUri(const char *uri) const noexcept; + + template<typename F> + void ForeachSupportedUri(F lambda) const noexcept { + assert(prefixes || protocols); + + if (prefixes != nullptr) { + for (auto schema = prefixes; *schema != nullptr; ++schema) { + lambda(*schema); + } + } + if (protocols != nullptr) { + for (auto schema : protocols()) { + lambda(schema.c_str()); + } + } + } }; +bool +protocol_is_whitelisted(const char *proto); + #endif diff --git a/src/input/plugins/AlsaInputPlugin.cxx b/src/input/plugins/AlsaInputPlugin.cxx index ae8ff50cc..552fe8fd0 100644 --- a/src/input/plugins/AlsaInputPlugin.cxx +++ b/src/input/plugins/AlsaInputPlugin.cxx @@ -486,4 +486,5 @@ const struct InputPlugin input_plugin_alsa = { alsa_input_init, nullptr, alsa_input_open, + nullptr }; diff --git a/src/input/plugins/CdioParanoiaInputPlugin.cxx b/src/input/plugins/CdioParanoiaInputPlugin.cxx index fb7a276b3..166feb935 100644 --- a/src/input/plugins/CdioParanoiaInputPlugin.cxx +++ b/src/input/plugins/CdioParanoiaInputPlugin.cxx @@ -360,4 +360,5 @@ const InputPlugin input_plugin_cdio_paranoia = { input_cdio_init, nullptr, input_cdio_open, + nullptr }; diff --git a/src/input/plugins/CurlInputPlugin.cxx b/src/input/plugins/CurlInputPlugin.cxx index 395965335..f43da9a84 100644 --- a/src/input/plugins/CurlInputPlugin.cxx +++ b/src/input/plugins/CurlInputPlugin.cxx @@ -470,16 +470,25 @@ input_curl_open(const char *url, Mutex &mutex) return CurlInputStream::Open(url, {}, mutex); } -static constexpr const char *curl_prefixes[] = { - "http://", - "https://", - nullptr -}; +static std::set<std::string> +input_curl_protocols() { + std::set<std::string> protocols; + auto version_info = curl_version_info(CURLVERSION_FIRST); + for (auto proto_ptr = version_info->protocols; *proto_ptr != nullptr; proto_ptr++) { + if (protocol_is_whitelisted(*proto_ptr)) { + std::string schema(*proto_ptr); + schema.append("://"); + protocols.emplace(schema); + } + } + return protocols; +} const struct InputPlugin input_plugin_curl = { "curl", - curl_prefixes, + nullptr, input_curl_init, input_curl_finish, input_curl_open, + input_curl_protocols }; diff --git a/src/input/plugins/FfmpegInputPlugin.cxx b/src/input/plugins/FfmpegInputPlugin.cxx index e08caef73..e3ef77fc3 100644 --- a/src/input/plugins/FfmpegInputPlugin.cxx +++ b/src/input/plugins/FfmpegInputPlugin.cxx @@ -25,8 +25,13 @@ #include "lib/ffmpeg/Init.hxx" #include "lib/ffmpeg/Error.hxx" #include "../InputStream.hxx" -#include "../InputPlugin.hxx" #include "PluginUnavailable.hxx" +#include "util/StringAPI.hxx" +#include "../InputPlugin.hxx" +#include <iostream> +#include <exception> +#include <typeinfo> +#include <stdexcept> class FfmpegInputStream final : public InputStream { Ffmpeg::IOContext io; @@ -73,6 +78,22 @@ input_ffmpeg_init(EventLoop &, const ConfigBlock &) throw PluginUnavailable("No protocol"); } +static std::set<std::string> +input_ffmpeg_protocols() { + void *opaque = nullptr; + const char* protocol; + std::set<std::string> protocols; + while ((protocol = avio_enum_protocols(&opaque, 0))) { + if (protocol_is_whitelisted(protocol)) { + std::string schema(protocol); + schema.append("://"); + protocols.emplace(schema); + } + } + + return protocols; +} + static InputStreamPtr input_ffmpeg_open(const char *uri, Mutex &mutex) @@ -114,20 +135,11 @@ FfmpegInputStream::Seek(std::unique_lock<Mutex> &, offset_type new_offset) offset = result; } -static constexpr const char *ffmpeg_prefixes[] = { - "gopher://", - "rtp://", - "rtsp://", - "rtmp://", - "rtmpt://", - "rtmps://", - nullptr -}; - const InputPlugin input_plugin_ffmpeg = { "ffmpeg", - ffmpeg_prefixes, + nullptr, input_ffmpeg_init, nullptr, input_ffmpeg_open, + input_ffmpeg_protocols }; diff --git a/src/input/plugins/MmsInputPlugin.cxx b/src/input/plugins/MmsInputPlugin.cxx index 775b83155..11e2c98c4 100644 --- a/src/input/plugins/MmsInputPlugin.cxx +++ b/src/input/plugins/MmsInputPlugin.cxx @@ -110,4 +110,5 @@ const InputPlugin input_plugin_mms = { nullptr, nullptr, input_mms_open, + nullptr }; diff --git a/src/input/plugins/NfsInputPlugin.cxx b/src/input/plugins/NfsInputPlugin.cxx index 520653924..9ab91397f 100644 --- a/src/input/plugins/NfsInputPlugin.cxx +++ b/src/input/plugins/NfsInputPlugin.cxx @@ -232,4 +232,5 @@ const InputPlugin input_plugin_nfs = { input_nfs_init, input_nfs_finish, input_nfs_open, + nullptr }; diff --git a/src/input/plugins/QobuzInputPlugin.cxx b/src/input/plugins/QobuzInputPlugin.cxx index 0f90903a3..8053f5638 100644 --- a/src/input/plugins/QobuzInputPlugin.cxx +++ b/src/input/plugins/QobuzInputPlugin.cxx @@ -219,5 +219,6 @@ const InputPlugin qobuz_input_plugin = { InitQobuzInput, FinishQobuzInput, OpenQobuzInput, + nullptr, ScanQobuzTags, }; diff --git a/src/input/plugins/SmbclientInputPlugin.cxx b/src/input/plugins/SmbclientInputPlugin.cxx index a72552d8d..7a20820ad 100644 --- a/src/input/plugins/SmbclientInputPlugin.cxx +++ b/src/input/plugins/SmbclientInputPlugin.cxx @@ -166,4 +166,5 @@ const InputPlugin input_plugin_smbclient = { input_smbclient_init, nullptr, input_smbclient_open, + nullptr }; diff --git a/src/input/plugins/TidalInputPlugin.cxx b/src/input/plugins/TidalInputPlugin.cxx index 7a47d6902..c2c89af4f 100644 --- a/src/input/plugins/TidalInputPlugin.cxx +++ b/src/input/plugins/TidalInputPlugin.cxx @@ -251,5 +251,6 @@ const InputPlugin tidal_input_plugin = { InitTidalInput, FinishTidalInput, OpenTidalInput, + nullptr, ScanTidalTags, }; diff --git a/src/ls.cxx b/src/ls.cxx index 46ae325d7..c73fd77ac 100644 --- a/src/ls.cxx +++ b/src/ls.cxx @@ -22,28 +22,41 @@ #include "input/Registry.hxx" #include "input/InputPlugin.hxx" #include "client/Response.hxx" -#include "util/ASCII.hxx" #include "util/UriUtil.hxx" #include <assert.h> +#include <string> + void print_supported_uri_schemes_to_fp(FILE *fp) { #ifdef HAVE_UN fprintf(fp, " file://"); #endif + std::set<std::string> protocols; input_plugins_for_each(plugin) - for (auto i = plugin->prefixes; *i != nullptr; ++i) - fprintf(fp, " %s", *i); + plugin->ForeachSupportedUri([&](const char* uri) { + protocols.emplace(uri); + }); + + for (auto protocol : protocols) { + fprintf(fp, " %s", protocol.c_str()); + } fprintf(fp,"\n"); } void print_supported_uri_schemes(Response &r) { + std::set<std::string> protocols; input_plugins_for_each_enabled(plugin) - for (auto i = plugin->prefixes; *i != nullptr; ++i) - r.Format("handler: %s\n", *i); + plugin->ForeachSupportedUri([&](const char* uri) { + protocols.emplace(uri); + }); + + for (auto protocol : protocols) { + r.Format("handler: %s\n", protocol.c_str()); + } } bool @@ -52,9 +65,7 @@ uri_supported_scheme(const char *uri) noexcept assert(uri_has_scheme(uri)); input_plugins_for_each_enabled(plugin) - for (auto i = plugin->prefixes; *i != nullptr; ++i) - if (StringStartsWithCaseASCII(uri, *i)) - return true; + return plugin->SupportsUri(uri); return false; } |