Commit d9e1effe authored by Christophe Massiot's avatar Christophe Massiot

* 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.
parent 7db33a0a
......@@ -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 */
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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" ) )
{
......
......@@ -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;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment