📄 http.c
字号:
/***************************************************************************** * http.c: HTTP input module ***************************************************************************** * Copyright (C) 2001-2008 the VideoLAN team * $Id: 66e32ffac17e8cd717aca74bfc2aa4c929809bf4 $ * * Authors: Laurent Aimar <fenrir@via.ecp.fr> * Christophe Massiot <massiot@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 * (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. * * 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. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_access.h>#include <vlc_interface.h>#include <vlc_meta.h>#include <vlc_network.h>#include <vlc_url.h>#include <vlc_tls.h>#include <vlc_strings.h>#include <vlc_charset.h>#include <vlc_input.h>#include <vlc_md5.h>#ifdef HAVE_ZLIB_H# include <zlib.h>#endif#include <assert.h>#ifdef HAVE_PROXY_H# include "proxy.h"#endif/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );#define PROXY_TEXT N_("HTTP proxy")#define PROXY_LONGTEXT N_( \ "HTTP proxy to be used It must be of the form " \ "http://[user@]myproxy.mydomain:myport/ ; " \ "if empty, the http_proxy environment variable will be tried." )#define PROXY_PASS_TEXT N_("HTTP proxy password")#define PROXY_PASS_LONGTEXT N_( \ "If your HTTP proxy requires a password, set it here." )#define CACHING_TEXT N_("Caching value in ms")#define CACHING_LONGTEXT N_( \ "Caching value for HTTP streams. This " \ "value should be set in milliseconds." )#define AGENT_TEXT N_("HTTP user agent")#define AGENT_LONGTEXT N_("User agent that will be " \ "used for the connection.")#define RECONNECT_TEXT N_("Auto re-connect")#define RECONNECT_LONGTEXT N_( \ "Automatically try to reconnect to the stream in case of a sudden " \ "disconnect." )#define CONTINUOUS_TEXT N_("Continuous stream")#define CONTINUOUS_LONGTEXT N_("Read a file that is " \ "being constantly updated (for example, a JPG file on a server). " \ "You should not globally enable this option as it will break all other " \ "types of HTTP streams." )#define FORWARD_COOKIES_TEXT N_("Forward Cookies")#define FORWARD_COOKIES_LONGTEXT N_("Forward Cookies Across http redirections ")vlc_module_begin(); set_description( N_("HTTP input") ); set_capability( "access", 0 ); set_shortname( N_( "HTTP(S)" ) ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_ACCESS ); add_string( "http-proxy", NULL, NULL, PROXY_TEXT, PROXY_LONGTEXT, false ); add_password( "http-proxy-pwd", NULL, NULL, PROXY_PASS_TEXT, PROXY_PASS_LONGTEXT, false ); add_integer( "http-caching", 4 * DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, true ); add_string( "http-user-agent", COPYRIGHT_MESSAGE , NULL, AGENT_TEXT, AGENT_LONGTEXT, true ); add_bool( "http-reconnect", 0, NULL, RECONNECT_TEXT, RECONNECT_LONGTEXT, true ); add_bool( "http-continuous", 0, NULL, CONTINUOUS_TEXT, CONTINUOUS_LONGTEXT, true ); add_bool( "http-forward-cookies", 0, NULL, FORWARD_COOKIES_TEXT, FORWARD_COOKIES_LONGTEXT, true ); add_obsolete_string("http-user"); add_obsolete_string("http-pwd"); add_shortcut( "http" ); add_shortcut( "https" ); add_shortcut( "unsv" ); add_shortcut( "itpc" ); /* iTunes Podcast */ set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************//* RFC 2617: Basic and Digest Access Authentication */typedef struct http_auth_t{ char *psz_realm; char *psz_domain; char *psz_nonce; char *psz_opaque; char *psz_stale; char *psz_algorithm; char *psz_qop; int i_nonce; char *psz_cnonce; char *psz_HA1; /* stored H(A1) value if algorithm = "MD5-sess" */} http_auth_t;struct access_sys_t{ int fd; tls_session_t *p_tls; v_socket_t *p_vs; /* From uri */ vlc_url_t url; char *psz_user_agent; http_auth_t auth; /* Proxy */ bool b_proxy; vlc_url_t proxy; http_auth_t proxy_auth; char *psz_proxy_passbuf; /* */ int i_code; const char *psz_protocol; int i_version; char *psz_mime; char *psz_pragma; char *psz_location; bool b_mms; bool b_icecast; bool b_ssl;#ifdef HAVE_ZLIB_H bool b_compressed; struct { z_stream stream; uint8_t *p_buffer; } inflate;#endif bool b_chunked; int64_t i_chunk; int i_icy_meta; int64_t i_icy_offset; char *psz_icy_name; char *psz_icy_genre; char *psz_icy_title; int64_t i_remaining; bool b_seekable; bool b_reconnect; bool b_continuous; bool b_pace_control; bool b_persist; vlc_array_t * cookies;};/* */static int OpenWithCookies( vlc_object_t *p_this, vlc_array_t *cookies );/* */static ssize_t Read( access_t *, uint8_t *, size_t );static ssize_t ReadCompressed( access_t *, uint8_t *, size_t );static int Seek( access_t *, int64_t );static int Control( access_t *, int, va_list );/* */static int Connect( access_t *, int64_t );static int Request( access_t *p_access, int64_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 AuthParseHeader( access_t *p_access, const char *psz_header, http_auth_t *p_auth );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 void AuthReset( http_auth_t *p_auth );/***************************************************************************** * Open: *****************************************************************************/static int Open( vlc_object_t *p_this ){ return OpenWithCookies( p_this, NULL );}static int OpenWithCookies( vlc_object_t *p_this, vlc_array_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_CreateGetBool( p_access, "http-forward-cookies" ); vlc_array_t * saved_cookies = b_forward_cookies ? (cookies ?: vlc_array_new()) : NULL; /* Set up p_access */ STANDARD_READ_ACCESS_INIT;#ifdef HAVE_ZLIB_H p_access->pf_read = ReadCompressed;#endif p_sys->fd = -1; p_sys->b_proxy = false; p_sys->psz_proxy_passbuf = NULL; p_sys->i_version = 1; p_sys->b_seekable = true; p_sys->psz_mime = NULL; p_sys->psz_pragma = NULL; p_sys->b_mms = false; p_sys->b_icecast = false; p_sys->psz_location = NULL; p_sys->psz_user_agent = NULL; p_sys->b_pace_control = true; p_sys->b_ssl = false;#ifdef HAVE_ZLIB_H p_sys->b_compressed = false; /* 15 is the max windowBits, +32 to enable optional gzip decoding */ if( inflateInit2( &p_sys->inflate.stream, 32+15 ) != Z_OK ) msg_Warn( p_access, "Error during zlib initialisation: %s", p_sys->inflate.stream.msg ); if( zlibCompileFlags() & (1<<17) ) msg_Warn( p_access, "Your zlib was compiled without gzip support." ); p_sys->inflate.p_buffer = NULL;#endif p_sys->p_tls = NULL; p_sys->p_vs = NULL; p_sys->i_icy_meta = 0; p_sys->i_icy_offset = 0; p_sys->psz_icy_name = NULL; p_sys->psz_icy_genre = NULL; p_sys->psz_icy_title = NULL; p_sys->i_remaining = 0; p_sys->b_persist = false; p_access->info.i_size = -1; p_access->info.i_pos = 0; p_access->info.b_eof = false; p_sys->cookies = saved_cookies; /* Parse URI - remove spaces */ p = psz = strdup( p_access->psz_path ); while( (p = strchr( p, ' ' )) != NULL ) *p = '+'; vlc_UrlParse( &p_sys->url, psz, 0 ); free( psz ); if( p_sys->url.psz_host == NULL || *p_sys->url.psz_host == '\0' ) { msg_Warn( p_access, "invalid host" ); goto error; } if( !strncmp( p_access->psz_access, "https", 5 ) ) { /* HTTP over SSL */ p_sys->b_ssl = true; if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 443; } else { if( p_sys->url.i_port <= 0 ) p_sys->url.i_port = 80; } /* Do user agent */ p_sys->psz_user_agent = var_CreateGetString( p_access, "http-user-agent" ); /* Check proxy */ psz = var_CreateGetNonEmptyString( p_access, "http-proxy" ); if( psz ) { p_sys->b_proxy = true; vlc_UrlParse( &p_sys->proxy, psz, 0 ); free( psz ); }#ifdef HAVE_PROXY_H else { pxProxyFactory *pf = px_proxy_factory_new(); if (pf) { char *buf; int i; i=asprintf(&buf, "%s://%s", p_access->psz_access, p_access->psz_path); 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 { msg_Err(p_access, "Allocating memory for libproxy failed"); } }#elif HAVE_GETENV else { psz = getenv( "http_proxy" ); if( psz ) { p_sys->b_proxy = true; vlc_UrlParse( &p_sys->proxy, psz, 0 ); } }#endif if( psz ) /* No, this is NOT a use-after-free error */ { psz = var_CreateGetNonEmptyString( 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" ); goto error; } if( p_sys->proxy.i_port <= 0 ) { p_sys->proxy.i_port = 80; } } msg_Dbg( p_access, "http: server='%s' port=%d file='%s", p_sys->url.psz_host, p_sys->url.i_port, p_sys->url.psz_path ); if( p_sys->b_proxy ) { msg_Dbg( p_access, " proxy %s:%d", p_sys->proxy.psz_host, p_sys->proxy.i_port ); } if( p_sys->url.psz_username && *p_sys->url.psz_username )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -