diff --git a/NEWS b/NEWS index d56b0141d0..4ba2741828 100644 --- a/NEWS +++ b/NEWS @@ -5,7 +5,8 @@ Access: * Support HDS (Http Dynamic Streaming) from Adobe (f4m, f4v, etc.) * New SMB access module using libdsm * Support decompression and extraction through libarchive (tar, zip, rar...) - * Improvements of cookie handling (domain / path matching, Secure cookies) + * Improvements of cookie handling (share cookies between playlist items, + domain / path matching, Secure cookies) Decoder: * OMX GPU-zerocopy support for decoding and display on Android using OpenMax IL diff --git a/include/vlc_http.h b/include/vlc_http.h index 47e3139e27..ab04a8aab8 100644 --- a/include/vlc_http.h +++ b/include/vlc_http.h @@ -69,7 +69,7 @@ VLC_API char *http_auth_FormatAuthorizationHeader /* RFC 6265: cookies */ -typedef struct vlc_array_t vlc_http_cookie_jar_t; +typedef struct vlc_http_cookie_jar_t vlc_http_cookie_jar_t; VLC_API vlc_http_cookie_jar_t * vlc_http_cookies_new( void ) VLC_USED; VLC_API void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar ); diff --git a/modules/access/http.c b/modules/access/http.c index 37df233796..6148b95c5e 100644 --- a/modules/access/http.c +++ b/modules/access/http.c @@ -178,19 +178,20 @@ struct access_sys_t uint64_t i_remaining; uint64_t size; + /* cookie jar borrowed from playlist, do not free */ + vlc_http_cookie_jar_t * cookies; + bool b_seekable; bool b_reconnect; bool b_continuous; bool b_pace_control; bool b_persist; bool b_has_size; - - vlc_http_cookie_jar_t * cookies; }; /* */ -static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access, - unsigned i_redirect, vlc_http_cookie_jar_t *cookies ); +static int OpenRedirected( vlc_object_t *p_this, const char *psz_access, + unsigned i_redirect ); /* */ static ssize_t Read( access_t *, uint8_t *, size_t ); @@ -208,6 +209,7 @@ static void AuthReply( access_t *p_acces, const char *psz_prefix, vlc_url_t *p_url, http_auth_t *p_auth ); static int AuthCheckReply( access_t *p_access, const char *psz_header, vlc_url_t *p_url, http_auth_t *p_auth ); +static vlc_http_cookie_jar_t *GetCookieJar( vlc_object_t *p_this ); /***************************************************************************** * Open: @@ -215,20 +217,19 @@ static int AuthCheckReply( access_t *p_access, const char *psz_header, static int Open( vlc_object_t *p_this ) { access_t *p_access = (access_t*)p_this; - return OpenWithCookies( p_this, p_access->psz_access, 5, NULL ); + return OpenRedirected( p_this, p_access->psz_access, 5 ); } /** - * Open the given url using the given cookies + * Open the given url with limited redirects * @param p_this: the vlc object * @psz_access: the acces to use (http, https, ...) (this value must be used * instead of p_access->psz_access) * @i_redirect: number of redirections remaining - * @cookies: the available cookies * @return vlc error codes */ -static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access, - unsigned i_redirect, vlc_http_cookie_jar_t *cookies ) +static int OpenRedirected( vlc_object_t *p_this, const char *psz_access, + unsigned i_redirect ) { access_t *p_access = (access_t*)p_this; access_sys_t *p_sys; @@ -278,7 +279,7 @@ static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access, /* Only forward an store cookies if the corresponding option is activated */ if( var_CreateGetBool( p_access, "http-forward-cookies" ) ) - p_sys->cookies = (cookies != NULL) ? cookies : vlc_http_cookies_new(); + p_sys->cookies = GetCookieJar( p_this ); else p_sys->cookies = NULL; @@ -509,15 +510,13 @@ connect: Disconnect( p_access ); vlc_tls_Delete( p_sys->p_creds ); - cookies = p_sys->cookies; #ifdef HAVE_ZLIB_H inflateEnd( &p_sys->inflate.stream ); #endif free( p_sys ); /* Do new Open() run with new data */ - return OpenWithCookies( p_this, psz_protocol, i_redirect - 1, - cookies ); + return OpenRedirected( p_this, psz_protocol, i_redirect - 1 ); } if( p_sys->b_mms ) @@ -596,8 +595,6 @@ error: Disconnect( p_access ); vlc_tls_Delete( p_sys->p_creds ); - vlc_http_cookies_destroy( p_sys->cookies ); - #ifdef HAVE_ZLIB_H inflateEnd( &p_sys->inflate.stream ); #endif @@ -632,8 +629,6 @@ static void Close( vlc_object_t *p_this ) Disconnect( p_access ); vlc_tls_Delete( p_sys->p_creds ); - vlc_http_cookies_destroy( p_sys->cookies ); - #ifdef HAVE_ZLIB_H inflateEnd( &p_sys->inflate.stream ); free( p_sys->inflate.p_buffer ); @@ -1582,3 +1577,23 @@ static int AuthCheckReply( access_t *p_access, const char *psz_header, p_url->psz_username, p_url->psz_password ); } + +/***************************************************************************** + * HTTP cookies + *****************************************************************************/ + +/** + * Inherit the cookie jar from the playlist + * + * @param p_this: http access object + * @return A borrowed reference to a vlc_http_cookie_jar_t, do not free + */ +static vlc_http_cookie_jar_t *GetCookieJar( vlc_object_t *p_this ) +{ + vlc_value_t val; + + if ( var_Inherit( p_this, "http-cookies", VLC_VAR_ADDRESS, &val ) == VLC_SUCCESS ) + return val.p_address; + else + return NULL; +} diff --git a/src/misc/httpcookies.c b/src/misc/httpcookies.c index 9eccbe7486..2ec3d33707 100644 --- a/src/misc/httpcookies.c +++ b/src/misc/httpcookies.c @@ -1,5 +1,5 @@ /***************************************************************************** - * httpcookies.h: HTTP cookie utilities + * httpcookies.c: HTTP cookie utilities ***************************************************************************** * Copyright (C) 2014 VLC authors and VideoLAN * $Id$ @@ -45,6 +45,12 @@ typedef struct http_cookie_t bool b_secure; } http_cookie_t; +struct vlc_http_cookie_jar_t +{ + vlc_array_t cookies; + vlc_mutex_t lock; +}; + static http_cookie_t * cookie_parse( const char * cookie_header, const vlc_url_t * url ); static void cookie_destroy( http_cookie_t * p_cookie ); static char * cookie_get_content( const char * cookie ); @@ -60,7 +66,14 @@ static char * cookie_default_path( const char *request_path ); vlc_http_cookie_jar_t * vlc_http_cookies_new() { - return vlc_array_new(); + vlc_http_cookie_jar_t * jar = malloc( sizeof( vlc_http_cookie_jar_t ) ); + if ( !jar ) + return NULL; + + vlc_array_init( &jar->cookies ); + vlc_mutex_init( &jar->lock ); + + return jar; } void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar ) @@ -69,9 +82,11 @@ void vlc_http_cookies_destroy( vlc_http_cookie_jar_t * p_jar ) return; int i; - for( i = 0; i < vlc_array_count( p_jar ); i++ ) - cookie_destroy( vlc_array_item_at_index( p_jar, i ) ); - vlc_array_destroy( p_jar ); + for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ ) + cookie_destroy( vlc_array_item_at_index( &p_jar->cookies, i ) ); + + vlc_array_clear( &p_jar->cookies ); + vlc_mutex_destroy( &p_jar->lock ); } bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_cookie_header, const vlc_url_t *p_url ) @@ -85,9 +100,11 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co return false; } - for( i = 0; i < vlc_array_count( p_jar ); i++ ) + vlc_mutex_lock( &p_jar->lock ); + + for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ ) { - http_cookie_t *iter = vlc_array_item_at_index( p_jar, i ); + http_cookie_t *iter = vlc_array_item_at_index( &p_jar->cookies, i ); assert( iter->psz_name ); assert( iter->psz_domain ); @@ -100,24 +117,28 @@ bool vlc_http_cookies_append( vlc_http_cookie_jar_t * p_jar, const char * psz_co if( domains_match && paths_match && names_match ) { /* Remove previous value for this cookie */ - vlc_array_remove( p_jar, i ); + vlc_array_remove( &p_jar->cookies, i ); cookie_destroy(iter); break; } } - vlc_array_append( p_jar, cookie ); + vlc_array_append( &p_jar->cookies, cookie ); + + vlc_mutex_unlock( &p_jar->lock ); return true; } - char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * p_url ) { int i; char *psz_cookiebuf = NULL; - for( i = 0; i < vlc_array_count( p_jar ); i++ ) + + vlc_mutex_lock( &p_jar->lock ); + + for( i = 0; i < vlc_array_count( &p_jar->cookies ); i++ ) { - const http_cookie_t * cookie = vlc_array_item_at_index( p_jar, i ); + const http_cookie_t * cookie = vlc_array_item_at_index( &p_jar->cookies, i ); if ( cookie_should_be_sent( cookie, p_url ) ) { char *psz_updated_buf = NULL; @@ -129,6 +150,7 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * { // TODO: report error free( psz_cookiebuf ); + vlc_mutex_unlock( &p_jar->lock ); return NULL; } free( psz_cookiebuf ); @@ -136,6 +158,8 @@ char *vlc_http_cookies_for_url( vlc_http_cookie_jar_t * p_jar, const vlc_url_t * } } + vlc_mutex_unlock( &p_jar->lock ); + return psz_cookiebuf; } diff --git a/src/playlist/engine.c b/src/playlist/engine.c index de1f76b179..ca342a9551 100644 --- a/src/playlist/engine.c +++ b/src/playlist/engine.c @@ -32,6 +32,7 @@ #include #include #include +#include #include "playlist_internal.h" #include "input/resource.h" @@ -296,6 +297,15 @@ playlist_t *playlist_Create( vlc_object_t *p_parent ) if( aout != NULL ) input_resource_PutAout( p->p_input_resource, aout ); + /* Initialize the shared HTTP cookie jar */ + vlc_value_t cookies; + cookies.p_address = vlc_http_cookies_new(); + if ( likely(cookies.p_address) ) + { + var_Create( p_playlist, "http-cookies", VLC_VAR_ADDRESS ); + var_SetChecked( p_playlist, "http-cookies", VLC_VAR_ADDRESS, cookies ); + } + /* Thread */ playlist_Activate (p_playlist); @@ -366,6 +376,13 @@ void playlist_Destroy( playlist_t *p_playlist ) ARRAY_RESET( p_playlist->items ); ARRAY_RESET( p_playlist->current ); + vlc_http_cookie_jar_t *cookies = var_GetAddress( p_playlist, "http-cookies" ); + if ( cookies ) + { + var_Destroy( p_playlist, "http-cookies" ); + vlc_http_cookies_destroy( cookies ); + } + vlc_object_release( p_playlist ); }