From: Christophe Massiot Date: Fri, 19 Aug 2005 17:07:27 +0000 (+0000) Subject: * modules/control/http/rpn.c: vlc_var_* now take an extra argument to X-Git-Tag: 0.8.4~759 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=d9e1effe9b306d176076c2c10271e710080051c8;p=vlc * modules/control/http/rpn.c: vlc_var_* now take an extra argument to indicate which object we are playing with (for instance 'VLC_OBJECT_INPUT' or 'VLC_OBJECT_PLAYLIST'). Espace \ in addslashes. * modules/control/http: Factorized and simplified the RealPath() stuff. Fixed a few hardcoded '/' as a path separator. --- diff --git a/modules/control/http/http.h b/modules/control/http/http.h index 80f9b68aa4..50b710aeb5 100644 --- a/modules/control/http/http.h +++ b/modules/control/http/http.h @@ -105,6 +105,8 @@ int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root, int E_(FileLoad)( FILE *f, char **pp_data, int *pi_data ); /** This function creates a suitable URL for a filename */ char *E_(FileToUrl)( char *name, vlc_bool_t *pb_index ); +/** This function returns the real path of a file or directory */ +char *E_(RealPath)( intf_thread_t *p_intf, const char *psz_src ); /* Locale handling functions */ diff --git a/modules/control/http/macro.c b/modules/control/http/macro.c index 7d3764e9f7..ce84c8217d 100644 --- a/modules/control/http/macro.c +++ b/modules/control/http/macro.c @@ -861,11 +861,18 @@ void E_(Execute)( httpd_file_sys_t *p_args, char *p_buffer; char psz_file[MAX_DIR_SIZE]; char *p; + char sep; - if( m.param1[0] != '/' ) +#if defined( WIN32 ) + sep = '\\'; +#else + sep = '/'; +#endif + + if( m.param1[0] != sep ) { strcpy( psz_file, p_args->file ); - p = strrchr( psz_file, '/' ); + p = strrchr( psz_file, sep ); if( p != NULL ) strcpy( p + 1, m.param1 ); else diff --git a/modules/control/http/mvar.c b/modules/control/http/mvar.c index 8dbc31dea8..79b7eebac7 100644 --- a/modules/control/http/mvar.c +++ b/modules/control/http/mvar.c @@ -495,10 +495,10 @@ mvar_t *mvar_HttpdInfoSetNew( char *name, httpd_t *p_httpd, int i_type ) #endif mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, - char *psz_dir ) + char *psz_dir ) { mvar_t *s = mvar_New( name, "set" ); - char tmp[MAX_DIR_SIZE], dir[MAX_DIR_SIZE], *p, *src; + char tmp[MAX_DIR_SIZE]; #ifdef HAVE_SYS_STAT_H struct stat stat_info; #endif @@ -508,91 +508,17 @@ mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, /* convert all / to native separator */ #if defined( WIN32 ) - while( (p = strchr( psz_dir, '/' )) ) - { - *p = '\\'; - } sep = '\\'; #else sep = '/'; #endif - /* remove trailling separator */ - while( strlen( psz_dir ) > 1 && -#if defined( WIN32 ) - !( strlen(psz_dir)==3 && psz_dir[1]==':' && psz_dir[2]==sep ) && -#endif - psz_dir[strlen( psz_dir ) -1 ] == sep ) - { - psz_dir[strlen( psz_dir ) -1 ] ='\0'; - } - /* remove double separator */ - for( p = src = psz_dir; *src != '\0'; src++, p++ ) - { - if( src[0] == sep && src[1] == sep ) - { - src++; - } - *p = *src; - } - *p = '\0'; - - if( *psz_dir == '\0' ) - { - return s; - } - - if( psz_dir[0] == '~' && psz_dir[1] == '/' ) - { - /* This is incomplete : we should also support the ~cmassiot/ syntax. */ - snprintf( dir, sizeof(dir), "%s/%s", p_intf->p_vlc->psz_homedir, - psz_dir + 2 ); - psz_dir = dir; - } - - /* first fix all .. dir */ - p = src = psz_dir; - while( *src ) - { - if( src[0] == '.' && src[1] == '.' ) - { - src += 2; - if( p <= &psz_dir[1] ) - { - continue; - } - - p -= 2; - - while( p > &psz_dir[1] && *p != sep ) - { - p--; - } - } - else if( *src == sep ) - { - if( p > psz_dir && p[-1] == sep ) - { - src++; - } - else - { - *p++ = *src++; - } - } - else - { - do - { - *p++ = *src++; - } while( *src && *src != sep ); - } - } - *p = '\0'; + psz_dir = E_(RealPath)( p_intf, psz_dir ); #ifdef HAVE_SYS_STAT_H if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) ) { + free( psz_dir ); return s; } #endif @@ -603,16 +529,10 @@ mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, { msg_Warn( p_intf, "scandir error on %s (%s)", psz_dir, strerror(errno) ); + free( psz_dir ); return s; } - /* remove trailing / or \ */ - for( p = &psz_dir[strlen( psz_dir) - 1]; - p >= psz_dir && ( *p =='/' || *p =='\\' ); p-- ) - { - *p = '\0'; - } - for( i = 0; i < i_dir_content; i++ ) { struct dirent *p_dir_content = pp_dir_content[i]; @@ -625,7 +545,8 @@ mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, continue; } - snprintf( tmp, sizeof(tmp), "%s/%s", psz_dir, p_dir_content->d_name ); + snprintf( tmp, sizeof(tmp), "%s%c%s", psz_dir, sep, + p_dir_content->d_name ); #ifdef HAVE_SYS_STAT_H if( stat( tmp, &stat_info ) == -1 ) @@ -638,7 +559,7 @@ mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, psz_tmp = vlc_fix_readdir_charset( p_intf, p_dir_content->d_name ); psz_name = E_(FromUTF8)( p_intf, psz_tmp ); free( psz_tmp ); - snprintf( tmp, sizeof(tmp), "%s/%s", psz_dir, psz_name ); + snprintf( tmp, sizeof(tmp), "%s%c%s", psz_dir, sep, psz_name ); mvar_AppendNewVar( f, "name", tmp ); mvar_AppendNewVar( f, "basename", psz_name ); @@ -681,6 +602,7 @@ mvar_t *mvar_FileSetNew( intf_thread_t *p_intf, char *name, mvar_AppendVar( s, f ); } + free( psz_dir ); return s; } diff --git a/modules/control/http/rpn.c b/modules/control/http/rpn.c index b5c840ec01..43dee08060 100644 --- a/modules/control/http/rpn.c +++ b/modules/control/http/rpn.c @@ -25,6 +25,43 @@ #include "http.h" +static vlc_object_t *GetVLCObject( intf_thread_t *p_intf, + const char *psz_object, + vlc_bool_t *pb_need_release ) +{ + intf_sys_t *p_sys = p_intf->p_sys; + int i_object_type = 0; + vlc_object_t *p_object = NULL; + *pb_need_release = VLC_FALSE; + + if( !strcmp( psz_object, "VLC_OBJECT_ROOT" ) ) + i_object_type = VLC_OBJECT_ROOT; + else if( !strcmp( psz_object, "VLC_OBJECT_VLC" ) ) + p_object = VLC_OBJECT(p_intf->p_vlc); + else if( !strcmp( psz_object, "VLC_OBJECT_INTF" ) ) + p_object = VLC_OBJECT(p_intf); + else if( !strcmp( psz_object, "VLC_OBJECT_PLAYLIST" ) ) + p_object = VLC_OBJECT(p_sys->p_playlist); + else if( !strcmp( psz_object, "VLC_OBJECT_INPUT" ) ) + p_object = VLC_OBJECT(p_sys->p_input); + else if( !strcmp( psz_object, "VLC_OBJECT_VOUT" ) ) + i_object_type = VLC_OBJECT_VOUT; + else if( !strcmp( psz_object, "VLC_OBJECT_AOUT" ) ) + i_object_type = VLC_OBJECT_AOUT; + else if( !strcmp( psz_object, "VLC_OBJECT_SOUT" ) ) + i_object_type = VLC_OBJECT_SOUT; + else + msg_Warn( p_intf, "unknown object type (%s)", psz_object ); + + if( p_object == NULL && i_object_type ) + { + *pb_need_release = VLC_TRUE; + p_object = vlc_object_find( p_intf, i_object_type, FIND_ANYWHERE ); + } + + return p_object; +} + void SSInit( rpn_stack_t *st ) { st->i_stack = 0; @@ -344,7 +381,7 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, while( *str != '\0' ) { - if( *str == '"' || *str == '\'' ) + if( *str == '"' || *str == '\'' || *str == '\\' ) { *p++ = '\\'; } @@ -428,73 +465,13 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, } else if( !strcmp( s, "realpath" ) ) { - char dir[MAX_DIR_SIZE], *src; char *psz_src = SSPop( st ); - char *psz_dir = psz_src; + char *psz_dir = E_(RealPath)( p_intf, psz_src ); char sep; - /* convert all / to native separator */ -#if defined( WIN32 ) - while( (p = strchr( psz_dir, '/' )) ) - { - *p = '\\'; - } - sep = '\\'; -#else - sep = '/'; -#endif - - if( *psz_dir == '~' ) - { - /* This is incomplete : we should also support the ~cmassiot/ syntax. */ - snprintf( dir, sizeof(dir), "%s/%s", p_intf->p_vlc->psz_homedir, - psz_dir + 1 ); - psz_dir = dir; - } - - /* first fix all .. dir */ - p = src = psz_dir; - while( *src ) - { - if( src[0] == '.' && src[1] == '.' ) - { - src += 2; - if( p <= &psz_dir[1] ) - { - continue; - } - - p -= 2; - - while( p > &psz_dir[1] && *p != sep ) - { - p--; - } - } - else if( *src == sep ) - { - if( p > psz_dir && p[-1] == sep ) - { - src++; - } - else - { - *p++ = *src++; - } - } - else - { - do - { - *p++ = *src++; - } while( *src && *src != sep ); - } - } - if( p != psz_dir + 1 && p[-1] == '/' ) p--; - *p = '\0'; - SSPush( st, psz_dir ); free( psz_src ); + free( psz_dir ); } /* 4. stack functions */ else if( !strcmp( s, "dup" ) ) @@ -584,21 +561,31 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, else if( !strcmp( s, "vlc_var_type" ) || !strcmp( s, "vlc_config_type" ) ) { - const char *psz_type = NULL; - char *psz_variable = SSPop( st ); vlc_object_t *p_object; - int i_type; + const char *psz_type = NULL; + int i_type = 0; if( !strcmp( s, "vlc_var_type" ) ) { - p_object = VLC_OBJECT(p_sys->p_input); + char *psz_object = SSPop( st ); + char *psz_variable = SSPop( st ); + vlc_bool_t b_need_release; + + p_object = GetVLCObject( p_intf, psz_object, &b_need_release ); + if( p_object != NULL ) i_type = var_Type( p_object, psz_variable ); + free( psz_variable ); + free( psz_object ); + if( b_need_release && p_object != NULL ) + vlc_object_release( p_object ); } else { + char *psz_variable = SSPop( st ); p_object = VLC_OBJECT(p_intf); i_type = config_GetType( p_object, psz_variable ); + free( psz_variable ); } if( p_object != NULL ) @@ -640,33 +627,37 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, psz_type = "INVALID"; SSPush( st, psz_type ); - free( psz_variable ); } else if( !strcmp( s, "vlc_var_set" ) ) { + char *psz_object = SSPop( st ); char *psz_variable = SSPop( st ); + vlc_bool_t b_need_release; - if( p_sys->p_input != NULL ) + vlc_object_t *p_object = GetVLCObject( p_intf, psz_object, + &b_need_release ); + + if( p_object != NULL ) { vlc_bool_t b_error = VLC_FALSE; char *psz_value = NULL; vlc_value_t val; int i_type; - i_type = var_Type( p_sys->p_input, psz_variable ); + i_type = var_Type( p_object, psz_variable ); switch( i_type & VLC_VAR_TYPE ) { case VLC_VAR_BOOL: val.b_bool = SSPopN( st, vars ); - msg_Dbg( p_intf, "requested input var change: %s->%d", - psz_variable, val.b_bool ); + msg_Dbg( p_intf, "requested %s var change: %s->%d", + psz_object, psz_variable, val.b_bool ); break; case VLC_VAR_INTEGER: case VLC_VAR_HOTKEY: val.i_int = SSPopN( st, vars ); - msg_Dbg( p_intf, "requested input var change: %s->%d", - psz_variable, val.i_int ); + msg_Dbg( p_intf, "requested %s var change: %s->%d", + psz_object, psz_variable, val.i_int ); break; case VLC_VAR_STRING: case VLC_VAR_MODULE: @@ -674,41 +665,51 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, case VLC_VAR_DIRECTORY: case VLC_VAR_VARIABLE: val.psz_string = psz_value = SSPop( st ); - msg_Dbg( p_intf, "requested input var change: %s->%s", - psz_variable, psz_value ); + msg_Dbg( p_intf, "requested %s var change: %s->%s", + psz_object, psz_variable, psz_value ); break; case VLC_VAR_FLOAT: psz_value = SSPop( st ); val.f_float = atof( psz_value ); - msg_Dbg( p_intf, "requested input var change: %s->%f", - psz_variable, val.f_float ); + msg_Dbg( p_intf, "requested %s var change: %s->%f", + psz_object, psz_variable, val.f_float ); break; default: - msg_Warn( p_intf, "invalid variable type %d (%s)", - i_type & VLC_VAR_TYPE, psz_variable ); + SSPopN( st, vars ); + msg_Warn( p_intf, "invalid %s variable type %d (%s)", + psz_object, i_type & VLC_VAR_TYPE, psz_variable ); b_error = VLC_TRUE; } if( !b_error ) - var_Set( p_sys->p_input, psz_variable, val ); + var_Set( p_object, psz_variable, val ); if( psz_value != NULL ) free( psz_value ); } else - msg_Warn( p_intf, "vlc_var_set called without an input" ); + msg_Warn( p_intf, "vlc_var_set called without an object" ); free( psz_variable ); + free( psz_object ); + + if( b_need_release && p_object != NULL ) + vlc_object_release( p_object ); } else if( !strcmp( s, "vlc_var_get" ) ) { + char *psz_object = SSPop( st ); char *psz_variable = SSPop( st ); + vlc_bool_t b_need_release; + + vlc_object_t *p_object = GetVLCObject( p_intf, psz_object, + &b_need_release ); - if( p_sys->p_input != NULL ) + if( p_object != NULL ) { vlc_value_t val; int i_type; - i_type = var_Type( p_sys->p_input, psz_variable ); - var_Get( p_sys->p_input, psz_variable, &val ); + i_type = var_Type( p_object, psz_variable ); + var_Get( p_object, psz_variable, &val ); switch( i_type & VLC_VAR_TYPE ) { @@ -735,17 +736,21 @@ void EvaluateRPN( intf_thread_t *p_intf, mvar_t *vars, break; } default: - msg_Warn( p_intf, "invalid variable type %d (%s)", - i_type & VLC_VAR_TYPE, psz_variable ); + msg_Warn( p_intf, "invalid %s variable type %d (%s)", + psz_object, i_type & VLC_VAR_TYPE, psz_variable ); SSPush( st, "" ); } } else { - msg_Warn( p_intf, "vlc_var_get called without an input" ); + msg_Warn( p_intf, "vlc_var_get called without an object" ); SSPush( st, "" ); } free( psz_variable ); + free( psz_object ); + + if( b_need_release && p_object != NULL ) + vlc_object_release( p_object ); } else if( !strcmp( s, "vlc_config_set" ) ) { diff --git a/modules/control/http/util.c b/modules/control/http/util.c index ee4c5ee9b4..213081810b 100644 --- a/modules/control/http/util.c +++ b/modules/control/http/util.c @@ -120,6 +120,14 @@ int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root, int i_dirlen; + char sep; + +#if defined( WIN32 ) + sep = '\\'; +#else + sep = '/'; +#endif + #ifdef HAVE_SYS_STAT_H if( stat( psz_dir, &stat_info ) == -1 || !S_ISDIR( stat_info.st_mode ) ) { @@ -142,7 +150,7 @@ int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root, msg_Dbg( p_intf, "dir=%s", psz_dir ); - sprintf( dir, "%s/.access", psz_dir ); + sprintf( dir, "%s%c.access", psz_dir, sep ); if( ( file = fopen( dir, "r" ) ) != NULL ) { char line[1024]; @@ -176,7 +184,7 @@ int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root, fclose( file ); } - sprintf( dir, "%s/.hosts", psz_dir ); + sprintf( dir, "%s%c.hosts", psz_dir, sep ); p_acl = ACL_Create( p_intf, VLC_FALSE ); if( ACL_LoadFile( p_acl, dir ) ) { @@ -196,7 +204,7 @@ int E_(ParseDirectory)( intf_thread_t *p_intf, char *psz_root, || ( i_dirlen + strlen( p_dir_content->d_name ) > MAX_DIR_SIZE ) ) continue; - sprintf( dir, "%s/%s", psz_dir, p_dir_content->d_name ); + sprintf( dir, "%s%c%s", psz_dir, sep, p_dir_content->d_name ); if( E_(ParseDirectory)( p_intf, psz_root, dir ) ) { httpd_file_sys_t *f = malloc( sizeof( httpd_file_sys_t ) ); @@ -793,3 +801,92 @@ playlist_item_t *E_(MRLParse)( intf_thread_t *p_intf, char *_psz, free( psz ); return p_item; } + +/********************************************************************** + * RealPath: parse ../, ~ and path stuff + **********************************************************************/ +char *E_(RealPath)( intf_thread_t *p_intf, const char *psz_src ) +{ + char *psz_dir; + char *p; + int i_len = strlen(psz_src); + char sep; + +#if defined( WIN32 ) + sep = '\\'; +#else + sep = '/'; +#endif + + psz_dir = malloc( i_len + 2 ); + strcpy( psz_dir, psz_src ); + + /* Add a trailing sep to ease the .. step */ + psz_dir[i_len] = sep; + psz_dir[i_len + 1] = '\0'; + +#ifdef WIN32 + /* Convert all / to native separator */ + p = psz_dir; + while( (p = strchr( p, '/' )) != NULL ) + { + *p = sep; + } +#endif + + /* Remove multiple separators and /./ */ + p = psz_dir; + while( (p = strchr( p, sep )) != NULL ) + { + if( p[1] == sep ) + memmove( &p[1], &p[2], strlen(&p[2]) + 1 ); + else if( p[1] == '.' && p[2] == sep ) + memmove( &p[1], &p[3], strlen(&p[3]) + 1 ); + else + p++; + } + + if( psz_dir[0] == '~' ) + { + char *dir = malloc( strlen(psz_dir) + + strlen(p_intf->p_vlc->psz_homedir) ); + /* This is incomplete : we should also support the ~cmassiot/ syntax. */ + sprintf( dir, "%s%s", p_intf->p_vlc->psz_homedir, psz_dir + 1 ); + free( psz_dir ); + psz_dir = dir; + } + + if( strlen(psz_dir) > 2 ) + { + /* Fix all .. dir */ + p = psz_dir + 3; + while( (p = strchr( p, sep )) != NULL ) + { + if( p[-1] == '.' && p[-2] == '.' && p[-3] == sep ) + { + char *q; + p[-3] = '\0'; + if( (q = strrchr( psz_dir, sep )) != NULL ) + { + memmove( q + 1, p + 1, strlen(p + 1) + 1 ); + p = q + 1; + } + else + { + memmove( psz_dir, p + 1, strlen(p + 1) + 1 ); + p = psz_dir + 3; + } + } + else + p++; + } + } + + /* Remove trailing sep if there are at least 2 sep in the string + * (handles the C:\ stuff) */ + p = strrchr( psz_dir, sep ); + if( p != NULL && p[1] == '\0' && p != strchr( psz_dir, sep ) ) + *p = '\0'; + + return psz_dir; +}