X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fcontrol%2Fhttp.c;h=a923d1140f1a22637f897eceb381fe0787f1e1e4;hb=9fad47dcd802710f621133f4440163d0a345e2d1;hp=b4eb2d952c9efd38c05ab64586b671b0d7e54f56;hpb=1b834a3623fd5f845bc628448337a6e3c3355d96;p=vlc diff --git a/modules/control/http.c b/modules/control/http.c index b4eb2d952c..a923d1140f 100644 --- a/modules/control/http.c +++ b/modules/control/http.c @@ -1,7 +1,7 @@ /***************************************************************************** * http.c : http mini-server ;) ***************************************************************************** - * Copyright (C) 2001-2004 VideoLAN + * Copyright (C) 2001-2005 the VideoLAN team * $Id$ * * Authors: Gildas Bazin @@ -39,6 +39,8 @@ #include "vlc_httpd.h" #include "vlc_vlm.h" +#include "vlc_tls.h" +#include "charset.h" #ifdef HAVE_SYS_STAT_H # include @@ -56,11 +58,15 @@ # include #endif -#if (!defined( WIN32 ) || defined(__MINGW32__)) -/* Mingw has its own version of dirent */ +#ifdef HAVE_DIRENT_H # include #endif +/* stat() support for large files on win32 */ +#if defined( WIN32 ) && !defined( UNDER_CE ) +# define stat _stati64 +#endif + /***************************************************************************** * Module descriptor *****************************************************************************/ @@ -72,11 +78,29 @@ static void Close( vlc_object_t * ); "You can set the address and port the http interface will bind to." ) #define SRC_TEXT N_( "Source directory" ) #define SRC_LONGTEXT N_( "Source directory" ) +#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_GENERAL ); add_string ( "http-host", NULL, NULL, HOST_TEXT, HOST_LONGTEXT, VLC_TRUE ); add_string ( "http-src", NULL, NULL, SRC_TEXT, SRC_LONGTEXT, VLC_TRUE ); + 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(); @@ -124,8 +148,7 @@ static int uri_test_param( char *psz_uri, const char *psz_name ); static void uri_decode_url_encoded( char *psz ); static char *Find_end_MRL( char *psz ); - -static playlist_item_t * parse_MRL( intf_thread_t * , char *psz ); +static playlist_item_t *parse_MRL( intf_thread_t * , char *psz ); /***************************************************************************** * @@ -151,6 +174,7 @@ struct httpd_file_sys_t intf_thread_t *p_intf; httpd_file_t *p_file; httpd_redirect_t *p_redir; + httpd_redirect_t *p_redir2; char *file; char *name; @@ -172,6 +196,7 @@ struct intf_sys_t playlist_t *p_playlist; input_thread_t *p_input; vlm_t *p_vlm; + char *psz_html_type; }; @@ -185,6 +210,8 @@ static int Open( vlc_object_t *p_this ) intf_sys_t *p_sys; char *psz_host; char *psz_address = ""; + const char *psz_cert = NULL, *psz_key = NULL, *psz_ca = NULL, + *psz_crl = NULL; int i_port = 0; char *psz_src; @@ -201,12 +228,7 @@ static int Open( vlc_object_t *p_this ) i_port = atoi( psz_parser ); } } - if( i_port <= 0 ) - { - i_port= 8080; - } - msg_Dbg( p_intf, "base %s:%d", psz_address, i_port ); p_intf->p_sys = p_sys = malloc( sizeof( intf_sys_t ) ); if( !p_intf->p_sys ) { @@ -216,10 +238,51 @@ static int Open( vlc_object_t *p_this ) p_sys->p_input = NULL; p_sys->p_vlm = NULL; - p_sys->p_httpd_host = httpd_HostNew( VLC_OBJECT(p_intf), psz_address, i_port ); + /* determine Content-Type value for HTML pages */ + vlc_current_charset(&psz_src); + if( psz_src == NULL ) + { + free( p_sys ); + return VLC_ENOMEM; + } + p_sys->psz_html_type = malloc( 20 + strlen( psz_src ) ); + if( p_sys->psz_html_type == NULL ) + { + free( p_sys ); + free( psz_src ); + return VLC_ENOMEM ; + } + sprintf( p_sys->psz_html_type, "text/html; charset=%s", psz_src ); + free( psz_src ); + + /* determine SSL configuration */ + psz_cert = config_GetPsz( p_intf, "http-intf-cert" ); + if ( psz_cert != NULL ) + { + msg_Dbg( p_intf, "enablind 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 ); return VLC_EGENERIC; } @@ -232,16 +295,12 @@ static int Open( vlc_object_t *p_this ) p_sys->i_files = 0; p_sys->pp_files = NULL; -#if defined(SYS_DARWIN) || defined(SYS_BEOS) || \ - ( defined(WIN32) && !defined(UNDER_CE ) ) +#if defined(SYS_DARWIN) || 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( !psz_src ) return VLC_ENOMEM; #if defined(WIN32) sprintf( psz_src, "%s/http", psz_vlcpath); #else @@ -297,6 +356,7 @@ failed: free( p_sys->pp_files ); } httpd_HostDelete( p_sys->p_httpd_host ); + free( p_sys->psz_html_type ); free( p_sys ); return VLC_EGENERIC; } @@ -315,14 +375,13 @@ void Close ( vlc_object_t *p_this ) { vlm_Delete( p_sys->p_vlm ); } - for( i = 0; i < p_sys->i_files; i++ ) { 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 ); @@ -334,6 +393,7 @@ void Close ( vlc_object_t *p_this ) } httpd_HostDelete( p_sys->p_httpd_host ); + free( p_sys->psz_html_type ); free( p_sys ); } @@ -396,12 +456,13 @@ static void Run( intf_thread_t *p_intf ) /**************************************************************************** * FileToUrl: create a good name for an url from filename ****************************************************************************/ -static char *FileToUrl( char *name ) +static char *FileToUrl( char *name, vlc_bool_t *pb_index ) { char *url, *p; url = p = malloc( strlen( name ) + 1 ); + *pb_index = VLC_FALSE; if( !url || !p ) { return NULL; @@ -438,6 +499,7 @@ static char *FileToUrl( char *name ) if( !strncmp( p, "/index.", 7 ) ) { p[1] = '\0'; + *pb_index = VLC_TRUE; } } return url; @@ -460,6 +522,10 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, char *user = NULL; char *password = NULL; + char **ppsz_hosts = NULL; + int i_hosts = 0; + + int i, i_dirlen; #ifdef HAVE_SYS_STAT_H if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) ) @@ -474,6 +540,13 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, return VLC_EGENERIC; } + i_dirlen = strlen( psz_dir ); + if( i_dirlen + 10 > MAX_DIR_SIZE ) + { + msg_Warn( p_intf, "skipping too deep dir (%s)", psz_dir ); + return 0; + } + msg_Dbg( p_intf, "dir=%s", psz_dir ); sprintf( dir, "%s/.access", psz_dir ); @@ -510,6 +583,43 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, fclose( file ); } + sprintf( dir, "%s/.hosts", psz_dir ); + if( ( file = fopen( dir, "r" ) ) != NULL ) + { + char line[1024]; + int i_size; + + msg_Dbg( p_intf, "find .hosts in dir=%s", psz_dir ); + + while( !feof( file ) ) + { + fgets( line, 1023, file ); + i_size = strlen(line); + if( i_size > 0 && line[0] != '#' ) + { + while( i_size > 0 && ( line[i_size-1] == '\n' || + line[i_size-1] == '\r' ) ) + { + i_size--; + } + if( !i_size ) continue; + + line[i_size] = '\0'; + + msg_Dbg( p_intf, "restricted to %s (read=%d)", + line, i_size ); + TAB_APPEND( i_hosts, ppsz_hosts, strdup( line ) ); + } + } + + fclose( file ); + + if( net_CheckIP( p_intf, "0.0.0.0", ppsz_hosts, i_hosts ) < 0 ) + { + msg_Err( p_intf, ".hosts file is invalid in dir=%s", psz_dir ); + } + } + for( ;; ) { /* parse psz_src dir */ @@ -518,20 +628,22 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, break; } - if( p_dir_content->d_name[0] == '.' ) - { + if( ( p_dir_content->d_name[0] == '.' ) + || ( i_dirlen + strlen( p_dir_content->d_name ) > MAX_DIR_SIZE ) ) continue; - } + sprintf( dir, "%s/%s", psz_dir, p_dir_content->d_name ); if( ParseDirectory( p_intf, psz_root, dir ) ) { httpd_file_sys_t *f = malloc( sizeof( httpd_file_sys_t ) ); + vlc_bool_t b_index; f->p_intf = p_intf; f->p_file = NULL; f->p_redir = NULL; + f->p_redir2 = NULL; f->file = strdup( dir ); - f->name = FileToUrl( &dir[strlen( psz_root )] ); + f->name = FileToUrl( &dir[strlen( psz_root )], &b_index ); f->b_html = strstr( &dir[strlen( psz_root )], ".htm" ) ? VLC_TRUE : VLC_FALSE; if( !f->name ) @@ -545,23 +657,38 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, f->file, f->name ); f->p_file = httpd_FileNew( p_sys->p_httpd_host, - f->name, f->b_html ? "text/html" : NULL, - user, password, + f->name, + f->b_html ? p_sys->psz_html_type : NULL, + user, password, ppsz_hosts, i_hosts, HttpCallback, f ); if( f->p_file ) { TAB_APPEND( p_sys->i_files, p_sys->pp_files, f ); } - /* For rep/ add a redir from rep to rep/ */ + /* for url that ends by / add + * - a redirect from rep to rep/ + * - in case of index.* rep/index.html to rep/ */ if( f && f->name[strlen(f->name) - 1] == '/' ) { char *psz_redir = strdup( f->name ); + char *p; psz_redir[strlen( psz_redir ) - 1] = '\0'; msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name ); f->p_redir = httpd_RedirectNew( p_sys->p_httpd_host, f->name, psz_redir ); free( psz_redir ); + + if( b_index && ( p = strstr( f->file, "index." ) ) ) + { + asprintf( &psz_redir, "%s%s", f->name, p ); + + msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name ); + f->p_redir2 = httpd_RedirectNew( p_sys->p_httpd_host, + f->name, psz_redir ); + + free( psz_redir ); + } } } } @@ -574,6 +701,10 @@ static int ParseDirectory( intf_thread_t *p_intf, char *psz_root, { free( password ); } + for( i = 0; i < i_hosts; i++ ) + { + TAB_REMOVE( i_hosts, ppsz_hosts, ppsz_hosts[0] ); + } closedir( p_dir ); @@ -770,7 +901,6 @@ static mvar_t *mvar_IntegerSetNew( char *name, char *arg ) char *str = dup; mvar_t *s = mvar_New( name, "set" ); - fprintf( stderr," mvar_IntegerSetNew: name=`%s' arg=`%s'\n", name, str ); while( str ) { @@ -786,7 +916,6 @@ static mvar_t *mvar_IntegerSetNew( char *name, char *arg ) i_step = 0; i_match = sscanf( str, "%d:%d:%d", &i_start, &i_stop, &i_step ); - fprintf( stderr," mvar_IntegerSetNew: m=%d start=%d stop=%d step=%d\n", i_match, i_start, i_stop, i_step ); if( i_match == 1 ) { @@ -802,12 +931,12 @@ static mvar_t *mvar_IntegerSetNew( char *name, char *arg ) { int i; - if( ( i_start < i_stop && i_step > 0 ) || - ( i_start > i_stop && i_step < 0 ) ) + if( ( i_start <= i_stop && i_step > 0 ) || + ( i_start >= i_stop && i_step < 0 ) ) { for( i = i_start; ; i += i_step ) { - char value[512]; + char value[79]; if( ( i_step > 0 && i > i_stop ) || ( i_step < 0 && i < i_stop ) ) @@ -815,7 +944,6 @@ static mvar_t *mvar_IntegerSetNew( char *name, char *arg ) break; } - fprintf( stderr," mvar_IntegerSetNew: adding %d\n", i ); sprintf( value, "%d", i ); mvar_PushNewVar( s, name, value ); @@ -829,34 +957,77 @@ static mvar_t *mvar_IntegerSetNew( char *name, char *arg ) return s; } -static mvar_t *mvar_PlaylistSetNew( char *name, playlist_t *p_pl ) +void PlaylistListNode( playlist_t *p_pl, playlist_item_t *p_node, + char *name, mvar_t *s, int i_depth ) { - mvar_t *s = mvar_New( name, "set" ); - int i; + if( p_node != NULL ) + { + if (p_node->i_children == -1) + { + char value[512]; + mvar_t *itm = mvar_New( name, "set" ); - fprintf( stderr," mvar_PlaylistSetNew: name=`%s'\n", name ); + sprintf( value, "%d", ( p_pl->status.p_item == p_node )? 1 : 0 ); + mvar_AppendNewVar( itm, "current", value ); - vlc_mutex_lock( &p_pl->object_lock ); - for( i = 0; i < p_pl->i_size; i++ ) - { - mvar_t *itm = mvar_New( name, "set" ); - char value[512]; + sprintf( value, "%d", p_node->input.i_id ); + mvar_AppendNewVar( itm, "index", value ); + + mvar_AppendNewVar( itm, "name", p_node->input.psz_name ); - sprintf( value, "%d", i == p_pl->i_index ? 1 : 0 ); - mvar_AppendNewVar( itm, "current", value ); + mvar_AppendNewVar( itm, "uri", p_node->input.psz_uri ); - sprintf( value, "%d", i ); - mvar_AppendNewVar( itm, "index", value ); + sprintf( value, "Item"); + mvar_AppendNewVar( itm, "type", value ); - mvar_AppendNewVar( itm, "name", p_pl->pp_items[i]->input.psz_name ); + sprintf( value, "%d", i_depth ); + mvar_AppendNewVar( itm, "depth", value ); - mvar_AppendNewVar( itm, "uri", p_pl->pp_items[i]->input.psz_uri ); + mvar_AppendVar( s, itm ); + } + else + { + char value[512]; + int i_child; + mvar_t *itm = mvar_New( name, "set" ); + + mvar_AppendNewVar( itm, "name", p_node->input.psz_name ); + mvar_AppendNewVar( itm, "uri", p_node->input.psz_name ); + + sprintf( value, "Node" ); + mvar_AppendNewVar( itm, "type", value ); + + sprintf( value, "%d", p_node->input.i_id ); + mvar_AppendNewVar( itm, "index", value ); + + sprintf( value, "%d", p_node->i_children); + mvar_AppendNewVar( itm, "i_children", value ); + + sprintf( value, "%d", i_depth ); + mvar_AppendNewVar( itm, "depth", value ); - sprintf( value, "%d", p_pl->pp_items[i]->i_group ); - mvar_AppendNewVar( itm, "group", value ); + mvar_AppendVar( s, itm ); - mvar_AppendVar( s, itm ); + for (i_child = 0 ; i_child < p_node->i_children ; i_child++) + PlaylistListNode( p_pl, p_node->pp_children[i_child], name, s, i_depth + 1); + + } } +} + +static mvar_t *mvar_PlaylistSetNew( char *name, playlist_t *p_pl ) +{ + playlist_view_t *p_view; + mvar_t *s = mvar_New( name, "set" ); + + + vlc_mutex_lock( &p_pl->object_lock ); + + p_view = playlist_ViewFind( p_pl, VIEW_CATEGORY ); /* FIXME */ + + if( p_view != NULL ) + PlaylistListNode( p_pl, p_view->p_root, name, s, 0 ); + vlc_mutex_unlock( &p_pl->object_lock ); return s; @@ -867,7 +1038,6 @@ static mvar_t *mvar_InfoSetNew( char *name, input_thread_t *p_input ) mvar_t *s = mvar_New( name, "set" ); int i, j; - fprintf( stderr," mvar_InfoSetNew: name=`%s'\n", name ); if( p_input == NULL ) { return s; @@ -907,7 +1077,6 @@ static mvar_t *mvar_HttpdInfoSetNew( char *name, httpd_t *p_httpd, int i_type ) httpd_info_t info; int i; - fprintf( stderr," mvar_HttpdInfoSetNew: name=`%s'\n", name ); if( !p_httpd->pf_control( p_httpd, i_type, &info, NULL ) ) { for( i= 0; i < info.i_count; ) @@ -1029,7 +1198,6 @@ static mvar_t *mvar_FileSetNew( char *name, char *psz_dir ) } *p = '\0'; - fprintf( stderr," mvar_FileSetNew: name=`%s' dir=`%s'\n", name, psz_dir ); #ifdef HAVE_SYS_STAT_H if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) ) @@ -1045,7 +1213,8 @@ static mvar_t *mvar_FileSetNew( char *name, char *psz_dir ) } /* remove traling / or \ */ - for( p = &psz_dir[strlen( psz_dir) - 1]; p >= psz_dir && ( *p =='/' || *p =='\\' ); p-- ) + for( p = &psz_dir[strlen( psz_dir) - 1]; + p >= psz_dir && ( *p =='/' || *p =='\\' ); p-- ) { *p = '\0'; } @@ -1064,11 +1233,7 @@ static mvar_t *mvar_FileSetNew( char *name, char *psz_dir ) continue; } -#if defined( WIN32 ) - sprintf( tmp, "%s\\%s", psz_dir, p_dir_content->d_name ); -#else sprintf( tmp, "%s/%s", psz_dir, p_dir_content->d_name ); -#endif #ifdef HAVE_SYS_STAT_H if( stat( tmp, &stat_info ) == -1 ) @@ -1078,6 +1243,7 @@ static mvar_t *mvar_FileSetNew( char *name, char *psz_dir ) #endif f = mvar_New( name, "set" ); mvar_AppendNewVar( f, "name", tmp ); + #ifdef HAVE_SYS_STAT_H if( S_ISDIR( stat_info.st_mode ) ) { @@ -1092,7 +1258,7 @@ static mvar_t *mvar_FileSetNew( char *name, char *psz_dir ) mvar_AppendNewVar( f, "type", "unknown" ); } - sprintf( tmp, "%lld", stat_info.st_size ); + sprintf( tmp, I64Fd, (int64_t)stat_info.st_size ); mvar_AppendNewVar( f, "size", tmp ); /* FIXME memory leak FIXME */ @@ -1120,9 +1286,8 @@ static mvar_t *mvar_VlmSetNew( char *name, vlm_t *vlm ) vlm_message_t *msg; int i; - /* fprintf( stderr," mvar_VlmSetNew: name=`%s'\n", name ); */ - if( vlm == NULL ) - return s; + if( vlm == NULL ) return s; + if( vlm_ExecuteCommand( vlm, "show", &msg ) ) { return s; @@ -1152,8 +1317,6 @@ static mvar_t *mvar_VlmSetNew( char *name, vlm_t *vlm ) set = mvar_New( name, "set" ); mvar_AppendNewVar( set, "name", el->psz_name ); - /* fprintf( stderr, "#### name=%s\n", el->psz_name ); */ - for( k = 0; k < desc->i_child; k++ ) { vlm_message_t *ch = desc->child[k]; @@ -1162,19 +1325,22 @@ static mvar_t *mvar_VlmSetNew( char *name, vlm_t *vlm ) int c; mvar_t *n = mvar_New( ch->psz_name, "set" ); - /* fprintf( stderr, " child=%s [%d]\n", ch->psz_name, ch->i_child ); */ for( c = 0; c < ch->i_child; c++ ) { - mvar_t *in = mvar_New( ch->psz_name, ch->child[c]->psz_name ); - mvar_AppendVar( n, in ); - - /* fprintf( stderr, " sub=%s\n", ch->child[c]->psz_name );*/ + if( ch->child[c]->psz_value ) + { + mvar_AppendNewVar( n, ch->child[c]->psz_name, ch->child[c]->psz_value ); + } + else + { + mvar_t *in = mvar_New( ch->psz_name, ch->child[c]->psz_name ); + mvar_AppendVar( n, in ); + } } mvar_AppendVar( set, n ); } else { - /* fprintf( stderr, " child=%s->%s\n", ch->psz_name, ch->psz_value ); */ mvar_AppendNewVar( set, ch->psz_name, ch->psz_value ); } } @@ -1210,7 +1376,7 @@ typedef struct char *param2; } macro_t; -static int FileLoad( FILE *f, uint8_t **pp_data, int *pi_data ) +static int FileLoad( FILE *f, char **pp_data, int *pi_data ) { int i_read; @@ -1231,11 +1397,11 @@ static int FileLoad( FILE *f, uint8_t **pp_data, int *pi_data ) return VLC_SUCCESS; } -static int MacroParse( macro_t *m, uint8_t *psz_src ) +static int MacroParse( macro_t *m, char *psz_src ) { - uint8_t *dup = strdup( psz_src ); - uint8_t *src = dup; - uint8_t *p; + char *dup = strdup( (char *)psz_src ); + char *src = dup; + char *p; int i_skip; #define EXTRACT( name, l ) \ @@ -1353,6 +1519,7 @@ enum macroType MVLC_FOREACH, MVLC_IF, MVLC_RPN, + MVLC_STACK, MVLC_ELSE, MVLC_END, MVLC_GET, @@ -1406,6 +1573,7 @@ StrToMacroTypeTab [] = { "vlm_save", MVLC_VLM_SAVE }, { "rpn", MVLC_RPN }, + { "stack", MVLC_STACK }, { "foreach", MVLC_FOREACH }, { "value", MVLC_VALUE }, @@ -1443,9 +1611,9 @@ static int StrToMacroType( char *name ) static void MacroDo( httpd_file_sys_t *p_args, macro_t *m, - uint8_t *p_request, int i_request, - uint8_t **pp_data, int *pi_data, - uint8_t **pp_dst ) + char *p_request, int i_request, + char **pp_data, int *pi_data, + char **pp_dst ) { intf_thread_t *p_intf = p_args->p_intf; intf_sys_t *p_sys = p_args->p_intf->p_sys; @@ -1498,26 +1666,26 @@ static void MacroDo( httpd_file_sys_t *p_args, uri_extract_value( p_request, "item", item, 512 ); i_item = atoi( item ); - playlist_Command( p_sys->p_playlist, PLAYLIST_GOTO, i_item ); + playlist_Control( p_sys->p_playlist, PLAYLIST_ITEMPLAY, + playlist_ItemGetById( p_sys->p_playlist, + i_item ) ); msg_Dbg( p_intf, "requested playlist item: %i", i_item ); break; } case MVLC_STOP: - playlist_Command( p_sys->p_playlist, PLAYLIST_STOP, 0 ); + playlist_Control( p_sys->p_playlist, PLAYLIST_STOP); msg_Dbg( p_intf, "requested playlist stop" ); break; case MVLC_PAUSE: - playlist_Command( p_sys->p_playlist, PLAYLIST_PAUSE, 0 ); + playlist_Control( p_sys->p_playlist, PLAYLIST_PAUSE ); msg_Dbg( p_intf, "requested playlist pause" ); break; case MVLC_NEXT: - playlist_Command( p_sys->p_playlist, PLAYLIST_GOTO, - p_sys->p_playlist->i_index + 1 ); + playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, 1 ); msg_Dbg( p_intf, "requested playlist next" ); break; case MVLC_PREVIOUS: - playlist_Command( p_sys->p_playlist, PLAYLIST_GOTO, - p_sys->p_playlist->i_index - 1 ); + playlist_Control( p_sys->p_playlist, PLAYLIST_SKIP, -1); msg_Dbg( p_intf, "requested playlist next" ); break; case MVLC_FULLSCREEN: @@ -1549,9 +1717,9 @@ static void MacroDo( httpd_file_sys_t *p_args, #define POSITION_ABSOLUTE 12 #define POSITION_REL_FOR 13 #define POSITION_REL_BACK 11 -#define TIME_ABSOLUTE 0 -#define TIME_REL_FOR 1 -#define TIME_REL_BACK -1 +#define VL_TIME_ABSOLUTE 0 +#define VL_TIME_REL_FOR 1 +#define VL_TIME_REL_BACK -1 if( p_sys->p_input ) { uri_extract_value( p_request, "seek_value", value, 20 ); @@ -1566,13 +1734,13 @@ static void MacroDo( httpd_file_sys_t *p_args, { case '+': { - i_relative = TIME_REL_FOR; + i_relative = VL_TIME_REL_FOR; p_value++; break; } case '-': { - i_relative = TIME_REL_BACK; + i_relative = VL_TIME_REL_BACK; p_value++; break; } @@ -1642,7 +1810,7 @@ static void MacroDo( httpd_file_sys_t *p_args, switch(i_relative) { - case TIME_ABSOLUTE: + case VL_TIME_ABSOLUTE: { if( (uint64_t)( i_value ) * 1000000 <= i_length ) val.i_time = (uint64_t)( i_value ) * 1000000; @@ -1653,7 +1821,7 @@ static void MacroDo( httpd_file_sys_t *p_args, msg_Dbg( p_intf, "requested seek position: %dsec", i_value ); break; } - case TIME_REL_FOR: + case VL_TIME_REL_FOR: { var_Get( p_sys->p_input, "time", &val ); if( (uint64_t)( i_value ) * 1000000 + val.i_time <= i_length ) @@ -1667,7 +1835,7 @@ static void MacroDo( httpd_file_sys_t *p_args, msg_Dbg( p_intf, "requested seek position forward: %dsec", i_value ); break; } - case TIME_REL_BACK: + case VL_TIME_REL_BACK: { var_Get( p_sys->p_input, "time", &val ); if( (int64_t)( i_value ) * 1000000 > val.i_time ) @@ -1714,9 +1882,9 @@ static void MacroDo( httpd_file_sys_t *p_args, #undef POSITION_ABSOLUTE #undef POSITION_REL_FOR #undef POSITION_REL_BACK -#undef TIME_ABSOLUTE -#undef TIME_REL_FOR -#undef TIME_REL_BACK +#undef VL_TIME_ABSOLUTE +#undef VL_TIME_REL_FOR +#undef VL_TIME_REL_BACK break; } case MVLC_VOLUME: @@ -1755,6 +1923,14 @@ static void MacroDo( httpd_file_sys_t *p_args, msg_Dbg( p_intf, "requested volume set: -%i", (i_volume - i_value) ); } } else + if( strstr(vol, "%") != NULL ) + { + i_value = atoi( vol ); + if( (i_value <= 100) && (i_value>=0) ){ + aout_VolumeSet( p_intf, (i_value * (AOUT_VOLUME_MAX - AOUT_VOLUME_MIN))/100+AOUT_VOLUME_MIN); + msg_Dbg( p_intf, "requested volume set: %i%%", atoi( vol )); + } + } else { i_value = atoi( vol ); if( ( i_value <= AOUT_VOLUME_MAX ) && ( i_value >= AOUT_VOLUME_MIN ) ) @@ -1807,24 +1983,15 @@ static void MacroDo( httpd_file_sys_t *p_args, i_nb_items++; } - /* The items need to be deleted from in reversed order */ if( i_nb_items ) { int i; for( i = 0; i < i_nb_items; i++ ) { - int j, i_index = 0; - for( j = 0; j < i_nb_items; j++ ) - { - if( p_items[j] > p_items[i_index] ) - i_index = j; - } - - playlist_Delete( p_sys->p_playlist, - p_items[i_index] ); + playlist_LockDelete( p_sys->p_playlist, p_items[i] ); msg_Dbg( p_intf, "requested playlist delete: %d", - p_items[i_index] ); - p_items[i_index] = -1; + p_items[i] ); + p_items[i] = -1; } } @@ -1850,17 +2017,17 @@ static void MacroDo( httpd_file_sys_t *p_args, i_nb_items++; } - /* The items need to be deleted from in reversed order */ - for( i = p_sys->p_playlist->i_size - 1; i >= 0 ; i-- ) + for( i = p_sys->p_playlist->i_size - 1 ; i >= 0; i-- ) { /* Check if the item is in the keep list */ for( j = 0 ; j < i_nb_items ; j++ ) { - if( p_items[j] == i ) break; + if( p_items[j] == + p_sys->p_playlist->pp_items[i]->input.i_id ) break; } if( j == i_nb_items ) { - playlist_Delete( p_sys->p_playlist, i ); + playlist_LockDelete( p_sys->p_playlist, p_sys->p_playlist->pp_items[i]->input.i_id ); msg_Dbg( p_intf, "requested playlist delete: %d", i ); } @@ -1871,10 +2038,7 @@ static void MacroDo( httpd_file_sys_t *p_args, } case MVLC_EMPTY: { - while( p_sys->p_playlist->i_size > 0 ) - { - playlist_Delete( p_sys->p_playlist, 0 ); - } + playlist_LockClear( p_sys->p_playlist ); msg_Dbg( p_intf, "requested playlist empty" ); break; } @@ -1882,31 +2046,40 @@ static void MacroDo( httpd_file_sys_t *p_args, { char type[12]; char order[2]; + char item[512]; int i_order; + int i_item; uri_extract_value( p_request, "type", type, 12 ); uri_extract_value( p_request, "order", order, 2 ); + uri_extract_value( p_request, "item", item, 512 ); + i_item = atoi( item ); if( order[0] == '0' ) i_order = ORDER_NORMAL; else i_order = ORDER_REVERSE; if( !strcmp( type , "title" ) ) { - playlist_SortTitle( p_sys->p_playlist , i_order ); + playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ + p_sys->p_playlist->pp_views[0]->p_root, + SORT_TITLE_NODES_FIRST, + ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist sort by title (%d)" , i_order ); - } else if( !strcmp( type , "group" ) ) - { - playlist_SortGroup( p_sys->p_playlist , i_order ); - msg_Dbg( p_intf, "requested playlist sort by group (%d)" , i_order ); } else if( !strcmp( type , "author" ) ) { - playlist_SortAuthor( p_sys->p_playlist , i_order ); + playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ + p_sys->p_playlist->pp_views[0]->p_root, + SORT_AUTHOR, + ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist sort by author (%d)" , i_order ); } else if( !strcmp( type , "shuffle" ) ) { - playlist_Sort( p_sys->p_playlist , SORT_RANDOM, ORDER_NORMAL ); + playlist_RecursiveNodeSort( p_sys->p_playlist, /*playlist_ItemGetById( p_sys->p_playlist, i_item ),*/ + p_sys->p_playlist->pp_views[0]->p_root, + SORT_RANDOM, + ( i_order == 0 ) ? ORDER_NORMAL : ORDER_REVERSE ); msg_Dbg( p_intf, "requested playlist shuffle"); - } + } break; } @@ -1971,6 +2144,8 @@ static void MacroDo( httpd_file_sys_t *p_args, if( p_intf->p_sys->p_vlm == NULL ) p_intf->p_sys->p_vlm = vlm_New( p_intf ); + if( p_intf->p_sys->p_vlm == NULL ) break; + uri_extract_value( p_request, "name", name, 512 ); if( StrToMacroType( control ) == MVLC_VLM_NEW ) { @@ -1997,7 +2172,6 @@ static void MacroDo( httpd_file_sys_t *p_args, p += sprintf( p, " %s", vlm_properties[i] ); } } - fprintf( stderr, "vlm_ExecuteCommand: %s\n", psz ); vlm_ExecuteCommand( p_intf->p_sys->p_vlm, psz, &vlm_answer ); if( vlm_answer->psz_value == NULL ) /* there is no error */ { @@ -2028,6 +2202,8 @@ static void MacroDo( httpd_file_sys_t *p_args, if( p_intf->p_sys->p_vlm == NULL ) p_intf->p_sys->p_vlm = vlm_New( p_intf ); + if( p_intf->p_sys->p_vlm == NULL ) break; + uri_extract_value( p_request, "name", name, 512 ); sprintf( psz, "del %s", name ); @@ -2048,6 +2224,8 @@ static void MacroDo( httpd_file_sys_t *p_args, if( p_intf->p_sys->p_vlm == NULL ) p_intf->p_sys->p_vlm = vlm_New( p_intf ); + if( p_intf->p_sys->p_vlm == NULL ) break; + uri_extract_value( p_request, "name", name, 512 ); if( StrToMacroType( control ) == MVLC_VLM_PLAY ) sprintf( psz, "control %s play", name ); @@ -2077,6 +2255,8 @@ static void MacroDo( httpd_file_sys_t *p_args, if( p_intf->p_sys->p_vlm == NULL ) p_intf->p_sys->p_vlm = vlm_New( p_intf ); + if( p_intf->p_sys->p_vlm == NULL ) break; + uri_extract_value( p_request, "file", file, 512 ); uri_decode_url_encoded( file ); @@ -2149,7 +2329,7 @@ static void MacroDo( httpd_file_sys_t *p_args, { case MVLC_INT: i = config_GetInt( p_intf, m->param1 ); - sprintf( value, "%i", i ); + sprintf( value, "%d", i ); break; case MVLC_FLOAT: f = config_GetFloat( p_intf, m->param1 ); @@ -2157,13 +2337,15 @@ static void MacroDo( httpd_file_sys_t *p_args, break; case MVLC_STRING: psz = config_GetPsz( p_intf, m->param1 ); - sprintf( value, "%s", psz ? psz : "" ); + snprintf( value, sizeof( value ), "%s", psz ? psz : "" ); if( psz ) free( psz ); break; default: - sprintf( value, "invalid type(%s) in set", m->param2 ); + snprintf( value, sizeof( value ), + "invalid type(%s) in set", m->param2 ); break; } + value[sizeof( value ) - 1] = '\0'; msg_Dbg( p_intf, "get name=%s value=%s type=%s", m->param1, value, m->param2 ); PRINTS( "%s", value ); break; @@ -2191,6 +2373,16 @@ static void MacroDo( httpd_file_sys_t *p_args, EvaluateRPN( p_args->vars, &p_args->stack, m->param1 ); break; +/* Usefull for learning stack management */ + case MVLC_STACK: + { + int i; + msg_Dbg( p_intf, "stack" ); + for (i=0;i<(&p_args->stack)->i_stack;i++) + msg_Dbg( p_intf, "%d -> %s", i, (&p_args->stack)->stack[i] ); + break; + } + case MVLC_UNKNOWN: default: PRINTS( "", m->id ); @@ -2202,14 +2394,14 @@ static void MacroDo( httpd_file_sys_t *p_args, #undef ALLOC } -static uint8_t *MacroSearch( uint8_t *src, uint8_t *end, int i_mvlc, vlc_bool_t b_after ) +static char *MacroSearch( char *src, char *end, int i_mvlc, vlc_bool_t b_after ) { int i_id; int i_level = 0; while( src < end ) { - if( src + 4 < end && !strncmp( src, "p_intf; - uint8_t *src, *dup, *end; - uint8_t *dst = *pp_dst; + char *src, *dup, *end; + char *dst = *pp_dst; src = dup = malloc( _end - _src + 1 ); end = src +( _end - _src ); @@ -2274,10 +2466,10 @@ static void Execute( httpd_file_sys_t *p_args, /* we parse searching vars, &p_args->stack, m.param1 ); if( SSPopN( &p_args->stack, p_args->vars ) ) @@ -2306,11 +2498,11 @@ static void Execute( httpd_file_sys_t *p_args, if( i_test == 0 ) { - uint8_t *start = MacroSearch( src, endif, MVLC_ELSE, VLC_TRUE ); + char *start = MacroSearch( src, endif, MVLC_ELSE, VLC_TRUE ); if( start ) { - uint8_t *stop = MacroSearch( start, endif, MVLC_END, VLC_FALSE ); + char *stop = MacroSearch( start, endif, MVLC_END, VLC_FALSE ); if( stop ) { Execute( p_args, p_request, i_request, pp_data, pi_data, &dst, start, stop ); @@ -2319,7 +2511,7 @@ static void Execute( httpd_file_sys_t *p_args, } else if( i_test == 1 ) { - uint8_t *stop; + char *stop; if( ( stop = MacroSearch( src, endif, MVLC_ELSE, VLC_FALSE ) ) == NULL ) { stop = MacroSearch( src, endif, MVLC_END, VLC_FALSE ); @@ -2335,9 +2527,9 @@ static void Execute( httpd_file_sys_t *p_args, } case MVLC_FOREACH: { - uint8_t *endfor = MacroSearch( src, end, MVLC_END, VLC_TRUE ); - uint8_t *start = src; - uint8_t *stop = MacroSearch( src, end, MVLC_END, VLC_FALSE ); + char *endfor = MacroSearch( src, end, MVLC_END, VLC_TRUE ); + char *start = src; + char *stop = MacroSearch( src, end, MVLC_END, VLC_FALSE ); if( stop ) { @@ -2360,16 +2552,14 @@ static void Execute( httpd_file_sys_t *p_args, { index = mvar_PlaylistSetNew( m.param1, p_intf->p_sys->p_playlist ); } - else if( !strcmp( m.param2, "informations" ) ) + else if( !strcmp( m.param2, "information" ) ) { index = mvar_InfoSetNew( m.param1, p_intf->p_sys->p_input ); } else if( !strcmp( m.param2, "vlm" ) ) { if( p_intf->p_sys->p_vlm == NULL ) - { p_intf->p_sys->p_vlm = vlm_New( p_intf ); - } index = mvar_VlmSetNew( m.param1, p_intf->p_sys->p_vlm ); } #if 0 @@ -2457,9 +2647,11 @@ static void Execute( httpd_file_sys_t *p_args, ****************************************************************************/ static int HttpCallback( httpd_file_sys_t *p_args, httpd_file_t *p_file, - uint8_t *p_request, - uint8_t **pp_data, int *pi_data ) + uint8_t *_p_request, + uint8_t **_pp_data, int *pi_data ) { + char *p_request = (char *)_p_request; + char **pp_data = (char **)_pp_data; int i_request = p_request ? strlen( p_request ) : 0; char *p; FILE *f; @@ -2494,8 +2686,8 @@ static int HttpCallback( httpd_file_sys_t *p_args, else { int i_buffer; - uint8_t *p_buffer; - uint8_t *dst; + char *p_buffer; + char *dst; vlc_value_t val; char position[4]; /* percentage */ char time[12]; /* in seconds */ @@ -2852,6 +3044,10 @@ static void EvaluateRPN( mvar_t *vars, rpn_stack_t *st, char *exp ) { SSPushN( st, SSPopN( st, vars ) == SSPopN( st, vars ) ? -1 : 0 ); } + else if( !strcmp( s, "!=" ) ) + { + SSPushN( st, SSPopN( st, vars ) != SSPopN( st, vars ) ? -1 : 0 ); + } else if( !strcmp( s, "<" ) ) { int j = SSPopN( st, vars ); @@ -3102,10 +3298,10 @@ static char *Find_end_MRL( char *psz ) /********************************************************************** * parse_MRL: parse the MRL, find the mrl string and the options, - * create an item with all informations in it, and return the item. + * create an item with all information in it, and return the item. * return NULL if there is an error. **********************************************************************/ -playlist_item_t * parse_MRL( intf_thread_t *p_intf, char *psz ) +static playlist_item_t *parse_MRL( intf_thread_t *p_intf, char *psz ) { char **ppsz_options = NULL; char *mrl; @@ -3209,11 +3405,8 @@ playlist_item_t * parse_MRL( intf_thread_t *p_intf, char *psz ) } } - for( i = 0 ; i < i_options ; i++ ) - { - free( ppsz_options[i] ); - } - free( ppsz_options ); + for( i = 0; i < i_options; i++ ) free( ppsz_options[i] ); + if( i_options ) free( ppsz_options ); return p_item; }