diff --git a/libavformat/avio.c b/libavformat/avio.c index 4a29827935..69b6eaac83 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -239,6 +239,7 @@ int ffurl_handshake(URLContext *c) static const struct URLProtocol *url_find_protocol(const char *filename) { const URLProtocol *up; + const URLProtocol **protocols; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); int i; @@ -257,14 +258,16 @@ static const struct URLProtocol *url_find_protocol(const char *filename) if ((ptr = strchr(proto_nested, '+'))) *ptr = '\0'; - for (i = 0; ff_url_protocols[i]; i++) { - up = ff_url_protocols[i]; + protocols = ffurl_get_protocols(NULL, NULL); + for (i = 0; protocols[i]; i++) { + up = protocols[i]; if (!strcmp(proto_str, up->name)) break; if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && !strcmp(proto_nested, up->name)) break; } + av_freep(&protocols); return up; } diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 266e2c0d6d..f37497056d 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -18,6 +18,9 @@ #include "config.h" +#include "libavutil/avstring.h" +#include "libavutil/mem.h" + #include "url.h" extern const URLProtocol ff_async_protocol; @@ -66,7 +69,7 @@ extern const URLProtocol ff_librtmpte_protocol; extern const URLProtocol ff_libssh_protocol; extern const URLProtocol ff_libsmbclient_protocol; -const URLProtocol *ff_url_protocols[] = { +static const URLProtocol *url_protocols[] = { #if CONFIG_ASYNC_PROTOCOL &ff_async_protocol, #endif @@ -212,17 +215,17 @@ const AVClass *ff_urlcontext_child_class_next(const AVClass *prev) int i; /* find the protocol that corresponds to prev */ - for (i = 0; ff_url_protocols[i]; i++) { - if (ff_url_protocols[i]->priv_data_class == prev) { + for (i = 0; url_protocols[i]; i++) { + if (url_protocols[i]->priv_data_class == prev) { i++; break; } } /* find next protocol with priv options */ - for (; ff_url_protocols[i]; i++) - if (ff_url_protocols[i]->priv_data_class) - return ff_url_protocols[i]->priv_data_class; + for (; url_protocols[i]; i++) + if (url_protocols[i]->priv_data_class) + return url_protocols[i]->priv_data_class; return NULL; } @@ -231,7 +234,7 @@ const char *avio_enum_protocols(void **opaque, int output) { const URLProtocol **p = *opaque; - p = p ? p + 1 : ff_url_protocols; + p = p ? p + 1 : url_protocols; *opaque = p; if (!*p) { *opaque = NULL; @@ -241,3 +244,27 @@ const char *avio_enum_protocols(void **opaque, int output) return (*p)->name; return avio_enum_protocols(opaque, output); } + +const URLProtocol **ffurl_get_protocols(const char *whitelist, + const char *blacklist) +{ + const URLProtocol **ret; + int i, ret_idx = 0; + + ret = av_mallocz_array(FF_ARRAY_ELEMS(url_protocols), sizeof(*ret)); + if (!ret) + return NULL; + + for (i = 0; url_protocols[i]; i++) { + const URLProtocol *up = url_protocols[i]; + + if (whitelist && *whitelist && !av_match_name(up->name, whitelist)) + continue; + if (blacklist && *blacklist && av_match_name(up->name, blacklist)) + continue; + + ret[ret_idx++] = up; + } + + return ret; +} diff --git a/libavformat/url.h b/libavformat/url.h index 810fd147b1..95acd27b46 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -311,6 +311,20 @@ AVIODirEntry *ff_alloc_dir_entry(void); const AVClass *ff_urlcontext_child_class_next(const AVClass *prev); -extern const URLProtocol *ff_url_protocols[]; +/** + * Construct a list of protocols matching a given whitelist and/or blacklist. + * + * @param whitelist a comma-separated list of allowed protocol names or NULL. If + * this is a non-empty string, only protocols in this list will + * be included. + * @param blacklist a comma-separated list of forbidden protocol names or NULL. + * If this is a non-empty string, all protocols in this list + * will be excluded. + * + * @return a NULL-terminated array of matching protocols. The array must be + * freed by the caller. + */ +const URLProtocol **ffurl_get_protocols(const char *whitelist, + const char *blacklist); #endif /* AVFORMAT_URL_H */