mirror of
https://github.com/xenia-project/FFmpeg.git
synced 2024-11-27 21:40:34 +00:00
avformat: add protocol_whitelist
Note to maintainers: update tools Note to maintainers: set a default whitelist for your protocol If that makes no sense then consider to set "none" and thus require the user to specify a white-list for sub-protocols to be opened Note, testing and checking for missing changes is needed Reviewed-by: Andreas Cadhalpun <andreas.cadhalpun@googlemail.com> Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
This commit is contained in:
parent
838abfc1d7
commit
1dba8371d9
@ -15,6 +15,9 @@ libavutil: 2015-08-28
|
||||
|
||||
API changes, most recent first:
|
||||
|
||||
2016-02-01 - xxxxxxx - lavf 57.24.100
|
||||
Add protocol_whitelist to AVFormatContext, AVIOContext
|
||||
|
||||
2016-01-31 - xxxxxxx - lavu 55.17.100
|
||||
Add AV_FRAME_DATA_GOP_TIMECODE for exporting MPEG1/2 GOP timecodes.
|
||||
|
||||
|
@ -1827,6 +1827,13 @@ typedef struct AVFormatContext {
|
||||
* Demuxing: Set by user.
|
||||
*/
|
||||
int (*open_cb)(struct AVFormatContext *s, AVIOContext **p, const char *url, int flags, const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
* - encoding: unused
|
||||
* - decoding: set by user through AVOptions (NO direct access)
|
||||
*/
|
||||
char *protocol_whitelist;
|
||||
} AVFormatContext;
|
||||
|
||||
int av_format_get_probe_score(const AVFormatContext *s);
|
||||
|
@ -73,7 +73,13 @@ static const AVClass *urlcontext_child_class_next(const AVClass *prev)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const AVOption options[] = { { 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 },
|
||||
{ NULL }
|
||||
};
|
||||
const AVClass ffurl_context_class = {
|
||||
.class_name = "URLContext",
|
||||
.item_name = urlcontext_to_name,
|
||||
@ -201,12 +207,43 @@ fail:
|
||||
|
||||
int ffurl_connect(URLContext *uc, AVDictionary **options)
|
||||
{
|
||||
int err =
|
||||
int err;
|
||||
AVDictionary *tmp_opts = NULL;
|
||||
AVDictionaryEntry *e;
|
||||
|
||||
if (!options)
|
||||
options = &tmp_opts;
|
||||
|
||||
// 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)));
|
||||
|
||||
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_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 (!uc->protocol_whitelist) {
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
} else if (!uc->protocol_whitelist)
|
||||
av_log(uc, AV_LOG_DEBUG, "No default whitelist set\n"); // This should be an error once all declare a default whitelist
|
||||
|
||||
if ((err = av_dict_set(options, "protocol_whitelist", uc->protocol_whitelist, 0)) < 0)
|
||||
return err;
|
||||
|
||||
err =
|
||||
uc->prot->url_open2 ? uc->prot->url_open2(uc,
|
||||
uc->filename,
|
||||
uc->flags,
|
||||
options) :
|
||||
uc->prot->url_open(uc, uc->filename, uc->flags);
|
||||
|
||||
av_dict_set(options, "protocol_whitelist", NULL, 0);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
uc->is_connected = 1;
|
||||
@ -296,18 +333,33 @@ int ffurl_alloc(URLContext **puc, const char *filename, int flags,
|
||||
return AVERROR_PROTOCOL_NOT_FOUND;
|
||||
}
|
||||
|
||||
int ffurl_open(URLContext **puc, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options)
|
||||
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options, const char *whitelist)
|
||||
{
|
||||
AVDictionary *tmp_opts = NULL;
|
||||
AVDictionaryEntry *e;
|
||||
int ret = ffurl_alloc(puc, filename, flags, int_cb);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (options && (*puc)->prot->priv_data_class &&
|
||||
(ret = av_opt_set_dict((*puc)->priv_data, options)) < 0)
|
||||
goto fail;
|
||||
|
||||
if (!options)
|
||||
options = &tmp_opts;
|
||||
|
||||
av_assert0(!whitelist ||
|
||||
!(e=av_dict_get(*options, "protocol_whitelist", NULL, 0)) ||
|
||||
!strcmp(whitelist, e->value));
|
||||
|
||||
if ((ret = av_dict_set(options, "protocol_whitelist", whitelist, 0)) < 0)
|
||||
goto fail;
|
||||
|
||||
if ((ret = av_opt_set_dict(*puc, options)) < 0)
|
||||
goto fail;
|
||||
|
||||
ret = ffurl_connect(*puc, options);
|
||||
|
||||
if (!ret)
|
||||
return 0;
|
||||
fail:
|
||||
@ -316,6 +368,13 @@ fail:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ffurl_open(URLContext **puc, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options)
|
||||
{
|
||||
return ffurl_open_whitelist(puc, filename, flags,
|
||||
int_cb, options, NULL);
|
||||
}
|
||||
|
||||
static inline int retry_transfer_wrapper(URLContext *h, uint8_t *buf,
|
||||
int size, int size_min,
|
||||
int (*transfer_func)(URLContext *h,
|
||||
|
@ -249,6 +249,11 @@ typedef struct AVIOContext {
|
||||
* This is current internal only, do not use from outside.
|
||||
*/
|
||||
int short_seek_threshold;
|
||||
|
||||
/**
|
||||
* ',' separated list of allowed protocols.
|
||||
*/
|
||||
const char *protocol_whitelist;
|
||||
} AVIOContext;
|
||||
|
||||
/* unbuffered I/O */
|
||||
|
@ -149,6 +149,10 @@ int ffio_fdopen(AVIOContext **s, URLContext *h);
|
||||
*/
|
||||
int ffio_open_null_buf(AVIOContext **s);
|
||||
|
||||
int ffio_open_whitelist(AVIOContext **s, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options,
|
||||
const char *whitelist);
|
||||
|
||||
/**
|
||||
* Close a null buffer.
|
||||
*
|
||||
|
@ -53,7 +53,11 @@ static const AVClass *ff_avio_child_class_next(const AVClass *prev)
|
||||
return prev ? NULL : &ffurl_context_class;
|
||||
}
|
||||
|
||||
#define OFFSET(x) offsetof(AVIOContext,x)
|
||||
#define E AV_OPT_FLAG_ENCODING_PARAM
|
||||
#define D AV_OPT_FLAG_DECODING_PARAM
|
||||
static const AVOption ff_avio_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 },
|
||||
{ NULL },
|
||||
};
|
||||
|
||||
@ -800,6 +804,11 @@ int ffio_fdopen(AVIOContext **s, URLContext *h)
|
||||
av_free(buffer);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
(*s)->protocol_whitelist = av_strdup(h->protocol_whitelist);
|
||||
if (!(*s)->protocol_whitelist && h->protocol_whitelist) {
|
||||
avio_closep(s);
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
(*s)->direct = h->flags & AVIO_FLAG_DIRECT;
|
||||
(*s)->seekable = h->is_streamed ? 0 : AVIO_SEEKABLE_NORMAL;
|
||||
(*s)->max_packet_size = max_packet_size;
|
||||
@ -919,13 +928,15 @@ int avio_open(AVIOContext **s, const char *filename, int flags)
|
||||
return avio_open2(s, filename, flags, NULL, NULL);
|
||||
}
|
||||
|
||||
int avio_open2(AVIOContext **s, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options)
|
||||
int ffio_open_whitelist(AVIOContext **s, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options,
|
||||
const char *whitelist
|
||||
)
|
||||
{
|
||||
URLContext *h;
|
||||
int err;
|
||||
|
||||
err = ffurl_open(&h, filename, flags, int_cb, options);
|
||||
err = ffurl_open_whitelist(&h, filename, flags, int_cb, options, whitelist);
|
||||
if (err < 0)
|
||||
return err;
|
||||
err = ffio_fdopen(s, h);
|
||||
@ -936,10 +947,16 @@ int avio_open2(AVIOContext **s, const char *filename, int flags,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int avio_open2(AVIOContext **s, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options)
|
||||
{
|
||||
return ffio_open_whitelist(s, filename, flags, int_cb, options, NULL);
|
||||
}
|
||||
|
||||
int ffio_open2_wrapper(struct AVFormatContext *s, AVIOContext **pb, const char *url, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options)
|
||||
{
|
||||
return avio_open2(pb, url, flags, int_cb, options);
|
||||
return ffio_open_whitelist(pb, url, flags, int_cb, options, s->protocol_whitelist);
|
||||
}
|
||||
|
||||
int avio_close(AVIOContext *s)
|
||||
|
@ -100,6 +100,7 @@ static const AVOption avformat_options[] = {
|
||||
{"dump_separator", "set information dump field separator", OFFSET(dump_separator), AV_OPT_TYPE_STRING, {.str = ", "}, CHAR_MIN, CHAR_MAX, D|E},
|
||||
{"codec_whitelist", "List of decoders that are allowed to be used", OFFSET(codec_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
|
||||
{"format_whitelist", "List of demuxers that are allowed to be used", OFFSET(format_whitelist), AV_OPT_TYPE_STRING, { .str = NULL }, CHAR_MIN, CHAR_MAX, D },
|
||||
{"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 },
|
||||
{NULL},
|
||||
};
|
||||
|
||||
|
@ -47,6 +47,7 @@ typedef struct URLContext {
|
||||
int is_connected;
|
||||
AVIOInterruptCB interrupt_callback;
|
||||
int64_t rw_timeout; /**< maximum time to wait for (network) read/write operation completion, in mcs */
|
||||
const char *protocol_whitelist;
|
||||
} URLContext;
|
||||
|
||||
typedef struct URLProtocol {
|
||||
@ -94,6 +95,7 @@ typedef struct URLProtocol {
|
||||
int (*url_close_dir)(URLContext *h);
|
||||
int (*url_delete)(URLContext *h);
|
||||
int (*url_move)(URLContext *h_src, URLContext *h_dst);
|
||||
const char *default_whitelist;
|
||||
} URLProtocol;
|
||||
|
||||
/**
|
||||
@ -138,6 +140,10 @@ int ffurl_connect(URLContext *uc, AVDictionary **options);
|
||||
* @return >= 0 in case of success, a negative value corresponding to an
|
||||
* AVERROR code in case of failure
|
||||
*/
|
||||
int ffurl_open_whitelist(URLContext **puc, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options,
|
||||
const char *whitelist);
|
||||
|
||||
int ffurl_open(URLContext **puc, const char *filename, int flags,
|
||||
const AVIOInterruptCB *int_cb, AVDictionary **options);
|
||||
|
||||
|
@ -139,11 +139,15 @@ void av_format_inject_global_side_data(AVFormatContext *s)
|
||||
|
||||
int ff_copy_whitelists(AVFormatContext *dst, AVFormatContext *src)
|
||||
{
|
||||
av_assert0(!dst->codec_whitelist && !dst->format_whitelist);
|
||||
av_assert0(!dst->codec_whitelist &&
|
||||
!dst->format_whitelist &&
|
||||
!dst->protocol_whitelist);
|
||||
dst-> codec_whitelist = av_strdup(src->codec_whitelist);
|
||||
dst->format_whitelist = av_strdup(src->format_whitelist);
|
||||
dst->protocol_whitelist = av_strdup(src->protocol_whitelist);
|
||||
if ( (src-> codec_whitelist && !dst-> codec_whitelist)
|
||||
|| (src->format_whitelist && !dst->format_whitelist)) {
|
||||
|| (src-> format_whitelist && !dst-> format_whitelist)
|
||||
|| (src->protocol_whitelist && !dst->protocol_whitelist)) {
|
||||
av_log(dst, AV_LOG_ERROR, "Failed to duplicate whitelist\n");
|
||||
return AVERROR(ENOMEM);
|
||||
}
|
||||
@ -352,9 +356,11 @@ static int init_input(AVFormatContext *s, const char *filename,
|
||||
(!s->iformat && (s->iformat = av_probe_input_format2(&pd, 0, &score))))
|
||||
return score;
|
||||
|
||||
if ((ret = avio_open2(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
|
||||
&s->interrupt_callback, options)) < 0)
|
||||
if ((ret = ffio_open_whitelist(&s->pb, filename, AVIO_FLAG_READ | s->avio_flags,
|
||||
&s->interrupt_callback, options,
|
||||
s->protocol_whitelist)) < 0)
|
||||
return ret;
|
||||
|
||||
if (s->iformat)
|
||||
return 0;
|
||||
return av_probe_input_buffer2(s->pb, &s->iformat, filename,
|
||||
@ -441,6 +447,14 @@ int avformat_open_input(AVFormatContext **ps, const char *filename,
|
||||
goto fail;
|
||||
s->probe_score = ret;
|
||||
|
||||
if (!s->protocol_whitelist && s->pb && s->pb->protocol_whitelist) {
|
||||
s->protocol_whitelist = av_strdup(s->pb->protocol_whitelist);
|
||||
if (!s->protocol_whitelist) {
|
||||
ret = AVERROR(ENOMEM);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (s->format_whitelist && av_match_list(s->iformat->name, s->format_whitelist, ',') <= 0) {
|
||||
av_log(s, AV_LOG_ERROR, "Format not on whitelist \'%s\'\n", s->format_whitelist);
|
||||
ret = AVERROR(EINVAL);
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include "libavutil/version.h"
|
||||
|
||||
#define LIBAVFORMAT_VERSION_MAJOR 57
|
||||
#define LIBAVFORMAT_VERSION_MINOR 23
|
||||
#define LIBAVFORMAT_VERSION_MICRO 101
|
||||
#define LIBAVFORMAT_VERSION_MINOR 24
|
||||
#define LIBAVFORMAT_VERSION_MICRO 100
|
||||
|
||||
#define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
|
||||
LIBAVFORMAT_VERSION_MINOR, \
|
||||
|
Loading…
Reference in New Issue
Block a user