From 780d7897a9c9295b43f1f0e9b49a11f99cd402c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Storsj=C3=B6?= Date: Fri, 5 Mar 2010 22:31:45 +0000 Subject: [PATCH] Add a function ff_url_join for assembling URLs Originally committed as revision 22225 to svn://svn.ffmpeg.org/ffmpeg/trunk --- libavformat/avformat.h | 24 +++++++++++++++++++++ libavformat/utils.c | 49 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/libavformat/avformat.h b/libavformat/avformat.h index e7426aa16d..aa727979ba 100644 --- a/libavformat/avformat.h +++ b/libavformat/avformat.h @@ -1350,6 +1350,30 @@ void url_split(char *proto, int proto_size, char *path, int path_size, const char *url); +/** + * Assembles a URL string from components. This is the reverse operation + * of url_split. + * + * Note, this requires networking to be initialized, so the caller must + * ensure ff_network_init has been called. + * + * @see url_split + * + * @param str the buffer to fill with the url + * @param size the size of the str buffer + * @param proto the protocol identifier, if null, the separator + * after the identifier is left out, too + * @param authorization an optional authorization string, may be null + * @param hostname the host name string + * @param port the port number, left out from the string if negative + * @param fmt a generic format string for everything to add after the + * host/port, may be null + * @return the number of characters written to the destination buffer + */ +int ff_url_join(char *str, int size, const char *proto, + const char *authorization, const char *hostname, + int port, const char *fmt, ...); + #if LIBAVFORMAT_VERSION_MAJOR < 53 /** * @deprecated Use av_match_ext() instead. diff --git a/libavformat/utils.c b/libavformat/utils.c index b8538c2602..2317fe77e5 100644 --- a/libavformat/utils.c +++ b/libavformat/utils.c @@ -27,6 +27,10 @@ #include #include #include +#include +#if CONFIG_NETWORK +#include "network.h" +#endif #undef NDEBUG #include @@ -3446,3 +3450,48 @@ void av_set_pts_info(AVStream *s, int pts_wrap_bits, if(!s->time_base.num || !s->time_base.den) s->time_base.num= s->time_base.den= 0; } + +int ff_url_join(char *str, int size, const char *proto, + const char *authorization, const char *hostname, + int port, const char *fmt, ...) +{ +#if CONFIG_NETWORK + struct addrinfo hints, *ai; +#endif + + str[0] = '\0'; + if (proto) + av_strlcatf(str, size, "%s://", proto); + if (authorization) + av_strlcatf(str, size, "%s@", authorization); +#if CONFIG_NETWORK && defined(AF_INET6) + /* Determine if hostname is a numerical IPv6 address, + * properly escape it within [] in that case. */ + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_NUMERICHOST; + if (!getaddrinfo(hostname, NULL, &hints, &ai)) { + if (ai->ai_family == AF_INET6) { + av_strlcat(str, "[", size); + av_strlcat(str, hostname, size); + av_strlcat(str, "]", size); + } else { + av_strlcat(str, hostname, size); + } + freeaddrinfo(ai); + } else +#endif + /* Not an IPv6 address, just output the plain string. */ + av_strlcat(str, hostname, size); + + if (port >= 0) + av_strlcatf(str, size, ":%d", port); + if (fmt) { + va_list vl; + int len = strlen(str); + + va_start(vl, fmt); + vsnprintf(str + len, size > len ? size - len : 0, fmt, vl); + va_end(vl); + } + return strlen(str); +}