mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2025-03-23 04:24:35 +02:00
lavf/url: add ff_url_decompose().
This commit is contained in:
parent
64ff61b3c5
commit
d853293679
@ -21,6 +21,31 @@
|
|||||||
#include "libavformat/url.h"
|
#include "libavformat/url.h"
|
||||||
#include "libavformat/avformat.h"
|
#include "libavformat/avformat.h"
|
||||||
|
|
||||||
|
static void test_decompose(const char *url)
|
||||||
|
{
|
||||||
|
URLComponents uc;
|
||||||
|
int len, ret;
|
||||||
|
|
||||||
|
printf("%s =>\n", url);
|
||||||
|
ret = ff_url_decompose(&uc, url, NULL);
|
||||||
|
if (ret < 0) {
|
||||||
|
printf(" error: %s\n", av_err2str(ret));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#define PRINT_COMPONENT(comp) \
|
||||||
|
len = uc.url_component_end_##comp - uc.comp; \
|
||||||
|
if (len) printf(" "#comp": %.*s\n", len, uc.comp);
|
||||||
|
PRINT_COMPONENT(scheme);
|
||||||
|
PRINT_COMPONENT(authority);
|
||||||
|
PRINT_COMPONENT(userinfo);
|
||||||
|
PRINT_COMPONENT(host);
|
||||||
|
PRINT_COMPONENT(port);
|
||||||
|
PRINT_COMPONENT(path);
|
||||||
|
PRINT_COMPONENT(query);
|
||||||
|
PRINT_COMPONENT(fragment);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
static void test(const char *base, const char *rel)
|
static void test(const char *base, const char *rel)
|
||||||
{
|
{
|
||||||
char buf[200], buf2[200];
|
char buf[200], buf2[200];
|
||||||
@ -51,6 +76,15 @@ static void test2(const char *url)
|
|||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
|
printf("Testing ff_url_decompose:\n\n");
|
||||||
|
test_decompose("http://user:pass@ffmpeg:8080/dir/file?query#fragment");
|
||||||
|
test_decompose("http://ffmpeg/dir/file");
|
||||||
|
test_decompose("file:///dev/null");
|
||||||
|
test_decompose("file:/dev/null");
|
||||||
|
test_decompose("http://[::1]/dev/null");
|
||||||
|
test_decompose("http://[::1]:8080/dev/null");
|
||||||
|
test_decompose("//ffmpeg/dev/null");
|
||||||
|
|
||||||
printf("Testing ff_make_absolute_url:\n");
|
printf("Testing ff_make_absolute_url:\n");
|
||||||
test(NULL, "baz");
|
test(NULL, "baz");
|
||||||
test("/foo/bar", "baz");
|
test("/foo/bar", "baz");
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#if CONFIG_NETWORK
|
#if CONFIG_NETWORK
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include "libavutil/avassert.h"
|
||||||
#include "libavutil/avstring.h"
|
#include "libavutil/avstring.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -78,6 +79,76 @@ int ff_url_join(char *str, int size, const char *proto,
|
|||||||
return strlen(str);
|
return strlen(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *find_delim(const char *delim, const char *cur, const char *end)
|
||||||
|
{
|
||||||
|
while (cur < end && !strchr(delim, *cur))
|
||||||
|
cur++;
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ff_url_decompose(URLComponents *uc, const char *url, const char *end)
|
||||||
|
{
|
||||||
|
const char *cur, *aend, *p;
|
||||||
|
|
||||||
|
av_assert0(url);
|
||||||
|
if (!end)
|
||||||
|
end = url + strlen(url);
|
||||||
|
cur = uc->url = url;
|
||||||
|
|
||||||
|
/* scheme */
|
||||||
|
uc->scheme = cur;
|
||||||
|
p = find_delim(":/", cur, end); /* lavf "schemes" can contain options */
|
||||||
|
if (*p == ':')
|
||||||
|
cur = p + 1;
|
||||||
|
|
||||||
|
/* authority */
|
||||||
|
uc->authority = cur;
|
||||||
|
if (end - cur >= 2 && cur[0] == '/' && cur[1] == '/') {
|
||||||
|
cur += 2;
|
||||||
|
aend = find_delim("/?#", cur, end);
|
||||||
|
|
||||||
|
/* userinfo */
|
||||||
|
uc->userinfo = cur;
|
||||||
|
p = find_delim("@", cur, aend);
|
||||||
|
if (*p == '@')
|
||||||
|
cur = p + 1;
|
||||||
|
|
||||||
|
/* host */
|
||||||
|
uc->host = cur;
|
||||||
|
if (*cur == '[') { /* hello IPv6, thanks for using colons! */
|
||||||
|
p = find_delim("]", cur, aend);
|
||||||
|
if (*p != ']')
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
if (p + 1 < aend && p[1] != ':')
|
||||||
|
return AVERROR(EINVAL);
|
||||||
|
cur = p + 1;
|
||||||
|
} else {
|
||||||
|
cur = find_delim(":", cur, aend);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* port */
|
||||||
|
uc->port = cur;
|
||||||
|
cur = aend;
|
||||||
|
} else {
|
||||||
|
uc->userinfo = uc->host = uc->port = cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* path */
|
||||||
|
uc->path = cur;
|
||||||
|
cur = find_delim("?#", cur, end);
|
||||||
|
|
||||||
|
/* query */
|
||||||
|
uc->query = cur;
|
||||||
|
if (*cur == '?')
|
||||||
|
cur = find_delim("#", cur, end);
|
||||||
|
|
||||||
|
/* fragment */
|
||||||
|
uc->fragment = cur;
|
||||||
|
|
||||||
|
uc->end = end;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void trim_double_dot_url(char *buf, const char *rel, int size)
|
static void trim_double_dot_url(char *buf, const char *rel, int size)
|
||||||
{
|
{
|
||||||
const char *p = rel;
|
const char *p = rel;
|
||||||
|
@ -344,4 +344,45 @@ const AVClass *ff_urlcontext_child_class_iterate(void **iter);
|
|||||||
const URLProtocol **ffurl_get_protocols(const char *whitelist,
|
const URLProtocol **ffurl_get_protocols(const char *whitelist,
|
||||||
const char *blacklist);
|
const char *blacklist);
|
||||||
|
|
||||||
|
typedef struct URLComponents {
|
||||||
|
const char *url; /**< whole URL, for reference */
|
||||||
|
const char *scheme; /**< possibly including lavf-specific options */
|
||||||
|
const char *authority; /**< "//" if it is a real URL */
|
||||||
|
const char *userinfo; /**< including final '@' if present */
|
||||||
|
const char *host;
|
||||||
|
const char *port; /**< including initial ':' if present */
|
||||||
|
const char *path;
|
||||||
|
const char *query; /**< including initial '?' if present */
|
||||||
|
const char *fragment; /**< including initial '#' if present */
|
||||||
|
const char *end;
|
||||||
|
} URLComponents;
|
||||||
|
|
||||||
|
#define url_component_end_scheme authority
|
||||||
|
#define url_component_end_authority userinfo
|
||||||
|
#define url_component_end_userinfo host
|
||||||
|
#define url_component_end_host port
|
||||||
|
#define url_component_end_port path
|
||||||
|
#define url_component_end_path query
|
||||||
|
#define url_component_end_query fragment
|
||||||
|
#define url_component_end_fragment end
|
||||||
|
#define url_component_end_authority_full path
|
||||||
|
|
||||||
|
#define URL_COMPONENT_HAVE(uc, component) \
|
||||||
|
((uc).url_component_end_##component > (uc).component)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an URL to find the components.
|
||||||
|
*
|
||||||
|
* Each component runs until the start of the next component,
|
||||||
|
* possibly including a mandatory delimiter.
|
||||||
|
*
|
||||||
|
* @param uc structure to fill with pointers to the components.
|
||||||
|
* @param url URL to parse.
|
||||||
|
* @param end end of the URL, or NULL to parse to the end of string.
|
||||||
|
*
|
||||||
|
* @return >= 0 for success or an AVERROR code, especially if the URL is
|
||||||
|
* malformed.
|
||||||
|
*/
|
||||||
|
int ff_url_decompose(URLComponents *uc, const char *url, const char *end);
|
||||||
|
|
||||||
#endif /* AVFORMAT_URL_H */
|
#endif /* AVFORMAT_URL_H */
|
||||||
|
@ -1,3 +1,48 @@
|
|||||||
|
Testing ff_url_decompose:
|
||||||
|
|
||||||
|
http://user:pass@ffmpeg:8080/dir/file?query#fragment =>
|
||||||
|
scheme: http:
|
||||||
|
authority: //
|
||||||
|
userinfo: user:pass@
|
||||||
|
host: ffmpeg
|
||||||
|
port: :8080
|
||||||
|
path: /dir/file
|
||||||
|
query: ?query
|
||||||
|
fragment: #fragment
|
||||||
|
|
||||||
|
http://ffmpeg/dir/file =>
|
||||||
|
scheme: http:
|
||||||
|
authority: //
|
||||||
|
host: ffmpeg
|
||||||
|
path: /dir/file
|
||||||
|
|
||||||
|
file:///dev/null =>
|
||||||
|
scheme: file:
|
||||||
|
authority: //
|
||||||
|
path: /dev/null
|
||||||
|
|
||||||
|
file:/dev/null =>
|
||||||
|
scheme: file:
|
||||||
|
path: /dev/null
|
||||||
|
|
||||||
|
http://[::1]/dev/null =>
|
||||||
|
scheme: http:
|
||||||
|
authority: //
|
||||||
|
host: [::1]
|
||||||
|
path: /dev/null
|
||||||
|
|
||||||
|
http://[::1]:8080/dev/null =>
|
||||||
|
scheme: http:
|
||||||
|
authority: //
|
||||||
|
host: [::1]
|
||||||
|
port: :8080
|
||||||
|
path: /dev/null
|
||||||
|
|
||||||
|
//ffmpeg/dev/null =>
|
||||||
|
authority: //
|
||||||
|
host: ffmpeg
|
||||||
|
path: /dev/null
|
||||||
|
|
||||||
Testing ff_make_absolute_url:
|
Testing ff_make_absolute_url:
|
||||||
(null) baz => baz
|
(null) baz => baz
|
||||||
/foo/bar baz => /foo/baz
|
/foo/bar baz => /foo/baz
|
||||||
|
Loading…
x
Reference in New Issue
Block a user