📄 http.c
字号:
/***************************************************************************** * http.c : HTTP/HTTPS Remote control interface ***************************************************************************** * Copyright (C) 2001-2006 the VideoLAN team * $Id: http.c 18327 2006-12-08 17:12:19Z md $ * * Authors: Gildas Bazin <gbazin@netcourrier.com> * Laurent Aimar <fenrir@via.ecp.fr> * Christophe Massiot <massiot@via.ecp.fr> * * 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. *****************************************************************************/#include "http.h"/***************************************************************************** * Module descriptor *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );#define HOST_TEXT N_( "Host address" )#define HOST_LONGTEXT N_( \ "Address and port the HTTP interface will listen on. It defaults to " \ "all network interfaces (0.0.0.0)." \ " If you want the HTTP interface to be available only on the local " \ "machine, enter 127.0.0.1" )#define SRC_TEXT N_( "Source directory" )#define SRC_LONGTEXT N_( "Source directory" )#define CHARSET_TEXT N_( "Charset" )#define CHARSET_LONGTEXT N_( \ "Charset declared in Content-Type header (default UTF-8)." )#define HANDLERS_TEXT N_( "Handlers" )#define HANDLERS_LONGTEXT N_( \ "List of handler extensions and executable paths (for instance: " \ "php=/usr/bin/php,pl=/usr/bin/perl)." )#define CERT_TEXT N_( "Certificate file" )#define CERT_LONGTEXT N_( "HTTP interface x509 PEM certificate file " \ "(enables SSL)." )#define KEY_TEXT N_( "Private key file" )#define KEY_LONGTEXT N_( "HTTP interface x509 PEM private key file." )#define CA_TEXT N_( "Root CA file" )#define CA_LONGTEXT N_( "HTTP interface x509 PEM trusted root CA " \ "certificates file." )#define CRL_TEXT N_( "CRL file" )#define CRL_LONGTEXT N_( "HTTP interace Certificates Revocation List file." )vlc_module_begin(); set_shortname( _("HTTP")); set_description( _("HTTP remote control interface") ); set_category( CAT_INTERFACE ); set_subcategory( SUBCAT_INTERFACE_MAIN ); add_string ( "http-host", NULL, NULL, HOST_TEXT, HOST_LONGTEXT, VLC_TRUE ); add_string ( "http-src", NULL, NULL, SRC_TEXT, SRC_LONGTEXT, VLC_TRUE ); add_string ( "http-charset", "UTF-8", NULL, CHARSET_TEXT, CHARSET_LONGTEXT, VLC_TRUE );#if defined( HAVE_FORK ) || defined( WIN32 ) add_string ( "http-handlers", NULL, NULL, HANDLERS_TEXT, HANDLERS_LONGTEXT, VLC_TRUE );#endif set_section( N_("HTTP SSL" ), 0 ); add_string ( "http-intf-cert", NULL, NULL, CERT_TEXT, CERT_LONGTEXT, VLC_TRUE ); add_string ( "http-intf-key", NULL, NULL, KEY_TEXT, KEY_LONGTEXT, VLC_TRUE ); add_string ( "http-intf-ca", NULL, NULL, CA_TEXT, CA_LONGTEXT, VLC_TRUE ); add_string ( "http-intf-crl", NULL, NULL, CRL_TEXT, CRL_LONGTEXT, VLC_TRUE ); set_capability( "interface", 0 ); set_callbacks( Open, Close );vlc_module_end();/***************************************************************************** * Local prototypes *****************************************************************************/static void Run ( intf_thread_t *p_intf );/***************************************************************************** * Local functions *****************************************************************************/#if !defined(__APPLE__) && !defined(SYS_BEOS) && !defined(WIN32)static int DirectoryCheck( const char *psz_dir ){ DIR *p_dir;#ifdef HAVE_SYS_STAT_H struct stat stat_info; if( ( utf8_stat( psz_dir, &stat_info ) == -1 ) || !S_ISDIR( stat_info.st_mode ) ) { return VLC_EGENERIC; }#endif if( ( p_dir = utf8_opendir( psz_dir ) ) == NULL ) { return VLC_EGENERIC; } closedir( p_dir ); return VLC_SUCCESS;}#endif/***************************************************************************** * Activate: initialize and create stuff *****************************************************************************/static int Open( vlc_object_t *p_this ){ intf_thread_t *p_intf = (intf_thread_t*)p_this; intf_sys_t *p_sys; char *psz_address; const char *psz_cert = NULL, *psz_key = NULL, *psz_ca = NULL, *psz_crl = NULL; int i_port = 0; char *psz_src; var_Create( p_intf->p_libvlc, "http-host", VLC_VAR_STRING ); psz_address = var_GetString( p_intf->p_libvlc, "http-host"); if( !psz_address || !*psz_address ) { psz_address = config_GetPsz( p_intf, "http-host" ); } if( psz_address != NULL ) { char *psz_parser = strchr( psz_address, ':' ); if( psz_parser ) { *psz_parser++ = '\0'; i_port = atoi( psz_parser ); } } else psz_address = strdup(""); p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) ); if( !p_intf->p_sys ) { return( VLC_ENOMEM ); } memset( p_intf->p_sys, 0, sizeof( intf_sys_t ) ); p_sys->psz_address = psz_address; p_sys->i_port = i_port; /* determine Content-Type value for HTML pages */ psz_src = config_GetPsz( p_intf, "http-charset" ); if( psz_src == NULL || !*psz_src ) { if( psz_src != NULL ) free( psz_src ); psz_src = strdup("UTF-8"); } p_sys->psz_html_type = malloc( 20 + strlen( psz_src ) ); if( p_sys->psz_html_type == NULL ) { free( p_sys->psz_address ); free( p_sys ); free( psz_src ); return VLC_ENOMEM ; } sprintf( p_sys->psz_html_type, "text/html; charset=%s", psz_src ); msg_Dbg( p_intf, "using charset=%s", psz_src ); if( strcmp( psz_src, "UTF-8" ) ) { char psz_encoding[strlen( psz_src ) + sizeof( "//translit")]; sprintf( psz_encoding, "%s//translit", psz_src); p_sys->iconv_from_utf8 = vlc_iconv_open( psz_encoding, "UTF-8" ); if( p_sys->iconv_from_utf8 == (vlc_iconv_t)-1 ) msg_Warn( p_intf, "unable to perform charset conversion to %s", psz_encoding ); else { p_sys->iconv_to_utf8 = vlc_iconv_open( "UTF-8", psz_src ); if( p_sys->iconv_to_utf8 == (vlc_iconv_t)-1 ) msg_Warn( p_intf, "unable to perform charset conversion from %s", psz_src ); } } else { p_sys->iconv_from_utf8 = p_sys->iconv_to_utf8 = (vlc_iconv_t)-1; } p_sys->psz_charset = psz_src; psz_src = NULL; /* determine file handler associations */ p_sys->i_handlers = 0; p_sys->pp_handlers = NULL;#if defined( HAVE_FORK ) || defined( WIN32 ) psz_src = config_GetPsz( p_intf, "http-handlers" ); if( psz_src != NULL && *psz_src ) { char *p = psz_src; while( p != NULL ) { http_association_t *p_handler; char *psz_ext = p; char *psz_program, *psz_options; p = strchr( p, '=' ); if( p == NULL ) break; *p++ = '\0'; psz_program = p; p = strchr( p, ',' ); if( p != NULL ) *p++ = '\0'; p_handler = malloc( sizeof( http_association_t ) ); p_handler->psz_ext = strdup( psz_ext ); psz_options = E_(FirstWord)( psz_program, psz_program ); p_handler->i_argc = 0; p_handler->ppsz_argv = NULL; TAB_APPEND( p_handler->i_argc, p_handler->ppsz_argv, strdup( psz_program ) ); while( psz_options != NULL && *psz_options ) { char *psz_next = E_(FirstWord)( psz_options, psz_options ); TAB_APPEND( p_handler->i_argc, p_handler->ppsz_argv, strdup( psz_options ) ); psz_options = psz_next; } /* NULL will be appended later on */ TAB_APPEND( p_sys->i_handlers, p_sys->pp_handlers, p_handler ); } } if( psz_src != NULL ) free( psz_src );#endif /* determine SSL configuration */ psz_cert = config_GetPsz( p_intf, "http-intf-cert" ); if ( psz_cert != NULL ) { msg_Dbg( p_intf, "enabling TLS for HTTP interface (cert file: %s)", psz_cert ); psz_key = config_GetPsz( p_intf, "http-intf-key" ); psz_ca = config_GetPsz( p_intf, "http-intf-ca" ); psz_crl = config_GetPsz( p_intf, "http-intf-crl" ); if( i_port <= 0 ) i_port = 8443; } else { if( i_port <= 0 ) i_port= 8080; } msg_Dbg( p_intf, "base %s:%d", psz_address, i_port ); p_sys->p_httpd_host = httpd_TLSHostNew( VLC_OBJECT(p_intf), psz_address, i_port, psz_cert, psz_key, psz_ca, psz_crl ); if( p_sys->p_httpd_host == NULL ) { msg_Err( p_intf, "cannot listen on %s:%d", psz_address, i_port ); free( p_sys->psz_html_type ); free( p_sys->psz_address ); free( p_sys ); return VLC_EGENERIC; } else { char psz_tmp[NI_MAXHOST + 6]; /* Ugly hack to run several HTTP servers on different ports */ snprintf( psz_tmp, sizeof (psz_tmp), "%s:%d", psz_address, i_port + 1 ); var_SetString( p_intf->p_libvlc, "http-host", psz_tmp ); } p_sys->i_files = 0; p_sys->pp_files = NULL;#if defined(__APPLE__) || defined(SYS_BEOS) || defined(WIN32) if ( ( psz_src = config_GetPsz( p_intf, "http-src" )) == NULL ) { char * psz_vlcpath = p_intf->p_libvlc->psz_vlcpath; psz_src = malloc( strlen(psz_vlcpath) + strlen("/share/http" ) + 1 ); if( !psz_src ) return VLC_ENOMEM;#if defined(WIN32) sprintf( psz_src, "%s\\http", psz_vlcpath );#else sprintf( psz_src, "%s/share/http", psz_vlcpath );#endif }#else psz_src = config_GetPsz( p_intf, "http-src" ); if( ( psz_src == NULL ) || ( *psz_src == '\0' ) ) { static char const* ppsz_paths[] = { "share/http", "../share/http", DATA_PATH"/http", NULL }; unsigned i; if( psz_src != NULL ) { free( psz_src ); psz_src = NULL; } for( i = 0; ppsz_paths[i] != NULL; i++ ) if( !DirectoryCheck( ppsz_paths[i] ) ) { psz_src = strdup( ppsz_paths[i] ); break; } }#endif if( !psz_src || *psz_src == '\0' ) { msg_Err( p_intf, "invalid web interface source directory" ); goto failed; } /* remove trainling \ or / */ if( psz_src[strlen( psz_src ) - 1] == '\\' || psz_src[strlen( psz_src ) - 1] == '/' ) { psz_src[strlen( psz_src ) - 1] = '\0'; } E_(ParseDirectory)( p_intf, psz_src, psz_src ); if( p_sys->i_files <= 0 ) { msg_Err( p_intf, "cannot find any file in directory %s", psz_src ); goto failed; } p_intf->pf_run = Run; free( psz_src ); return VLC_SUCCESS;failed: if( psz_src ) free( psz_src ); if( p_sys->pp_files ) { free( p_sys->pp_files ); } httpd_HostDelete( p_sys->p_httpd_host ); free( p_sys->psz_address ); free( p_sys->psz_html_type ); if( p_sys->iconv_from_utf8 != (vlc_iconv_t)-1 ) vlc_iconv_close( p_sys->iconv_from_utf8 ); if( p_sys->iconv_to_utf8 != (vlc_iconv_t)-1 ) vlc_iconv_close( p_sys->iconv_to_utf8 ); free( p_sys ); return VLC_EGENERIC;}/***************************************************************************** * Close: destroy interface *****************************************************************************/static void Close ( vlc_object_t *p_this ){ intf_thread_t *p_intf = (intf_thread_t *)p_this; intf_sys_t *p_sys = p_intf->p_sys; int i; if( p_sys->p_vlm ) { vlm_Delete( p_sys->p_vlm ); } for( i = 0; i < p_sys->i_files; i++ ) { if( p_sys->pp_files[i]->b_handler ) httpd_HandlerDelete( ((httpd_handler_sys_t *)p_sys->pp_files[i])->p_handler ); else httpd_FileDelete( p_sys->pp_files[i]->p_file ); if( p_sys->pp_files[i]->p_redir ) httpd_RedirectDelete( p_sys->pp_files[i]->p_redir ); if( p_sys->pp_files[i]->p_redir2 ) httpd_RedirectDelete( p_sys->pp_files[i]->p_redir2 ); free( p_sys->pp_files[i]->file ); free( p_sys->pp_files[i]->name ); free( p_sys->pp_files[i] ); } if( p_sys->pp_files ) { free( p_sys->pp_files ); } for( i = 0; i < p_sys->i_handlers; i++ ) { http_association_t *p_handler = p_sys->pp_handlers[i]; int j; free( p_handler->psz_ext ); for( j = 0; j < p_handler->i_argc; j++ ) free( p_handler->ppsz_argv[j] ); if( p_handler->i_argc ) free( p_handler->ppsz_argv ); free( p_handler ); } if( p_sys->i_handlers ) free( p_sys->pp_handlers ); httpd_HostDelete( p_sys->p_httpd_host ); free( p_sys->psz_address ); free( p_sys->psz_html_type ); if( p_sys->iconv_from_utf8 != (vlc_iconv_t)-1 ) vlc_iconv_close( p_sys->iconv_from_utf8 ); if( p_sys->iconv_to_utf8 != (vlc_iconv_t)-1 ) vlc_iconv_close( p_sys->iconv_to_utf8 ); free( p_sys );}/***************************************************************************** * Run: http interface thread *****************************************************************************/static void Run( intf_thread_t *p_intf ){ intf_sys_t *p_sys = p_intf->p_sys; while( !p_intf->b_die ) { /* get the playlist */ if( p_sys->p_playlist == NULL ) { p_sys->p_playlist = vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST, FIND_ANYWHERE ); } /* Manage the input part */ if( p_sys->p_input == NULL ) { if( p_sys->p_playlist )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -