vlc | branch: master | Rémi Denis-Courmont <[email protected]> | Mon Aug 20 23:06:18 2012 +0300| [85b213028c1f04d831422381d1ac523316102843] | committer: Rémi Denis-Courmont
vlc_UrlParse: rewrite, de-inline and simplify > http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=85b213028c1f04d831422381d1ac523316102843 --- include/vlc_url.h | 148 ++-------------------------------------------------- src/libvlccore.sym | 2 + src/text/url.c | 113 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 118 insertions(+), 145 deletions(-) diff --git a/include/vlc_url.h b/include/vlc_url.h index fa7677c..820250f 100644 --- a/include/vlc_url.h +++ b/include/vlc_url.h @@ -38,10 +38,8 @@ struct vlc_url_t char *psz_username; char *psz_password; char *psz_host; - int i_port; - + unsigned i_port; char *psz_path; - char *psz_option; char *psz_buffer; /* to be freed */ @@ -52,146 +50,6 @@ VLC_API char * decode_URI( char *psz ); VLC_API char * encode_URI_component( const char *psz ) VLC_MALLOC; VLC_API char * make_path( const char *url ) VLC_MALLOC; -/***************************************************************************** - * vlc_UrlParse: - ***************************************************************************** - * option : if != 0 then path is split at this char - * - * format [protocol://[login[:password]@]][host[:port]]/path[OPTIONoption] - *****************************************************************************/ -static inline void vlc_UrlParse( vlc_url_t *url, const char *psz_url, - char option ) -{ - char *psz_dup; - char *psz_parse; - char *p; - char *p2; - - url->psz_protocol = NULL; - url->psz_username = NULL; - url->psz_password = NULL; - url->psz_host = NULL; - url->i_port = 0; - url->psz_path = NULL; - url->psz_option = NULL; - - if( psz_url == NULL ) - { - url->psz_buffer = NULL; - return; - } - url->psz_buffer = psz_parse = psz_dup = strdup( psz_url ); - - /* Search a valid protocol */ - p = strstr( psz_parse, ":/" ); - if( p != NULL ) - { - for( p2 = psz_parse; p2 < p; p2++ ) - { -#define I(i,a,b) ( (a) <= (i) && (i) <= (b) ) - if( !I(*p2, 'a', 'z' ) && !I(*p2, 'A', 'Z') && !I(*p2, '0', '9') && *p2 != '+' && *p2 != '-' && *p2 != '.' ) - { - p = NULL; - break; - } -#undef I - } - } - - if( p != NULL ) - { - /* we have a protocol */ - - /* skip :// */ - *p++ = '\0'; - if( p[1] == '/' ) - p += 2; - url->psz_protocol = psz_parse; - psz_parse = p; - } - p = strchr( psz_parse, '@' ); - p2 = strchr( psz_parse, '/' ); - if( p != NULL && ( p2 != NULL ? p < p2 : 1 ) ) - { - /* We have a login */ - url->psz_username = psz_parse; - *p++ = '\0'; - - psz_parse = strchr( psz_parse, ':' ); - if( psz_parse != NULL ) - { - /* We have a password */ - *psz_parse++ = '\0'; - url->psz_password = psz_parse; - decode_URI( url->psz_password ); - } - decode_URI( url->psz_username ); - psz_parse = p; - } - - p = strchr( psz_parse, '/' ); - if( !p || psz_parse < p ) - { - /* We have a host[:port] */ - url->psz_host = strdup( psz_parse ); - if( p ) - { - url->psz_host[p - psz_parse] = '\0'; - } - - if( *url->psz_host == '[' ) - { - /* Ipv6 address */ - p2 = strchr( url->psz_host, ']' ); - if( p2 ) - { - p2 = strchr( p2, ':' ); - } - } - else - { - p2 = strchr( url->psz_host, ':' ); - } - if( p2 ) - { - *p2++ = '\0'; - url->i_port = atoi( p2 ); - } - } - psz_parse = p; - - /* Now parse psz_path and psz_option */ - if( psz_parse ) - { - url->psz_path = psz_parse; - if( option != '\0' ) - { - p = strchr( url->psz_path, option ); - if( p ) - { - *p++ = '\0'; - url->psz_option = p; - } - } - } -} - -/***************************************************************************** - * vlc_UrlClean: - *****************************************************************************/ -static inline void vlc_UrlClean( vlc_url_t *url ) -{ - free( url->psz_buffer ); - free( url->psz_host ); - - url->psz_protocol = NULL; - url->psz_username = NULL; - url->psz_password = NULL; - url->psz_host = NULL; - url->i_port = 0; - url->psz_path = NULL; - url->psz_option = NULL; - - url->psz_buffer = NULL; -} +VLC_API void vlc_UrlParse (vlc_url_t *, const char *, unsigned char); +VLC_API void vlc_UrlClean (vlc_url_t *); #endif diff --git a/src/libvlccore.sym b/src/libvlccore.sym index d35b800..94b2a55 100644 --- a/src/libvlccore.sym +++ b/src/libvlccore.sym @@ -221,6 +221,8 @@ libvlc_InternalDestroy libvlc_InternalInit libvlc_Quit libvlc_SetExitHandler +vlc_UrlParse +vlc_UrlClean vlc_path2uri make_path mdate diff --git a/src/text/url.c b/src/text/url.c index f0c152b..fa9d86b 100644 --- a/src/text/url.c +++ b/src/text/url.c @@ -369,3 +369,116 @@ out: free (path); return ret; /* unknown scheme */ } + +/** + * Splits an URL into parts. + * \param url structure of URL parts [OUT] + * \param str nul-terminated URL string to split + * \param opt if non-zero, character separating paths from options, + * normally the question mark + * \note Use vlc_UrlClean() to free associated resources + * \bug Errors cannot be detected. + * \return nothing + */ +void vlc_UrlParse (vlc_url_t *restrict url, const char *str, unsigned char opt) +{ + url->psz_protocol = NULL; + url->psz_username = NULL; + url->psz_password = NULL; + url->psz_host = NULL; + url->i_port = 0; + url->psz_path = NULL; + url->psz_option = NULL; + url->psz_buffer = NULL; + + if (str == NULL) + return; + + char *buf = strdup (str); + if (unlikely(buf == NULL)) + abort (); + url->psz_buffer = buf; + + char *cur = buf, *next; + + /* URL scheme */ + next = strchr (cur, ':'); + /* This is not strictly correct. In principles, the scheme is always + * present in an absolute URL and followed by a colon. Depending on the + * URL scheme, the two subsequent slashes are not required. + * VLC uses a different scheme for historical compatibility reasons - the + * scheme is often implicit. */ + if (next != NULL && !strncmp (next + 1, "//", 2)) + { + *next = '\0'; + next += 3; + url->psz_protocol = cur; + cur = next; + } + + /* Path */ + next = strchr (cur, '/'); + if (next != NULL) + { + *next = '\0'; /* temporary nul, reset to slash later */ + url->psz_path = next; + if (opt && (next = strchr (next, opt)) != NULL) + { + *(next++) = '\0'; + url->psz_option = next; + } + } + /*else + url->psz_path = "/";*/ + + /* User name */ + next = strchr (cur, '@'); + if (next != NULL) + { + *(next++) = '\0'; + url->psz_username = cur; + cur = next; + + /* Password (obsolete) */ + next = strchr (url->psz_username, ':'); + if (next != NULL) + { + *(next++) = '\0'; + url->psz_password = next; + decode_URI (url->psz_password); + } + decode_URI (url->psz_username); + } + + /* Host name */ + if (*cur == '[' && (next = strstr (cur, "]:")) != NULL) + { + /* IPv6 numeral within brackets */ + *(next++) = '\0'; + url->psz_host = strdup (cur + 1); + } + else + { + url->psz_host = strdup (cur); + next = strchr (cur, ':'); + } + + /* Port number */ + if (next != NULL) + { + assert (*next == ':'); + url->i_port = atoi (next + 1); + } + + if (url->psz_path != NULL) + *url->psz_path = '/'; /* restore leading slash */ +} + +/** + * Releases resources allocated by vlc_UrlParse(). + */ +void vlc_UrlClean (vlc_url_t *restrict url) +{ + free (url->psz_host); + free (url->psz_buffer); +} _______________________________________________ vlc-commits mailing list [email protected] http://mailman.videolan.org/listinfo/vlc-commits
