]> git.sesse.net Git - vlc/blobdiff - modules/control/http/http.c
Qt4 - Preferences: Add an option and the code needed to start with the advanced prefe...
[vlc] / modules / control / http / http.c
index ed234728e061a9b5a6e7ef32f3e178e976978d12..7835cee35bdc94b74e5ab7fcb34a95a5ef7c8d3a 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * http.c : HTTP/HTTPS Remote control interface
  *****************************************************************************
- * Copyright (C) 2001-2005 the VideoLAN team
+ * Copyright (C) 2001-2006 the VideoLAN team
  * $Id$
  *
  * Authors: Gildas Bazin <gbazin@netcourrier.com>
@@ -20,7 +20,7 @@
  *
  * 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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 #include "http.h"
@@ -33,7 +33,10 @@ static void Close( vlc_object_t * );
 
 #define HOST_TEXT N_( "Host address" )
 #define HOST_LONGTEXT N_( \
-    "You can set the address and port the http interface will bind to." )
+    "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" )
@@ -41,24 +44,24 @@ static void Close( vlc_object_t * );
         "Charset declared in Content-Type header (default UTF-8)." )
 #define HANDLERS_TEXT N_( "Handlers" )
 #define HANDLERS_LONGTEXT N_( \
-        "List of extensions and executable paths (for instance: " \
+        "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)" )
+                          "(enables SSL)." )
 #define KEY_TEXT N_( "Private key file" )
-#define KEY_LONGTEXT N_( "HTTP interface x509 PEM 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" )
+                        "certificates file." )
 #define CRL_TEXT N_( "CRL file" )
-#define CRL_LONGTEXT N_( "HTTP interace Certificates Revocation List 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_GENERAL );
+    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 );
@@ -83,21 +86,22 @@ static void Run          ( intf_thread_t *p_intf );
 /*****************************************************************************
  * Local functions
  *****************************************************************************/
-#if !defined(SYS_DARWIN) && !defined(SYS_BEOS) && !defined(WIN32)
-static int DirectoryCheck( char *psz_dir )
+#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( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) )
+    if( ( utf8_stat( psz_dir, &stat_info ) == -1 )
+      || !S_ISDIR( stat_info.st_mode ) )
     {
         return VLC_EGENERIC;
     }
 #endif
 
-    if( ( p_dir = opendir( psz_dir ) ) == NULL )
+    if( ( p_dir = utf8_opendir( psz_dir ) ) == NULL )
     {
         return VLC_EGENERIC;
     }
@@ -121,7 +125,12 @@ static int Open( vlc_object_t *p_this )
     int           i_port       = 0;
     char          *psz_src;
 
-    psz_address = config_GetPsz( p_intf, "http-host" );
+    var_Create(p_intf->p_libvlc_global, "http-host", VLC_VAR_STRING );
+    psz_address=var_GetString(p_intf->p_libvlc_global, "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, ':' );
@@ -166,10 +175,13 @@ static int Open( vlc_object_t *p_this )
 
     if( strcmp( psz_src, "UTF-8" ) )
     {
-        p_sys->iconv_from_utf8 = vlc_iconv_open( 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_src );
+                      psz_encoding );
         else
         {
             p_sys->iconv_to_utf8 = vlc_iconv_open( "UTF-8", psz_src );
@@ -184,7 +196,8 @@ static int Open( vlc_object_t *p_this )
         p_sys->iconv_from_utf8 = p_sys->iconv_to_utf8 = (vlc_iconv_t)-1;
     }
 
-    free( psz_src );
+    p_sys->psz_charset = psz_src;
+    psz_src = NULL;
 
     /* determine file handler associations */
     p_sys->i_handlers = 0;
@@ -262,14 +275,22 @@ static int Open( vlc_object_t *p_this )
         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_global, "http-host", psz_tmp );
+    }
 
     p_sys->i_files  = 0;
     p_sys->pp_files = NULL;
 
-#if defined(SYS_DARWIN) || defined(SYS_BEOS) || defined(WIN32)
+#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;
+        char * psz_vlcpath = p_intf->p_libvlc_global->psz_vlcpath;
         psz_src = malloc( strlen(psz_vlcpath) + strlen("/share/http" ) + 1 );
         if( !psz_src ) return VLC_ENOMEM;
 #if defined(WIN32)
@@ -281,22 +302,34 @@ static int Open( vlc_object_t *p_this )
 #else
     psz_src = config_GetPsz( p_intf, "http-src" );
 
-    if( !psz_src || *psz_src == '\0' )
+    if( ( psz_src == NULL ) || ( *psz_src == '\0' ) )
     {
-        if( !DirectoryCheck( "share/http" ) )
-        {
-            psz_src = strdup( "share/http" );
-        }
-        else if( !DirectoryCheck( DATA_PATH "/http" ) )
+        static char const* ppsz_paths[] = {
+            "share/http",
+            "../share/http",
+            DATA_PATH"/http",
+            NULL
+        };
+        unsigned i;
+
+        if( psz_src != NULL )
         {
-            psz_src = strdup( DATA_PATH "/http" );
+            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 src dir" );
+        msg_Err( p_intf, "invalid web interface source directory" );
         goto failed;
     }
 
@@ -312,7 +345,7 @@ static int Open( vlc_object_t *p_this )
 
     if( p_sys->i_files <= 0 )
     {
-        msg_Err( p_intf, "cannot find any files (%s)", psz_src );
+        msg_Err( p_intf, "cannot find any file in directory %s", psz_src );
         goto failed;
     }
     p_intf->pf_run = Run;
@@ -328,7 +361,7 @@ failed:
     }
     httpd_HostDelete( p_sys->p_httpd_host );
     free( p_sys->psz_address );
-    free( p_sys->psz_html_type ); 
+    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 )
@@ -401,7 +434,7 @@ static void Run( intf_thread_t *p_intf )
 {
     intf_sys_t     *p_sys = p_intf->p_sys;
 
-    while( !p_intf->b_die )
+    while( !intf_ShouldDie( p_intf ) )
     {
         /* get the playlist */
         if( p_sys->p_playlist == NULL )
@@ -414,15 +447,11 @@ static void Run( intf_thread_t *p_intf )
         {
             if( p_sys->p_playlist )
             {
-                p_sys->p_input =
-                    vlc_object_find( p_sys->p_playlist,
-                                     VLC_OBJECT_INPUT,
-                                     FIND_CHILD );
+                p_sys->p_input = p_sys->p_playlist->p_input;
             }
         }
-        else if( p_sys->p_input->b_dead )
+        else if( p_sys->p_input->b_dead || p_sys->p_input->b_die )
         {
-            vlc_object_release( p_sys->p_input );
             p_sys->p_input = NULL;
         }
 
@@ -457,13 +486,13 @@ static void Callback404( httpd_file_sys_t *p_args, char **pp_data,
     {
         return;
     }
-    p += sprintf( p, "<html>\n" );
+    p += sprintf( p, "Content-Type: text/html\n" );
+    p += sprintf( p, "<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" );
     p += sprintf( p, "<head>\n" );
     p += sprintf( p, "<title>Error loading %s</title>\n", p_args->file );
     p += sprintf( p, "</head>\n" );
     p += sprintf( p, "<body>\n" );
     p += sprintf( p, "<h1><center>Error loading %s for %s</center></h1>\n", p_args->file, p_args->name );
-    p += sprintf( p, "<hr />\n" );
     p += sprintf( p, "<a href=\"http://www.videolan.org/\">VideoLAN</a>\n" );
     p += sprintf( p, "</body>\n" );
     p += sprintf( p, "</html>\n" );
@@ -484,6 +513,7 @@ static void ParseExecute( httpd_file_sys_t *p_args, char *p_buffer,
     audio_volume_t i_volume;
     char volume[5];
     char state[8];
+    char stats[20];
 
 #define p_sys p_args->p_intf->p_sys
     if( p_sys->p_input )
@@ -491,15 +521,23 @@ static void ParseExecute( httpd_file_sys_t *p_args, char *p_buffer,
         var_Get( p_sys->p_input, "position", &val);
         sprintf( position, "%d" , (int)((val.f_float) * 100.0));
         var_Get( p_sys->p_input, "time", &val);
-        sprintf( time, "%d" , (int)(val.i_time / 1000000) );
+        sprintf( time, I64Fi, val.i_time / 1000000LL );
         var_Get( p_sys->p_input, "length", &val);
-        sprintf( length, "%d" , (int)(val.i_time / 1000000) );
+        sprintf( length, I64Fi, val.i_time / 1000000LL );
 
         var_Get( p_sys->p_input, "state", &val );
         if( val.i_int == PLAYING_S )
         {
             sprintf( state, "playing" );
         }
+        else if( val.i_int == OPENING_S )
+        {
+            sprintf( state, "opening/connecting" );
+        }
+        else if( val.i_int == BUFFERING_S )
+        {
+            sprintf( state, "buffering" );
+        }
         else if( val.i_int == PAUSE_S )
         {
             sprintf( state, "paused" );
@@ -533,12 +571,47 @@ static void ParseExecute( httpd_file_sys_t *p_args, char *p_buffer,
     E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_domain",
                            VLC_CompileDomain() );
     E_(mvar_AppendNewVar)( p_args->vars, "vlc_compiler", VLC_Compiler() );
+#ifndef HAVE_SHARED_LIBVLC
     E_(mvar_AppendNewVar)( p_args->vars, "vlc_changeset", VLC_Changeset() );
+#endif
     E_(mvar_AppendNewVar)( p_args->vars, "stream_position", position );
     E_(mvar_AppendNewVar)( p_args->vars, "stream_time", time );
     E_(mvar_AppendNewVar)( p_args->vars, "stream_length", length );
     E_(mvar_AppendNewVar)( p_args->vars, "volume", volume );
     E_(mvar_AppendNewVar)( p_args->vars, "stream_state", state );
+    E_(mvar_AppendNewVar)( p_args->vars, "charset", ((intf_sys_t *)p_args->p_intf->p_sys)->psz_charset );
+
+    /* Stats */
+#define p_sys p_args->p_intf->p_sys
+    if( p_sys->p_input )
+    {
+        input_item_t *p_item = input_GetItem( p_sys->p_input );
+        if( p_item )
+        {
+            vlc_mutex_lock( &p_item->p_stats->lock );
+#define STATS_INT( n ) sprintf( stats, "%d", p_item->p_stats->i_ ## n ); \
+                       E_(mvar_AppendNewVar)( p_args->vars, #n, stats );
+#define STATS_FLOAT( n ) sprintf( stats, "%f", p_item->p_stats->f_ ## n ); \
+                       E_(mvar_AppendNewVar)( p_args->vars, #n, stats );
+            STATS_INT( read_bytes )
+            STATS_FLOAT( input_bitrate )
+            STATS_INT( demux_read_bytes )
+            STATS_FLOAT( demux_bitrate )
+            STATS_INT( decoded_video )
+            STATS_INT( displayed_pictures )
+            STATS_INT( lost_pictures )
+            STATS_INT( decoded_audio )
+            STATS_INT( played_abuffers )
+            STATS_INT( lost_abuffers )
+            STATS_INT( sent_packets )
+            STATS_INT( sent_bytes )
+            STATS_FLOAT( send_bitrate )
+#undef STATS_INT
+#undef STATS_FLOAT
+            vlc_mutex_unlock( &p_item->p_stats->lock );
+        }
+    }
+#undef p_sys
 
     E_(SSInit)( &p_args->stack );
 
@@ -566,7 +639,7 @@ int  E_(HttpCallback)( httpd_file_sys_t *p_args,
     char **pp_data = (char **)_pp_data;
     FILE *f;
 
-    if( ( f = fopen( p_args->file, "r" ) ) == NULL )
+    if( ( f = utf8_fopen( p_args->file, "r" ) ) == NULL )
     {
         Callback404( p_args, pp_data, pi_data );
         return VLC_SUCCESS;
@@ -600,7 +673,7 @@ int  E_(HttpCallback)( httpd_file_sys_t *p_args,
  * call the external handler and parse vlc macros if Content-Type is HTML
  ****************************************************************************/
 int  E_(HandlerCallback)( httpd_handler_sys_t *p_args,
-                          httpd_handler_t *p_handler, uint8_t *_p_url,
+                          httpd_handler_t *p_handler, char *_p_url,
                           uint8_t *_p_request, int i_type,
                           uint8_t *_p_in, int i_in,
                           char *psz_remote_addr, char *psz_remote_host,
@@ -716,7 +789,7 @@ int  E_(HandlerCallback)( httpd_handler_sys_t *p_args,
         p = p_in;
         for ( ; ; )
         {
-            if( !strncmp( p, "Content-Type: ", strlen("Content-Type: ") ) )
+            if( !strncasecmp( p, "Content-Type: ", strlen("Content-Type: ") ) )
             {
                 char *end = strchr( p, '\r' );
                 if( end == NULL )
@@ -727,7 +800,8 @@ int  E_(HandlerCallback)( httpd_handler_sys_t *p_args,
                 TAB_APPEND( i_env, ppsz_env, psz_tmp );
                 *end = '\r';
             }
-            if( !strncmp( p, "Content-Length: ", strlen("Content-Length: ") ) )
+            if( !strncasecmp( p, "Content-Length: ",
+                              strlen("Content-Length: ") ) )
             {
                 char *end = strchr( p, '\r' );
                 if( end == NULL )
@@ -797,8 +871,8 @@ int  E_(HandlerCallback)( httpd_handler_sys_t *p_args,
         return VLC_SUCCESS;
     }
     p = p_buffer;
-    while( strncmp( p, "Content-Type: text/html",
-                    strlen("Content-Type: text/html") ) )
+    while( strncasecmp( p, "Content-Type: text/html",
+                        strlen("Content-Type: text/html") ) )
     {
         p = strchr( p, '\n' );
         if( p == NULL || p[1] == '\r' )