From 832a202c47a246ed15e3edc6b05dfcfa7d82c4b2 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Fri, 19 Feb 2016 11:17:22 +0100 Subject: protocols: make the list of protocols static Disallow other code to touch it directly, now it's only accessible through a blacklisting/whitelisting function. --- libavformat/avio.c | 14 ++++++++++---- libavformat/protocols.c | 41 ++++++++++++++++++++++++++++++++++------- libavformat/url.h | 16 +++++++++++++++- 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/libavformat/avio.c b/libavformat/avio.c index b4e57e943a..a9a399af93 100644 --- a/libavformat/avio.c +++ b/libavformat/avio.c @@ -138,6 +138,7 @@ int ffurl_connect(URLContext *uc, AVDictionary **options) int ffurl_alloc(URLContext **puc, const char *filename, int flags, const AVIOInterruptCB *int_cb) { + const URLProtocol **protocols; char proto_str[128], proto_nested[128], *ptr; size_t proto_len = strspn(filename, URL_SCHEME_CHARS); int i; @@ -152,13 +153,18 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags, if ((ptr = strchr(proto_nested, '+'))) *ptr = '\0'; - for (i = 0; ff_url_protocols[i]; i++) { - const URLProtocol *up = ff_url_protocols[i]; - if (!strcmp(proto_str, up->name)) + protocols = ffurl_get_protocols(NULL, NULL); + for (i = 0; protocols[i]; i++) { + const URLProtocol *up = protocols[i]; + if (!strcmp(proto_str, up->name)) { + av_freep(&protocols); return url_alloc_for_protocol(puc, up, filename, flags, int_cb); + } if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME && - !strcmp(proto_nested, up->name)) + !strcmp(proto_nested, up->name)) { + av_freep(&protocols); return url_alloc_for_protocol(puc, up, filename, flags, int_cb); + } } *puc = NULL; return AVERROR_PROTOCOL_NOT_FOUND; diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 45b2a90251..b03adffa77 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_concat_protocol; @@ -55,7 +58,7 @@ extern const URLProtocol ff_librtmps_protocol; extern const URLProtocol ff_librtmpt_protocol; extern const URLProtocol ff_librtmpte_protocol; -const URLProtocol *ff_url_protocols[] = { +static const URLProtocol *url_protocols[] = { #if CONFIG_CONCAT_PROTOCOL &ff_concat_protocol, #endif @@ -168,17 +171,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; } @@ -187,7 +190,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; @@ -197,3 +200,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 3006905446..455021964e 100644 --- a/libavformat/url.h +++ b/libavformat/url.h @@ -266,6 +266,20 @@ void ff_make_absolute_url(char *buf, int size, const char *base, 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 */ -- cgit v1.2.3