#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 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)" )
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 )
+ 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 );
{
intf_thread_t *p_intf = (intf_thread_t*)p_this;
intf_sys_t *p_sys;
- char *psz_host;
- char *psz_address = "";
+ char *psz_address;
const char *psz_cert = NULL, *psz_key = NULL, *psz_ca = NULL,
*psz_crl = NULL;
int i_port = 0;
char *psz_src;
- psz_host = config_GetPsz( p_intf, "http-host" );
- if( psz_host )
+ psz_address = config_GetPsz( p_intf, "http-host" );
+ if( psz_address != NULL )
{
- char *psz_parser;
- psz_address = psz_host;
-
- psz_parser = strchr( psz_host, ':' );
+ 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 )
p_sys->p_playlist = NULL;
p_sys->p_input = NULL;
p_sys->p_vlm = NULL;
+ 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" );
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 ;
free( psz_src );
+ /* determine file handler associations */
+ p_sys->i_handlers = 0;
+ p_sys->pp_handlers = NULL;
+#if defined( HAVE_FORK )
+ 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_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;
}
- if( psz_host )
- {
- free( psz_host );
- }
-
p_sys->i_files = 0;
p_sys->pp_files = NULL;
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);
+ sprintf( psz_src, "%s/http", psz_vlcpath );
#else
- sprintf( psz_src, "%s/share/http", psz_vlcpath);
+ sprintf( psz_src, "%s/share/http", psz_vlcpath );
#endif
}
#else
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 );
}
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 );
- free( p_sys->pp_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 )
* HttpCallback:
****************************************************************************
* a file with b_html is parsed and all "macro" replaced
- * <vlc id="macro name" [param1="" [param2=""]] />
- * valid id are
- *
****************************************************************************/
+static void Callback404( httpd_file_sys_t *p_args, char **pp_data,
+ int *pi_data )
+{
+ char *p = *pp_data = malloc( 10240 );
+ if( !p )
+ {
+ return;
+ }
+ p += sprintf( p, "<html>\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" );
+
+ *pi_data = strlen( *pp_data );
+}
+
+static void ParseExecute( httpd_file_sys_t *p_args, char *p_buffer,
+ int i_buffer, char *p_request,
+ char **pp_data, int *pi_data )
+{
+ int i_request = p_request != NULL ? strlen( p_request ) : 0;
+ char *dst;
+ vlc_value_t val;
+ char position[4]; /* percentage */
+ char time[12]; /* in seconds */
+ char length[12]; /* in seconds */
+ audio_volume_t i_volume;
+ char volume[5];
+ char state[8];
+
+#define p_sys p_args->p_intf->p_sys
+ if( p_sys->p_input )
+ {
+ 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) );
+ var_Get( p_sys->p_input, "length", &val);
+ sprintf( length, "%d" , (int)(val.i_time / 1000000) );
+
+ var_Get( p_sys->p_input, "state", &val );
+ if( val.i_int == PLAYING_S )
+ {
+ sprintf( state, "playing" );
+ }
+ else if( val.i_int == PAUSE_S )
+ {
+ sprintf( state, "paused" );
+ }
+ else
+ {
+ sprintf( state, "stop" );
+ }
+ }
+ else
+ {
+ sprintf( position, "%d", 0 );
+ sprintf( time, "%d", 0 );
+ sprintf( length, "%d", 0 );
+ sprintf( state, "stop" );
+ }
+#undef p_sys
+
+ aout_VolumeGet( p_args->p_intf, &i_volume );
+ sprintf( volume, "%d", (int)i_volume );
+
+ p_args->vars = E_(mvar_New)( "variables", "" );
+ E_(mvar_AppendNewVar)( p_args->vars, "url_param",
+ i_request > 0 ? "1" : "0" );
+ E_(mvar_AppendNewVar)( p_args->vars, "url_value", p_request );
+ E_(mvar_AppendNewVar)( p_args->vars, "version", VLC_Version() );
+ E_(mvar_AppendNewVar)( p_args->vars, "copyright", COPYRIGHT_MESSAGE );
+ E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_by", VLC_CompileBy() );
+ E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_host",
+ VLC_CompileHost() );
+ E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_domain",
+ VLC_CompileDomain() );
+ E_(mvar_AppendNewVar)( p_args->vars, "vlc_compiler", VLC_Compiler() );
+ E_(mvar_AppendNewVar)( p_args->vars, "vlc_changeset", VLC_Changeset() );
+ 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_(SSInit)( &p_args->stack );
+
+ /* allocate output */
+ *pi_data = i_buffer + 1000;
+ dst = *pp_data = malloc( *pi_data );
+
+ /* we parse executing all <vlc /> macros */
+ E_(Execute)( p_args, p_request, i_request, pp_data, pi_data, &dst,
+ &p_buffer[0], &p_buffer[i_buffer] );
+
+ *dst = '\0';
+ *pi_data = dst - *pp_data;
+
+ E_(SSClean)( &p_args->stack );
+ E_(mvar_Delete)( p_args->vars );
+}
+
int E_(HttpCallback)( httpd_file_sys_t *p_args,
httpd_file_t *p_file,
uint8_t *_p_request,
{
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;
if( ( f = fopen( p_args->file, "r" ) ) == NULL )
{
- p = *pp_data = malloc( 10240 );
- if( !p )
- {
- return VLC_EGENERIC;
- }
- p += sprintf( p, "<html>\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" );
-
- *pi_data = strlen( *pp_data );
-
+ Callback404( p_args, pp_data, pi_data );
return VLC_SUCCESS;
}
{
int i_buffer;
char *p_buffer;
- char *dst;
- vlc_value_t val;
- char position[4]; /* percentage */
- char time[12]; /* in seconds */
- char length[12]; /* in seconds */
- audio_volume_t i_volume;
- char volume[5];
- char state[8];
-
-#define p_sys p_args->p_intf->p_sys
- if( p_sys->p_input )
+
+ /* first we load in a temporary buffer */
+ E_(FileLoad)( f, &p_buffer, &i_buffer );
+
+ ParseExecute( p_args, p_buffer, i_buffer, p_request, pp_data, pi_data );
+
+ free( p_buffer );
+ }
+
+ fclose( f );
+
+ return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * HandlerCallback:
+ ****************************************************************************
+ * 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,
+ uint8_t *_p_request, int i_type,
+ uint8_t *_p_in, int i_in,
+ char *psz_remote_addr, char *psz_remote_host,
+ uint8_t **_pp_data, int *pi_data )
+{
+ char *p_url = (char *)_p_url;
+ char *p_request = (char *)_p_request;
+ char **pp_data = (char **)_pp_data;
+ char *p_in = (char *)p_in;
+ int i_request = p_request != NULL ? strlen( p_request ) : 0;
+ char *p;
+ int i_env = 0;
+ char **pp_env = NULL;
+ char *psz_tmp;
+ char sep;
+ int i_buffer;
+ char *p_buffer;
+ char *psz_cwd;
+
+#ifdef WIN32
+ sep = '\\';
+#else
+ sep = '/';
+#endif
+
+ /* Create environment for the CGI */
+ TAB_APPEND( i_env, pp_env, strdup("GATEWAY_INTERFACE=CGI/1.1") );
+ TAB_APPEND( i_env, pp_env, strdup("SERVER_PROTOCOL=HTTP/1.1") );
+ TAB_APPEND( i_env, pp_env, strdup("SERVER_SOFTWARE=" COPYRIGHT_MESSAGE) );
+
+ switch( i_type )
+ {
+ case HTTPD_MSG_GET:
+ TAB_APPEND( i_env, pp_env, strdup("REQUEST_METHOD=GET") );
+ break;
+ case HTTPD_MSG_POST:
+ TAB_APPEND( i_env, pp_env, strdup("REQUEST_METHOD=POST") );
+ break;
+ case HTTPD_MSG_HEAD:
+ TAB_APPEND( i_env, pp_env, strdup("REQUEST_METHOD=HEAD") );
+ break;
+ default:
+ break;
+ }
+
+ if( i_request )
+ {
+ psz_tmp = malloc( sizeof("QUERY_STRING=") + i_request );
+ sprintf( psz_tmp, "QUERY_STRING=%s", p_request );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+
+ psz_tmp = malloc( sizeof("REQUEST_URI=?") + strlen(p_url)
+ + i_request );
+ sprintf( psz_tmp, "REQUEST_URI=%s?%s", p_url, p_request );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ }
+ else
+ {
+ psz_tmp = malloc( sizeof("REQUEST_URI=") + strlen(p_url) );
+ sprintf( psz_tmp, "REQUEST_URI=%s", p_url );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ }
+
+ psz_tmp = malloc( sizeof("SCRIPT_NAME=") + strlen(p_url) );
+ sprintf( psz_tmp, "SCRIPT_NAME=%s", p_url );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+
+ psz_tmp = malloc( sizeof("SCRIPT_FILENAME=") + strlen(p_args->file.file) );
+ sprintf( psz_tmp, "SCRIPT_FILENAME=%s", p_args->file.file );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+
+#define p_sys p_args->file.p_intf->p_sys
+ psz_tmp = malloc( sizeof("SERVER_NAME=") + strlen(p_sys->psz_address) );
+ sprintf( psz_tmp, "SERVER_NAME=%s", p_sys->psz_address );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+
+ psz_tmp = malloc( sizeof("SERVER_PORT=") + 5 );
+ sprintf( psz_tmp, "SERVER_PORT=%u", p_sys->i_port );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+#undef p_sys
+
+ if( psz_remote_addr != NULL && *psz_remote_addr )
+ {
+ psz_tmp = malloc( sizeof("REMOTE_ADDR=") + strlen(psz_remote_addr) );
+ sprintf( psz_tmp, "REMOTE_ADDR=%s", psz_remote_addr );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ }
+
+ if( psz_remote_host != NULL && *psz_remote_host )
+ {
+ psz_tmp = malloc( sizeof("REMOTE_HOST=") + strlen(psz_remote_host) );
+ sprintf( psz_tmp, "REMOTE_HOST=%s", psz_remote_host );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ }
+
+ if( i_in )
+ {
+ p = p_in;
+ for ( ; ; )
{
- 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) );
- var_Get( p_sys->p_input, "length", &val);
- sprintf( length, "%d" , (int)(val.i_time / 1000000) );
-
- var_Get( p_sys->p_input, "state", &val );
- if( val.i_int == PLAYING_S )
+ if( !strncmp( p, "Content-Type: ", strlen("Content-Type: ") ) )
{
- sprintf( state, "playing" );
+ char *end = strchr( p, '\r' );
+ if( end == NULL )
+ break;
+ *end = '\0';
+ psz_tmp = malloc( sizeof("CONTENT_TYPE=") + strlen(p) );
+ sprintf( psz_tmp, "CONTENT_TYPE=%s", p );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ *end = '\r';
}
- else if( val.i_int == PAUSE_S )
+ if( !strncmp( p, "Content-Length: ", strlen("Content-Length: ") ) )
{
- sprintf( state, "paused" );
+ char *end = strchr( p, '\r' );
+ if( end == NULL )
+ break;
+ *end = '\0';
+ psz_tmp = malloc( sizeof("CONTENT_LENGTH=") + strlen(p) );
+ sprintf( psz_tmp, "CONTENT_LENGTH=%s", p );
+ TAB_APPEND( i_env, pp_env, psz_tmp );
+ *end = '\r';
}
- else
+
+ p = strchr( p, '\n' );
+ if( p == NULL || p[1] == '\r' )
{
- sprintf( state, "stop" );
+ p = NULL;
+ break;
}
+ p++;
}
- else
- {
- sprintf( position, "%d", 0 );
- sprintf( time, "%d", 0 );
- sprintf( length, "%d", 0 );
- sprintf( state, "stop" );
- }
-#undef p_sys
-
- aout_VolumeGet( p_args->p_intf , &i_volume );
- sprintf( volume , "%d" , (int)i_volume );
+ }
- p_args->vars = E_(mvar_New)( "variables", "" );
- E_(mvar_AppendNewVar)( p_args->vars, "url_param",
- i_request > 0 ? "1" : "0" );
- E_(mvar_AppendNewVar)( p_args->vars, "url_value", p_request );
- E_(mvar_AppendNewVar)( p_args->vars, "version", VLC_Version() );
- E_(mvar_AppendNewVar)( p_args->vars, "copyright", COPYRIGHT_MESSAGE );
- E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_by", VLC_CompileBy() );
- E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_host",
- VLC_CompileHost() );
- E_(mvar_AppendNewVar)( p_args->vars, "vlc_compile_domain",
- VLC_CompileDomain() );
- E_(mvar_AppendNewVar)( p_args->vars, "vlc_compiler", VLC_Compiler() );
- E_(mvar_AppendNewVar)( p_args->vars, "vlc_changeset", VLC_Changeset() );
- 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_(SSInit)( &p_args->stack );
+ TAB_APPEND( i_env, pp_env, NULL );
- /* first we load in a temporary buffer */
- E_(FileLoad)( f, &p_buffer, &i_buffer );
+ TAB_APPEND( p_args->p_association->i_argc, p_args->p_association->ppsz_argv,
+ p_args->file.file );
+ TAB_APPEND( p_args->p_association->i_argc, p_args->p_association->ppsz_argv,
+ NULL );
- /* allocate output */
- *pi_data = i_buffer + 1000;
- dst = *pp_data = malloc( *pi_data );
+ psz_tmp = strdup( p_args->file.file );
+ p = strrchr( psz_tmp, sep );
+ if( p != NULL )
+ {
+ *p = '\0';
+ psz_cwd = psz_tmp;
+ }
+ else
+ {
+ free( psz_tmp );
+ psz_cwd = NULL;
+ }
- /* we parse executing all <vlc /> macros */
- E_(Execute)( p_args, p_request, i_request, pp_data, pi_data, &dst,
- &p_buffer[0], &p_buffer[i_buffer] );
+ if( vlc_execve( p_args->file.p_intf, p_args->p_association->i_argc,
+ p_args->p_association->ppsz_argv, pp_env, psz_cwd,
+ (char *)p_in, i_in, &p_buffer, &i_buffer ) == -1 )
+ {
+ TAB_REMOVE( p_args->p_association->i_argc,
+ p_args->p_association->ppsz_argv, NULL );
+ TAB_REMOVE( p_args->p_association->i_argc,
+ p_args->p_association->ppsz_argv, p_args->file.file );
+ if( psz_cwd != NULL )
+ free( psz_cwd );
+
+ Callback404( (httpd_file_sys_t *)p_args, pp_data, pi_data );
+ return VLC_SUCCESS;
+ }
+ TAB_REMOVE( p_args->p_association->i_argc, p_args->p_association->ppsz_argv,
+ NULL );
+ TAB_REMOVE( p_args->p_association->i_argc, p_args->p_association->ppsz_argv,
+ p_args->file.file );
+ if( psz_cwd != NULL )
+ free( psz_cwd );
+
+ p = p_buffer;
+ while( strncmp( p, "Content-Type: text/html",
+ strlen("Content-Type: text/html") ) )
+ {
+ p = strchr( p, '\n' );
+ if( p == NULL || p[1] == '\r' )
+ {
+ p = NULL;
+ break;
+ }
+ p++;
+ }
- *dst = '\0';
- *pi_data = dst - *pp_data;
+ if( p == NULL )
+ {
+ *pp_data = p_buffer;
+ *pi_data = i_buffer;
+ }
+ else
+ {
+ ParseExecute( (httpd_file_sys_t *)p_args, p_buffer, i_buffer,
+ p_request, pp_data, pi_data );
- E_(SSClean)( &p_args->stack );
- E_(mvar_Delete)( p_args->vars );
free( p_buffer );
}
- fclose( f );
-
return VLC_SUCCESS;
}
-
}
/*****************************************************************************
- * High Level Funtions: httpd_file_t
+ * High Level Functions: httpd_file_t
*****************************************************************************/
struct httpd_file_t
{
static int httpd_FileCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query )
{
httpd_file_t *file = (httpd_file_t*)p_sys;
+ uint8_t *psz_args = query->psz_args;
+ uint8_t **pp_body, *p_body;
+ int *pi_body, i_body;
if( answer == NULL || query == NULL )
{
if( query->i_type != HTTPD_MSG_HEAD )
{
- uint8_t *psz_args = query->psz_args;
- if( query->i_type == HTTPD_MSG_POST )
- {
- /* Check that */
- psz_args = query->p_body;
- }
- file->pf_fill( file->p_sys, file, psz_args, &answer->p_body,
- &answer->i_body );
+ pp_body = &answer->p_body;
+ pi_body = &answer->i_body;
+ }
+ else
+ {
+ /* The file still needs to be executed. */
+ p_body = NULL;
+ i_body = 0;
+ pp_body = &p_body;
+ pi_body = &i_body;
}
+
+ if( query->i_type == HTTPD_MSG_POST )
+ {
+ /* msg_Warn not supported */
+ }
+
+ file->pf_fill( file->p_sys, file, psz_args, pp_body, pi_body );
+
+ if( query->i_type == HTTPD_MSG_HEAD && p_body != NULL )
+ {
+ free( p_body );
+ }
+
/* We respect client request */
if( strcmp( httpd_MsgGet( &cl->query, "Connection" ), "" ) )
{
free( file );
}
+/*****************************************************************************
+ * High Level Functions: httpd_handler_t (for CGIs)
+ *****************************************************************************/
+struct httpd_handler_t
+{
+ httpd_url_t *url;
+
+ httpd_handler_callback_t pf_fill;
+ httpd_handler_sys_t *p_sys;
+
+};
+
+static int httpd_HandlerCallBack( httpd_callback_sys_t *p_sys, httpd_client_t *cl, httpd_message_t *answer, httpd_message_t *query )
+{
+ httpd_handler_t *handler = (httpd_handler_t*)p_sys;
+ uint8_t *psz_args = query->psz_args;
+ char psz_remote_addr[100];
+
+ if( answer == NULL || query == NULL )
+ {
+ return VLC_SUCCESS;
+ }
+ answer->i_proto = HTTPD_PROTO_NONE;
+ answer->i_type = HTTPD_MSG_ANSWER;
+
+ /* We do it ourselves, thanks */
+ answer->i_status = 0;
+ answer->psz_status = NULL;
+
+ switch( cl->sock.ss_family )
+ {
+#ifdef HAVE_INET_PTON
+ case AF_INET:
+ inet_ntop( cl->sock.ss_family,
+ &((struct sockaddr_in *)&cl->sock)->sin_addr,
+ psz_remote_addr, sizeof(psz_remote_addr) );
+ break;
+ case AF_INET6:
+ inet_ntop( cl->sock.ss_family,
+ &((struct sockaddr_in6 *)&cl->sock)->sin6_addr,
+ psz_remote_addr, sizeof(psz_remote_addr) );
+ break;
+#else
+ case AF_INET:
+ {
+ char *psz_tmp = inet_ntoa( ((struct sockaddr_in *)&cl->sock)->sin_addr );
+ strncpy( psz_remote_addr, psz_tmp, sizeof(psz_remote_addr) );
+ break;
+ }
+#endif
+ default:
+ psz_remote_addr[0] = '\0';
+ }
+
+ handler->pf_fill( handler->p_sys, handler, query->psz_url, psz_args,
+ query->i_type, query->p_body, query->i_body,
+ psz_remote_addr, NULL,
+ &answer->p_body, &answer->i_body );
+
+ if( query->i_type == HTTPD_MSG_HEAD )
+ {
+ char *p = answer->p_body;
+ while ( (p = strchr( p, '\r' )) != NULL )
+ {
+ if( p[1] && p[1] == '\n' && p[2] && p[2] == '\r'
+ && p[3] && p[3] == '\n' )
+ {
+ break;
+ }
+ }
+ if( p != NULL )
+ {
+ p[4] = '\0';
+ answer->i_body = strlen(answer->p_body) + 1;
+ answer->p_body = realloc( answer->p_body, answer->i_body );
+ }
+ }
+
+ if( strncmp( answer->p_body, "HTTP/1.", 7 ) )
+ {
+ int i_status, i_headers;
+ char *psz_headers, *psz_new, *psz_status;
+ char psz_code[12];
+ if( !strncmp( answer->p_body, "Status: ", 8 ) )
+ {
+ /* Apache-style */
+ i_status = strtol( &answer->p_body[8], &psz_headers, 0 );
+ if( *psz_headers ) psz_headers++;
+ if( *psz_headers ) psz_headers++;
+ i_headers = answer->i_body - (psz_headers - (char *)answer->p_body);
+ }
+ else
+ {
+ i_status = 200;
+ psz_headers = answer->p_body;
+ i_headers = answer->i_body;
+ }
+ switch( i_status )
+ {
+ case 200:
+ psz_status = "OK";
+ break;
+ case 401:
+ psz_status = "Unauthorized";
+ break;
+ default:
+ psz_status = "Undefined";
+ break;
+ }
+ snprintf( psz_code, sizeof(psz_code), "%d", i_status );
+ answer->i_body = sizeof("HTTP/1.0 \r\n") + strlen(psz_code)
+ + strlen(psz_status) + i_headers - 1;
+ psz_new = malloc( answer->i_body + 1);
+ sprintf( psz_new, "HTTP/1.0 %s %s\r\n", psz_code, psz_status );
+ memcpy( &psz_new[strlen(psz_new)], psz_headers, i_headers );
+ free( answer->p_body );
+ answer->p_body = psz_new;
+ }
+
+ return VLC_SUCCESS;
+}
+
+httpd_handler_t *httpd_HandlerNew( httpd_host_t *host, const char *psz_url,
+ const char *psz_user,
+ const char *psz_password,
+ const vlc_acl_t *p_acl,
+ httpd_handler_callback_t pf_fill,
+ httpd_handler_sys_t *p_sys )
+{
+ httpd_handler_t *handler = malloc( sizeof( httpd_handler_t ) );
+
+ if( ( handler->url = httpd_UrlNewUnique( host, psz_url, psz_user,
+ psz_password, p_acl )
+ ) == NULL )
+ {
+ free( handler );
+ return NULL;
+ }
+
+ handler->pf_fill = pf_fill;
+ handler->p_sys = p_sys;
+
+ httpd_UrlCatch( handler->url, HTTPD_MSG_HEAD, httpd_HandlerCallBack,
+ (httpd_callback_sys_t*)handler );
+ httpd_UrlCatch( handler->url, HTTPD_MSG_GET, httpd_HandlerCallBack,
+ (httpd_callback_sys_t*)handler );
+ httpd_UrlCatch( handler->url, HTTPD_MSG_POST, httpd_HandlerCallBack,
+ (httpd_callback_sys_t*)handler );
+
+ return handler;
+}
+
+void httpd_HandlerDelete( httpd_handler_t *handler )
+{
+ httpd_UrlDelete( handler->url );
+ free( handler );
+}
+
/*****************************************************************************
* High Level Functions: httpd_redirect_t
*****************************************************************************/
if( cl->query.i_proto == HTTPD_PROTO_NONE )
{
- /* enought to see if it's rtp over rtsp or RTSP/HTTP */
+ /* enough to see if it's rtp over rtsp or RTSP/HTTP */
i_len = httpd_NetRecv( cl, &cl->p_buffer[cl->i_buffer],
4 - cl->i_buffer );
if( i_len > 0 )
i_len = httpd_NetSend( cl, &cl->p_buffer[cl->i_buffer],
cl->i_buffer_size - cl->i_buffer );
- if( i_len > 0 )
+ if( i_len >= 0 )
{
cl->i_activity_date = mdate();
cl->i_buffer += i_len;
if( !url->catch[i_msg].cb( url->catch[i_msg].p_sys, cl, answer, query ) )
{
+ if( answer->i_proto == HTTPD_PROTO_NONE )
+ {
+ /* Raw answer from a CGI */
+ cl->i_buffer = cl->i_buffer_size;
+ }
+ else
+ cl->i_buffer = -1;
+
/* only one url can answer */
answer = NULL;
if( cl->url == NULL )
}
answer->i_body = p - answer->p_body;
+ cl->i_buffer = -1; /* Force the creation of the answer in httpd_ClientSend */
httpd_MsgAdd( answer, "Content-Length", "%d", answer->i_body );
}
- cl->i_buffer = -1; /* Force the creation of the answer in httpd_ClientSend */
+
cl->i_state = HTTPD_CLIENT_SENDING;
}
}