@ -47,6 +47,7 @@ typedef struct {
int64_t off , filesize ;
char location [ MAX_URL_SIZE ] ;
HTTPAuthState auth_state ;
HTTPAuthState proxy_auth_state ;
char * headers ;
int willclose ; /**< Set if the server correctly handles Connection: close and will close the connection after feeding us the content. */
int chunked_post ;
@ -71,25 +72,29 @@ static const AVClass flavor ## _context_class = {\
HTTP_CLASS ( http ) ;
HTTP_CLASS ( https ) ;
static int http_connect ( URLContext * h , const char * path , const char * hoststr ,
const char * auth , int * new_location ) ;
static int http_connect ( URLContext * h , const char * path , const char * local_path ,
const char * hoststr , const char * auth ,
const char * proxyauth , int * new_location ) ;
void ff_http_init_auth_state ( URLContext * dest , const URLContext * src )
{
memcpy ( & ( ( HTTPContext * ) dest - > priv_data ) - > auth_state ,
& ( ( HTTPContext * ) src - > priv_data ) - > auth_state , sizeof ( HTTPAuthState ) ) ;
memcpy ( & ( ( HTTPContext * ) dest - > priv_data ) - > proxy_auth_state ,
& ( ( HTTPContext * ) src - > priv_data ) - > proxy_auth_state ,
sizeof ( HTTPAuthState ) ) ;
}
/* return non zero if error */
static int http_open_cnx ( URLContext * h )
{
const char * path , * proxy_path , * lower_proto = " tcp " ;
const char * path , * proxy_path , * lower_proto = " tcp " , * local_path ;
char hostname [ 1024 ] , hoststr [ 1024 ] , proto [ 10 ] ;
char auth [ 1024 ] ;
char auth [ 1024 ] , proxyauth [ 1024 ] ;
char path1 [ 1024 ] ;
char buf [ 1024 ] ;
char buf [ 1024 ] , urlbuf [ 1024 ] ;
int port , use_proxy , err , location_changed = 0 , redirects = 0 ;
HTTPAuthType cur_auth_type ;
HTTPAuthType cur_auth_type , cur_proxy_auth_type ;
HTTPContext * s = h - > priv_data ;
URLContext * hd = NULL ;
@ -105,15 +110,19 @@ static int http_open_cnx(URLContext *h)
path1 , sizeof ( path1 ) , s - > location ) ;
ff_url_join ( hoststr , sizeof ( hoststr ) , NULL , NULL , hostname , port , NULL ) ;
if ( path1 [ 0 ] = = ' \0 ' )
path = " / " ;
else
path = path1 ;
local_path = path ;
if ( use_proxy ) {
av_url_split ( NULL , 0 , auth , sizeof ( auth ) , hostname , sizeof ( hostname ) , & port ,
NULL , 0 , proxy_path ) ;
path = s - > location ;
} else {
if ( path1 [ 0 ] = = ' \0 ' )
path = " / " ;
else
path = path1 ;
/* Reassemble the request URL without auth string - we don't
* want to leak the auth to the proxy . */
ff_url_join ( urlbuf , sizeof ( urlbuf ) , proto , NULL , hostname , port , " %s " ,
path1 ) ;
path = urlbuf ;
av_url_split ( NULL , 0 , proxyauth , sizeof ( proxyauth ) ,
hostname , sizeof ( hostname ) , & port , NULL , 0 , proxy_path ) ;
}
if ( ! strcmp ( proto , " https " ) ) {
lower_proto = " tls " ;
@ -130,7 +139,8 @@ static int http_open_cnx(URLContext *h)
s - > hd = hd ;
cur_auth_type = s - > auth_state . auth_type ;
if ( http_connect ( h , path , hoststr , auth , & location_changed ) < 0 )
cur_proxy_auth_type = s - > auth_state . auth_type ;
if ( http_connect ( h , path , local_path , hoststr , auth , proxyauth , & location_changed ) < 0 )
goto fail ;
if ( s - > http_code = = 401 ) {
if ( cur_auth_type = = HTTP_AUTH_NONE & & s - > auth_state . auth_type ! = HTTP_AUTH_NONE ) {
@ -139,6 +149,14 @@ static int http_open_cnx(URLContext *h)
} else
goto fail ;
}
if ( s - > http_code = = 407 ) {
if ( cur_proxy_auth_type = = HTTP_AUTH_NONE & &
s - > proxy_auth_state . auth_type ! = HTTP_AUTH_NONE ) {
ffurl_close ( hd ) ;
goto redo ;
} else
goto fail ;
}
if ( ( s - > http_code = = 301 | | s - > http_code = = 302 | | s - > http_code = = 303 | | s - > http_code = = 307 )
& & location_changed = = 1 ) {
/* url moved, get next */
@ -237,7 +255,8 @@ static int process_line(URLContext *h, char *line, int line_count,
/* error codes are 4xx and 5xx, but regard 401 as a success, so we
* don ' t abort until all headers have been parsed . */
if ( s - > http_code > = 400 & & s - > http_code < 600 & & ( s - > http_code ! = 401
| | s - > auth_state . auth_type ! = HTTP_AUTH_NONE ) ) {
| | s - > auth_state . auth_type ! = HTTP_AUTH_NONE ) & &
( s - > http_code ! = 407 | | s - > proxy_auth_state . auth_type ! = HTTP_AUTH_NONE ) ) {
end + = strspn ( end , SPACE_CHARS ) ;
av_log ( h , AV_LOG_WARNING , " HTTP error %d %s \n " ,
s - > http_code , end ) ;
@ -278,6 +297,8 @@ static int process_line(URLContext *h, char *line, int line_count,
ff_http_auth_handle_header ( & s - > auth_state , tag , p ) ;
} else if ( ! av_strcasecmp ( tag , " Authentication-Info " ) ) {
ff_http_auth_handle_header ( & s - > auth_state , tag , p ) ;
} else if ( ! av_strcasecmp ( tag , " Proxy-Authenticate " ) ) {
ff_http_auth_handle_header ( & s - > proxy_auth_state , tag , p ) ;
} else if ( ! av_strcasecmp ( tag , " Connection " ) ) {
if ( ! strcmp ( p , " close " ) )
s - > willclose = 1 ;
@ -294,22 +315,27 @@ static inline int has_header(const char *str, const char *header)
return av_stristart ( str , header + 2 , NULL ) | | av_stristr ( str , header ) ;
}
static int http_connect ( URLContext * h , const char * path , const char * hoststr ,
const char * auth , int * new_location )
static int http_connect ( URLContext * h , const char * path , const char * local_path ,
const char * hoststr , const char * auth ,
const char * proxyauth , int * new_location )
{
HTTPContext * s = h - > priv_data ;
int post , err ;
char line [ 1024 ] ;
char headers [ 1024 ] = " " ;
char * authstr = NULL ;
char * authstr = NULL , * proxyauthstr = NULL ;
int64_t off = s - > off ;
int len = 0 ;
const char * method ;
/* send http header */
post = h - > flags & AVIO_FLAG_WRITE ;
authstr = ff_http_auth_create_response ( & s - > auth_state , auth , path ,
post ? " POST " : " GET " ) ;
method = post ? " POST " : " GET " ;
authstr = ff_http_auth_create_response ( & s - > auth_state , auth , local_path ,
method ) ;
proxyauthstr = ff_http_auth_create_response ( & s - > proxy_auth_state , proxyauth ,
local_path , method ) ;
/* set default headers if needed */
if ( ! has_header ( s - > headers , " \r \n User-Agent: " ) )
@ -337,14 +363,17 @@ static int http_connect(URLContext *h, const char *path, const char *hoststr,
" %s "
" %s "
" %s "
" %s%s "
" \r \n " ,
post ? " POST " : " GET " ,
method ,
path ,
post & & s - > chunked_post ? " Transfer-Encoding: chunked \r \n " : " " ,
headers ,
authstr ? authstr : " " ) ;
authstr ? authstr : " " ,
proxyauthstr ? " Proxy- " : " " , proxyauthstr ? proxyauthstr : " " ) ;
av_freep ( & authstr ) ;
av_freep ( & proxyauthstr ) ;
if ( ffurl_write ( s - > hd , s - > buffer , strlen ( s - > buffer ) ) < 0 )
return AVERROR ( EIO ) ;