/*****************************************************************************
* http.c: HTTP input module
*****************************************************************************
- * Copyright (C) 2001-2008 the VideoLAN team
+ * Copyright (C) 2001-2008 VLC authors and VideoLAN
* $Id$
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* RĂ©mi Denis-Courmont <rem # videolan.org>
* Antoine Cellerier <dionoea at videolan dot org>
*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
#include <vlc_input.h>
#include <vlc_md5.h>
#include <vlc_http.h>
+#include "httpcookies.h"
#ifdef HAVE_ZLIB_H
# include <zlib.h>
#include <assert.h>
#include <limits.h>
-#ifdef HAVE_LIBPROXY
-# include <proxy.h>
-#endif
-
-#ifdef WIN32
-# include <windows.h>
-#endif
-
/*****************************************************************************
* Module descriptor
*****************************************************************************/
char *psz_icy_title;
uint64_t i_remaining;
+ uint64_t size;
bool b_seekable;
bool b_reconnect;
bool b_persist;
bool b_has_size;
- vlc_array_t * cookies;
+ http_cookie_jar_t * cookies;
};
/* */
static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
- unsigned i_redirect, vlc_array_t *cookies );
+ unsigned i_redirect, http_cookie_jar_t *cookies );
/* */
static ssize_t Read( access_t *, uint8_t *, size_t );
static int Request( access_t *p_access, uint64_t i_tell );
static void Disconnect( access_t * );
-/* Small Cookie utilities. Cookies support is partial. */
-static char * cookie_get_content( const char * cookie );
-static char * cookie_get_domain( const char * cookie );
-static char * cookie_get_name( const char * cookie );
-static void cookie_append( vlc_array_t * cookies, char * cookie );
-
static void AuthReply( access_t *p_acces, const char *psz_prefix,
vlc_url_t *p_url, http_auth_t *p_auth );
* @return vlc error codes
*/
static int OpenWithCookies( vlc_object_t *p_this, const char *psz_access,
- unsigned i_redirect, vlc_array_t *cookies )
+ unsigned i_redirect, http_cookie_jar_t *cookies )
{
access_t *p_access = (access_t*)p_this;
access_sys_t *p_sys;
char *psz, *p;
- /* Only forward an store cookies if the corresponding option is activated */
- bool b_forward_cookies = var_InheritBool( p_access, "http-forward-cookies" );
- vlc_array_t * saved_cookies = b_forward_cookies ? (cookies ? cookies : vlc_array_new()) : NULL;
-
/* Set up p_access */
STANDARD_READ_ACCESS_INIT;
#ifdef HAVE_ZLIB_H
p_sys->i_remaining = 0;
p_sys->b_persist = false;
p_sys->b_has_size = false;
- p_access->info.i_size = 0;
+ p_sys->size = 0;
p_access->info.i_pos = 0;
p_access->info.b_eof = false;
- p_sys->cookies = saved_cookies;
+ /* 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 : http_cookies_new();
+ else
+ p_sys->cookies = NULL;
http_auth_Init( &p_sys->auth );
http_auth_Init( &p_sys->proxy_auth );
/* Check proxy */
psz = var_InheritString( p_access, "http-proxy" );
- if( psz )
- {
- p_sys->b_proxy = true;
- vlc_UrlParse( &p_sys->proxy, psz, 0 );
- free( psz );
- }
-#ifdef HAVE_LIBPROXY
- else
+ if( psz == NULL )
{
- pxProxyFactory *pf = px_proxy_factory_new();
- if (pf)
- {
- char *buf;
- int i;
- i=asprintf(&buf, "%s://%s", psz_access, p_access->psz_location);
- if (i >= 0)
- {
- msg_Dbg(p_access, "asking libproxy about url '%s'", buf);
- char **proxies = px_proxy_factory_get_proxies(pf, buf);
- if (proxies[0])
- {
- msg_Dbg(p_access, "libproxy suggest to use '%s'", proxies[0]);
- if(strcmp(proxies[0],"direct://") != 0)
- {
- p_sys->b_proxy = true;
- vlc_UrlParse( &p_sys->proxy, proxies[0], 0);
- }
- }
- for(i=0;proxies[i];i++) free(proxies[i]);
- free(proxies);
- free(buf);
- }
- px_proxy_factory_free(pf);
- }
- else
+ char *url;
+
+ if (likely(asprintf(&url, "%s://%s", psz_access,
+ p_access->psz_location) != -1))
{
- msg_Err(p_access, "Allocating memory for libproxy failed");
+ msg_Dbg(p_access, "querying proxy for %s", url);
+ psz = vlc_getProxyUrl(url);
+ free(url);
}
- }
-#elif (0) // defined( WIN32 ) The parsing is not complete enough
- else
- {
- /* Try to get the proxy server address from Windows internet settings using registry. */
- HKEY h_key;
- /* Open the key */
- if( RegOpenKeyEx( HKEY_CURRENT_USER, "Software\\Microsoft"
- "\\Windows\\CurrentVersion\\Internet Settings",
- 0, KEY_READ, &h_key ) == ERROR_SUCCESS )
- {
- DWORD len = sizeof( DWORD );
- BYTE proxyEnable;
- /* Get the proxy enable value */
- if( RegQueryValueEx( h_key, "ProxyEnable", NULL, NULL,
- &proxyEnable, &len ) == ERROR_SUCCESS
- && proxyEnable )
- {
- /* Proxy is enabled */
- /* Get the proxy URL :
- Proxy server value in the registry can be something like "address:port"
- or "ftp=address1:port1;http=address2:port2 ..." depending of the
- confirguration. */
- unsigned char key[256];
-
- len = sizeof( key );
- if( RegQueryValueEx( h_key, "ProxyServer", NULL, NULL,
- key, &len ) == ERROR_SUCCESS )
- {
- /* FIXME: This is lame. The string should be tokenized. */
-#warning FIXME.
- char *psz_proxy = strstr( (char *)key, "http=" );
- if( psz_proxy != NULL )
- {
- psz_proxy += 5;
- char *end = strchr( psz_proxy, ';' );
- if( end != NULL )
- *end = '\0';
- }
- else
- psz_proxy = (char *)key;
- /* Set proxy enable for this connection. */
- p_sys->b_proxy = true;
- vlc_UrlParse( &p_sys->proxy, psz_proxy, 0 );
- }
- }
- else
- msg_Dbg( p_access, "HTTP proxy disabled (MSIE)" );
- RegCloseKey( h_key );
- }
+ if (psz != NULL)
+ msg_Dbg(p_access, "proxy: %s", psz);
+ else
+ msg_Dbg(p_access, "no proxy");
}
-#else
- else
+ if( psz != NULL )
{
- psz = getenv( "http_proxy" );
- if( psz )
- {
- p_sys->b_proxy = true;
- vlc_UrlParse( &p_sys->proxy, psz, 0 );
- }
- }
-#endif
+ p_sys->b_proxy = true;
+ vlc_UrlParse( &p_sys->proxy, psz, 0 );
+ free( psz );
- if( psz ) /* No, this is NOT a use-after-free error */
- {
psz = var_InheritString( p_access, "http-proxy-pwd" );
if( psz )
p_sys->proxy.psz_password = p_sys->psz_proxy_passbuf = psz;
- }
- if( p_sys->b_proxy )
- {
if( p_sys->proxy.psz_host == NULL || *p_sys->proxy.psz_host == '\0' )
{
msg_Warn( p_access, "invalid proxy host" );
if( p_sys->i_code == 401 )
{
+ if( p_sys->auth.psz_realm == NULL )
+ {
+ msg_Err( p_access, "authentication failed without realm" );
+ goto error;
+ }
char *psz_login, *psz_password;
/* FIXME ? */
if( p_sys->url.psz_username && p_sys->url.psz_password &&
goto error;
}
-
- /* Do not accept redirection outside of HTTP works */
const char *psz_protocol;
- if( !strncmp( p_sys->psz_location, "http:", 5 ) )
+ if( !strncmp( p_sys->psz_location, "http://", 7 ) )
psz_protocol = "http";
- else if( !strncmp( p_sys->psz_location, "https:", 6 ) )
+ else if( !strncmp( p_sys->psz_location, "https://", 8 ) )
psz_protocol = "https";
else
- {
- msg_Err( p_access, "insecure redirection ignored" );
+ { /* Do not accept redirection outside of HTTP */
+ msg_Err( p_access, "unsupported redirection ignored" );
goto error;
}
free( p_access->psz_location );
- p_access->psz_location = strdup( p_sys->psz_location );
+ p_access->psz_location = strdup( p_sys->psz_location
+ + strlen( psz_protocol ) + 3 );
/* Clean up current Open() run */
vlc_UrlClean( &p_sys->url );
http_auth_Reset( &p_sys->auth );
free( p_access->psz_demux );
p_access->psz_demux = strdup( "podcast" );
}
- else if( p_sys->psz_mime &&
- !strncasecmp( p_sys->psz_mime, "application/xspf+xml", 20 ) &&
- ( memchr( " ;\t", p_sys->psz_mime[20], 4 ) != NULL ) )
- {
- free( p_access->psz_demux );
- p_access->psz_demux = strdup( "xspf-open" );
- }
if( p_sys->b_reconnect ) msg_Dbg( p_access, "auto re-connect enabled" );
Disconnect( p_access );
vlc_tls_Delete( p_sys->p_creds );
- if( p_sys->cookies )
- {
- int i;
- for( i = 0; i < vlc_array_count( p_sys->cookies ); i++ )
- free(vlc_array_item_at_index( p_sys->cookies, i ));
- vlc_array_destroy( p_sys->cookies );
- }
+ http_cookies_destroy( p_sys->cookies );
#ifdef HAVE_ZLIB_H
inflateEnd( &p_sys->inflate.stream );
Disconnect( p_access );
vlc_tls_Delete( p_sys->p_creds );
- if( p_sys->cookies )
- {
- int i;
- for( i = 0; i < vlc_array_count( p_sys->cookies ); i++ )
- free(vlc_array_item_at_index( p_sys->cookies, i ));
- vlc_array_destroy( p_sys->cookies );
- }
+ http_cookies_destroy( p_sys->cookies );
#ifdef HAVE_ZLIB_H
inflateEnd( &p_sys->inflate.stream );
if( p_sys->b_has_size )
{
/* Remaining bytes in the file */
- uint64_t remainder = p_access->info.i_size - p_access->info.i_pos;
+ uint64_t remainder = p_sys->size - p_access->info.i_pos;
if( remainder < i_len )
i_len = remainder;
p_access->info.i_pos += i_read;
if( p_sys->b_has_size )
{
- assert( p_access->info.i_pos <= p_access->info.i_size );
+ assert( p_access->info.i_pos <= p_sys->size );
assert( (unsigned)i_read <= p_sys->i_remaining );
p_sys->i_remaining -= i_read;
}
p_sys->psz_icy_title = EnsureUTF8( psz_tmp );
if( !p_sys->psz_icy_title )
free( psz_tmp );
- p_access->info.i_update |= INPUT_UPDATE_META;
- msg_Dbg( p_access, "New Title=%s", p_sys->psz_icy_title );
+ msg_Dbg( p_access, "New Icy-Title=%s", p_sys->psz_icy_title );
+ input_thread_t *p_input = access_GetParentInput( p_access );
+ if( p_input )
+ {
+ input_item_t *p_input_item = input_GetItem( p_access->p_input );
+ if( p_input_item )
+ input_item_SetMeta( p_input_item, vlc_meta_NowPlaying, p_sys->psz_icy_title );
+ vlc_object_release( p_input );
+ }
}
}
free( psz_meta );
p_sys->inflate.stream.next_out = p_buffer;
i_ret = inflate( &p_sys->inflate.stream, Z_SYNC_FLUSH );
- msg_Warn( p_access, "inflate return value: %d, %s", i_ret, p_sys->inflate.stream.msg );
+ if ( i_ret != Z_OK && i_ret != Z_STREAM_END )
+ msg_Warn( p_access, "inflate return value: %d, %s", i_ret, p_sys->inflate.stream.msg );
return i_len - p_sys->inflate.stream.avail_out;
}
*****************************************************************************/
static int Seek( access_t *p_access, uint64_t i_pos )
{
- msg_Dbg( p_access, "trying to seek to %"PRId64, i_pos );
+ access_sys_t *p_sys = p_access->p_sys;
+ msg_Dbg( p_access, "trying to seek to %"PRId64, i_pos );
Disconnect( p_access );
- if( p_access->info.i_size
- && i_pos >= p_access->info.i_size ) {
- msg_Err( p_access, "seek to far" );
- int retval = Seek( p_access, p_access->info.i_size - 1 );
+ if( p_sys->size && i_pos >= p_sys->size )
+ {
+ msg_Err( p_access, "seek too far" );
+ int retval = Seek( p_access, p_sys->size - 1 );
if( retval == VLC_SUCCESS ) {
uint8_t p_buffer[2];
Read( p_access, p_buffer, 1);
access_sys_t *p_sys = p_access->p_sys;
bool *pb_bool;
int64_t *pi_64;
- vlc_meta_t *p_meta;
switch( i_query )
{
* var_InheritInteger( p_access, "network-caching" );
break;
+ case ACCESS_GET_SIZE:
+ pi_64 = (int64_t*)va_arg( args, int64_t * );
+ *pi_64 = p_sys->size;
+ break;
+
/* */
case ACCESS_SET_PAUSE_STATE:
break;
- case ACCESS_GET_META:
- p_meta = (vlc_meta_t*)va_arg( args, vlc_meta_t* );
-
- if( p_sys->psz_icy_name )
- vlc_meta_Set( p_meta, vlc_meta_Title, p_sys->psz_icy_name );
- if( p_sys->psz_icy_genre )
- vlc_meta_Set( p_meta, vlc_meta_Genre, p_sys->psz_icy_genre );
- if( p_sys->psz_icy_title )
- vlc_meta_Set( p_meta, vlc_meta_NowPlaying, p_sys->psz_icy_title );
- break;
-
case ACCESS_GET_CONTENT_TYPE:
*va_arg( args, char ** ) =
p_sys->psz_mime ? strdup( p_sys->psz_mime ) : NULL;
break;
- case ACCESS_GET_TITLE_INFO:
- case ACCESS_SET_TITLE:
- case ACCESS_SET_SEEKPOINT:
- case ACCESS_SET_PRIVATE_ID_STATE:
- return VLC_EGENERIC;
-
default:
- msg_Warn( p_access, "unimplemented query in control" );
return VLC_EGENERIC;
}
p_sys->i_remaining = 0;
p_sys->b_persist = false;
p_sys->b_has_size = false;
- p_access->info.i_size = 0;
+ p_sys->size = 0;
p_access->info.i_pos = i_tell;
p_access->info.b_eof = false;
}
/* TLS/SSL handshake */
+ const char *alpn[] = { "http/1.1", NULL };
+
p_sys->p_tls = vlc_tls_ClientSessionCreate( p_sys->p_creds, p_sys->fd,
- p_sys->url.psz_host, "https" );
+ p_sys->url.psz_host, "https",
+ p_sys->i_version ? alpn : NULL, NULL );
if( p_sys->p_tls == NULL )
{
msg_Err( p_access, "cannot establish HTTP/TLS session" );
net_Printf( p_access, p_sys->fd, pvs, "Referer: %s\r\n",
p_sys->psz_referrer);
}
-#ifdef HAVE_ZLIB_H
- net_Printf( p_access, p_sys->fd, pvs, "Accept-Encoding: gzip, deflate\r\n" );
-#endif
/* Offset */
if( p_sys->i_version == 1 && ! p_sys->b_continuous )
{
/* Cookies */
if( p_sys->cookies )
{
- int i;
- for( i = 0; i < vlc_array_count( p_sys->cookies ); i++ )
+ char * psz_cookiestring = http_cookies_for_url( p_sys->cookies, &p_sys->url );
+ if ( psz_cookiestring )
{
- const char * cookie = vlc_array_item_at_index( p_sys->cookies, i );
- char * psz_cookie_content = cookie_get_content( cookie );
- char * psz_cookie_domain = cookie_get_domain( cookie );
-
- assert( psz_cookie_content );
-
- /* FIXME: This is clearly not conforming to the rfc */
- bool is_in_right_domain = (!psz_cookie_domain || strstr( p_sys->url.psz_host, psz_cookie_domain ));
-
- if( is_in_right_domain )
- {
- msg_Dbg( p_access, "Sending Cookie %s", psz_cookie_content );
- if( net_Printf( p_access, p_sys->fd, pvs, "Cookie: %s\r\n", psz_cookie_content ) < 0 )
- msg_Err( p_access, "failed to send Cookie" );
- }
- free( psz_cookie_content );
- free( psz_cookie_domain );
+ msg_Dbg( p_access, "Sending Cookie %s", psz_cookiestring );
+ if( net_Printf( p_access, p_sys->fd, pvs, "Cookie: %s\r\n", psz_cookiestring ) < 0 )
+ msg_Err( p_access, "failed to send Cookie" );
+ free( psz_cookiestring );
}
}
/* Authentication */
- if( p_sys->url.psz_username || p_sys->url.psz_password )
+ if( p_sys->url.psz_username && p_sys->url.psz_password )
AuthReply( p_access, "", &p_sys->url, &p_sys->auth );
/* Proxy Authentication */
- if( p_sys->proxy.psz_username || p_sys->proxy.psz_password )
+ if( p_sys->proxy.psz_username && p_sys->proxy.psz_password )
AuthReply( p_access, "Proxy-", &p_sys->proxy, &p_sys->proxy_auth );
/* ICY meta data request */
{
char *psz = net_Gets( p_access, p_sys->fd, pvs );
char *p;
+ char *p_trailing;
if( psz == NULL )
{
goto error;
}
*p++ = '\0';
- while( *p == ' ' ) p++;
+ p += strspn( p, " \t" );
+
+ /* trim trailing white space */
+ p_trailing = p + strlen( p );
+ if( p_trailing > p )
+ {
+ p_trailing--;
+ while( ( *p_trailing == ' ' || *p_trailing == '\t' ) && p_trailing > p )
+ {
+ *p_trailing = '\0';
+ p_trailing--;
+ }
+ }
if( !strcasecmp( psz, "Content-Length" ) )
{
uint64_t i_size = i_tell + (p_sys->i_remaining = (uint64_t)atoll( p ));
- if(i_size > p_access->info.i_size) {
+ if(i_size > p_sys->size) {
p_sys->b_has_size = true;
- p_access->info.i_size = i_size;
+ p_sys->size = i_size;
}
msg_Dbg( p_access, "this frame size=%"PRIu64, p_sys->i_remaining );
}
else if( !strcasecmp( psz, "Content-Range" ) ) {
uint64_t i_ntell = i_tell;
- uint64_t i_nend = (p_access->info.i_size > 0)?(p_access->info.i_size - 1):i_tell;
- uint64_t i_nsize = p_access->info.i_size;
+ uint64_t i_nend = (p_sys->size > 0) ? (p_sys->size - 1) : i_tell;
+ uint64_t i_nsize = p_sys->size;
sscanf(p,"bytes %"SCNu64"-%"SCNu64"/%"SCNu64,&i_ntell,&i_nend,&i_nsize);
if(i_nend > i_ntell ) {
p_access->info.i_pos = i_ntell;
p_sys->i_icy_offset = i_ntell;
p_sys->i_remaining = i_nend+1-i_ntell;
uint64_t i_size = (i_nsize > i_nend) ? i_nsize : (i_nend + 1);
- if(i_size > p_access->info.i_size) {
+ if(i_size > p_sys->size) {
p_sys->b_has_size = true;
- p_access->info.i_size = i_size;
+ p_sys->size = i_size;
}
msg_Dbg( p_access, "stream size=%"PRIu64",pos=%"PRIu64",remaining=%"PRIu64,
i_nsize, i_ntell, p_sys->i_remaining);
if( !p_sys->psz_icy_name )
free( psz_tmp );
msg_Dbg( p_access, "Icy-Name: %s", p_sys->psz_icy_name );
+ input_thread_t *p_input = access_GetParentInput( p_access );
+ if ( p_input )
+ {
+ input_item_t *p_input_item = input_GetItem( p_access->p_input );
+ if ( p_input_item )
+ input_item_SetMeta( p_input_item, vlc_meta_Title, p_sys->psz_icy_name );
+ vlc_object_release( p_input );
+ }
p_sys->b_icecast = true; /* be on the safeside. set it here as well. */
p_sys->b_reconnect = true;
if( !p_sys->psz_icy_genre )
free( psz_tmp );
msg_Dbg( p_access, "Icy-Genre: %s", p_sys->psz_icy_genre );
+ input_thread_t *p_input = access_GetParentInput( p_access );
+ if( p_input )
+ {
+ input_item_t *p_input_item = input_GetItem( p_access->p_input );
+ if( p_input_item )
+ input_item_SetMeta( p_input_item, vlc_meta_Genre, p_sys->psz_icy_genre );
+ vlc_object_release( p_input );
+ }
}
else if( !strncasecmp( psz, "Icy-Notice", 10 ) )
{
{
if( p_sys->cookies )
{
- msg_Dbg( p_access, "Accepting Cookie: %s", p );
- cookie_append( p_sys->cookies, strdup(p) );
+ if ( http_cookies_append( p_sys->cookies, p, &p_sys->url ) )
+ msg_Dbg( p_access, "Accepting Cookie: %s", p );
+ else
+ msg_Dbg( p_access, "Rejected Cookie: %s", p );
}
else
msg_Dbg( p_access, "We have a Cookie we won't remember: %s", p );
}
-/*****************************************************************************
- * Cookies (FIXME: we may want to rewrite that using a nice structure to hold
- * them) (FIXME: only support the "domain=" param)
- *****************************************************************************/
-
-/* Get the NAME=VALUE part of the Cookie */
-static char * cookie_get_content( const char * cookie )
-{
- char * ret = strdup( cookie );
- if( !ret ) return NULL;
- char * str = ret;
- /* Look for a ';' */
- while( *str && *str != ';' ) str++;
- /* Replace it by a end-char */
- if( *str == ';' ) *str = 0;
- return ret;
-}
-
-/* Get the domain where the cookie is stored */
-static char * cookie_get_domain( const char * cookie )
-{
- const char * str = cookie;
- static const char domain[] = "domain=";
- if( !str )
- return NULL;
- /* Look for a ';' */
- while( *str )
- {
- if( !strncmp( str, domain, sizeof(domain) - 1 /* minus \0 */ ) )
- {
- str += sizeof(domain) - 1 /* minus \0 */;
- char * ret = strdup( str );
- /* Now remove the next ';' if present */
- char * ret_iter = ret;
- while( *ret_iter && *ret_iter != ';' ) ret_iter++;
- if( *ret_iter == ';' )
- *ret_iter = 0;
- return ret;
- }
- /* Go to next ';' field */
- while( *str && *str != ';' ) str++;
- if( *str == ';' ) str++;
- /* skip blank */
- while( *str && *str == ' ' ) str++;
- }
- return NULL;
-}
-
-/* Get NAME in the NAME=VALUE field */
-static char * cookie_get_name( const char * cookie )
-{
- char * ret = cookie_get_content( cookie ); /* NAME=VALUE */
- if( !ret ) return NULL;
- char * str = ret;
- while( *str && *str != '=' ) str++;
- *str = 0;
- return ret;
-}
-
-/* Add a cookie in cookies, checking to see how it should be added */
-static void cookie_append( vlc_array_t * cookies, char * cookie )
-{
- int i;
-
- if( !cookie )
- return;
-
- char * cookie_name = cookie_get_name( cookie );
-
- /* Don't send invalid cookies */
- if( !cookie_name )
- return;
-
- char * cookie_domain = cookie_get_domain( cookie );
- for( i = 0; i < vlc_array_count( cookies ); i++ )
- {
- char * current_cookie = vlc_array_item_at_index( cookies, i );
- char * current_cookie_name = cookie_get_name( current_cookie );
- char * current_cookie_domain = cookie_get_domain( current_cookie );
-
- assert( current_cookie_name );
-
- bool is_domain_matching = (
- ( !cookie_domain && !current_cookie_domain ) ||
- ( cookie_domain && current_cookie_domain &&
- !strcmp( cookie_domain, current_cookie_domain ) ) );
-
- if( is_domain_matching && !strcmp( cookie_name, current_cookie_name ) )
- {
- /* Remove previous value for this cookie */
- free( current_cookie );
- vlc_array_remove( cookies, i );
-
- /* Clean */
- free( current_cookie_name );
- free( current_cookie_domain );
- break;
- }
- free( current_cookie_name );
- free( current_cookie_domain );
- }
- free( cookie_name );
- free( cookie_domain );
- vlc_array_append( cookies, cookie );
-}
-
-
/*****************************************************************************
* HTTP authentication
*****************************************************************************/