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/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)
 | 
			
		||||
{
 | 
			
		||||
    char buf[200], buf2[200];
 | 
			
		||||
@ -51,6 +76,15 @@ static void test2(const char *url)
 | 
			
		||||
 | 
			
		||||
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");
 | 
			
		||||
    test(NULL, "baz");
 | 
			
		||||
    test("/foo/bar", "baz");
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@
 | 
			
		||||
#if CONFIG_NETWORK
 | 
			
		||||
#include "network.h"
 | 
			
		||||
#endif
 | 
			
		||||
#include "libavutil/avassert.h"
 | 
			
		||||
#include "libavutil/avstring.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@ -78,6 +79,76 @@ int ff_url_join(char *str, int size, const char *proto,
 | 
			
		||||
    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)
 | 
			
		||||
{
 | 
			
		||||
    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 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 */
 | 
			
		||||
 | 
			
		||||
@ -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:
 | 
			
		||||
                                            (null) baz                  => baz
 | 
			
		||||
                                          /foo/bar baz                  => /foo/baz
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user