#endif
#include "url.h"
-static URLProtocol *first_protocol = NULL;
-
-URLProtocol *ffurl_protocol_next(const URLProtocol *prev)
-{
- return prev ? prev->next : first_protocol;
-}
-
/** @name Logging context. */
/*@{*/
static const char *urlcontext_to_name(void *ptr)
return NULL;
}
-static const AVClass *urlcontext_child_class_next(const AVClass *prev)
-{
- URLProtocol *p = NULL;
-
- /* find the protocol that corresponds to prev */
- while (prev && (p = ffurl_protocol_next(p)))
- if (p->priv_data_class == prev)
- break;
-
- /* find next protocol with priv options */
- while (p = ffurl_protocol_next(p))
- if (p->priv_data_class)
- return p->priv_data_class;
- return NULL;
-}
-
#define OFFSET(x) offsetof(URLContext,x)
#define E AV_OPT_FLAG_ENCODING_PARAM
#define D AV_OPT_FLAG_DECODING_PARAM
static const AVOption options[] = {
{"protocol_whitelist", "List of protocols that are allowed to be used", OFFSET(protocol_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
+ {"protocol_blacklist", "List of protocols that are not allowed to be used", OFFSET(protocol_blacklist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
{ NULL }
};
+
const AVClass ffurl_context_class = {
.class_name = "URLContext",
.item_name = urlcontext_to_name,
.option = options,
.version = LIBAVUTIL_VERSION_INT,
.child_next = urlcontext_child_next,
- .child_class_next = urlcontext_child_class_next,
+ .child_class_next = ff_urlcontext_child_class_next,
};
/*@}*/
-const char *avio_enum_protocols(void **opaque, int output)
-{
- URLProtocol *p;
- *opaque = ffurl_protocol_next(*opaque);
- if (!(p = *opaque))
- return NULL;
- if ((output && p->url_write) || (!output && p->url_read))
- return p->name;
- return avio_enum_protocols(opaque, output);
-}
-
-int ffurl_register_protocol(URLProtocol *protocol)
-{
- URLProtocol **p;
- p = &first_protocol;
- while (*p)
- p = &(*p)->next;
- *p = protocol;
- protocol->next = NULL;
- return 0;
-}
-
-static int url_alloc_for_protocol(URLContext **puc, struct URLProtocol *up,
+static int url_alloc_for_protocol(URLContext **puc, const URLProtocol *up,
const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
// Check that URLContext was initialized correctly and lists are matching if set
av_assert0(!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
(uc->protocol_whitelist && !strcmp(uc->protocol_whitelist, e->value)));
+ av_assert0(!(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+ (uc->protocol_blacklist && !strcmp(uc->protocol_blacklist, e->value)));
if (uc->protocol_whitelist && av_match_list(uc->prot->name, uc->protocol_whitelist, ',') <= 0) {
av_log(uc, AV_LOG_ERROR, "Protocol not on whitelist \'%s\'!\n", uc->protocol_whitelist);
return AVERROR(EINVAL);
}
+ if (uc->protocol_blacklist && av_match_list(uc->prot->name, uc->protocol_blacklist, ',') > 0) {
+ av_log(uc, AV_LOG_ERROR, "Protocol blacklisted \'%s\'!\n", uc->protocol_blacklist);
+ return AVERROR(EINVAL);
+ }
+
if (!uc->protocol_whitelist && uc->prot->default_whitelist) {
av_log(uc, AV_LOG_DEBUG, "Setting default whitelist '%s'\n", uc->prot->default_whitelist);
uc->protocol_whitelist = av_strdup(uc->prot->default_whitelist);
if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
return err;
+ if ((err = av_dict_set(options, "protocol_blacklist", uc->protocol_blacklist, 0)) < 0)
+ return err;
err =
uc->prot->url_open2 ? uc->prot->url_open2(uc,
uc->prot->url_open(uc, uc->filename, uc->flags);
av_dict_set(options, "protocol_whitelist", NULL, 0);
+ av_dict_set(options, "protocol_blacklist", NULL, 0);
if (err)
return err;
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
"0123456789+-."
-static struct URLProtocol *url_find_protocol(const char *filename)
+static const struct URLProtocol *url_find_protocol(const char *filename)
{
- URLProtocol *up = NULL;
+ const URLProtocol **protocols;
char proto_str[128], proto_nested[128], *ptr;
size_t proto_len = strspn(filename, URL_SCHEME_CHARS);
+ int i;
if (filename[proto_len] != ':' &&
(strncmp(filename, "subfile,", 8) || !strchr(filename + proto_len + 1, ':')) ||
if ((ptr = strchr(proto_nested, '+')))
*ptr = '\0';
- while (up = ffurl_protocol_next(up)) {
- if (!strcmp(proto_str, up->name))
- break;
+ 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 up;
+ }
if (up->flags & URL_PROTOCOL_FLAG_NESTED_SCHEME &&
- !strcmp(proto_nested, up->name))
- break;
+ !strcmp(proto_nested, up->name)) {
+ av_freep(&protocols);
+ return up;
+ }
}
- return up;
+ return NULL;
}
int ffurl_alloc(URLContext **puc, const char *filename, int flags,
const AVIOInterruptCB *int_cb)
{
- URLProtocol *p = NULL;
-
- if (!first_protocol) {
- av_log(NULL, AV_LOG_WARNING, "No URL Protocols are registered. "
- "Missing call to av_register_all()?\n");
- }
+ const URLProtocol *p = NULL;
p = url_find_protocol(filename);
if (p)
*puc = NULL;
if (av_strstart(filename, "https:", NULL))
av_log(NULL, AV_LOG_WARNING, "https protocol not found, recompile FFmpeg with "
- "openssl, gnutls,\n"
+ "openssl, gnutls "
"or securetransport enabled.\n");
return AVERROR_PROTOCOL_NOT_FOUND;
}
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
- const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
+ const AVIOInterruptCB *int_cb, AVDictionary **options,
+ const char *whitelist, const char* blacklist)
{
AVDictionary *tmp_opts = NULL;
AVDictionaryEntry *e;
av_assert0(!whitelist ||
!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
!strcmp(whitelist, e->value));
+ av_assert0(!blacklist ||
+ !(e=av_dict_get(*options, "protocol_blacklist", NULL, 0)) ||
+ !strcmp(blacklist, e->value));
if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
goto fail;
+ if ((ret = av_dict_set(options, "protocol_blacklist", blacklist, 0)) < 0)
+ goto fail;
+
if ((ret = av_opt_set_dict(*puc, options)) < 0)
goto fail;
const AVIOInterruptCB *int_cb, AVDictionary **options)
{
return ffurl_open_whitelist(puc, filename, flags,
- int_cb, options, NULL);
+ int_cb, options, NULL, NULL);
}
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
const char *avio_find_protocol_name(const char *url)
{
- URLProtocol *p = url_find_protocol(url);
+ const URLProtocol *p = url_find_protocol(url);
return p ? p->name : NULL;
}