Commit a362f5c3 authored by Laurent Aimar's avatar Laurent Aimar
Browse files

* http: rework of the http interface.

 There is no more hardcoded html page. The interface recursively parse a
directory, exporting all  files. All .htm/.html are  parsed, and special
macro are  used. I will commit  somes samples pages in  share/http and I
hope documentations.

 TODO: - (re)implement access control in httpd (but in a useable way).
       - clean login/password management. (for now .access protects
       a whole directory).
       - doc ;)
parent 16afd989
......@@ -2,7 +2,7 @@
* httpd.h
*****************************************************************************
* Copyright (C) 2001-2003 VideoLAN
* $Id: httpd.h,v 1.5 2003/06/25 15:50:52 fenrir Exp $
* $Id: httpd.h,v 1.6 2003/07/10 22:24:09 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -21,8 +21,6 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
typedef struct httpd_t httpd_t;
typedef struct httpd_host_t httpd_host_t;
typedef struct httpd_file_t httpd_file_t;
......@@ -34,6 +32,30 @@ typedef int (*httpd_file_callback)( httpd_file_callback_args_t *p_args, uint8_t
typedef struct httpd_sys_t httpd_sys_t;
enum httpdControl_e
{
HTTPD_GET_HOSTS,
HTTPD_GET_URLS,
HTTPD_GET_CONNECTIONS,
HTTPD_GET_ACL, /* not implemented */
HTTPD_SET_CLOSE,
HTTPD_SET_ACL /* not implemented */
};
typedef struct
{
char *psz_name;
char *psz_value;
} httpd_val_t;
typedef struct
{
int i_count;
httpd_val_t *info;
} httpd_info_t;
struct httpd_t
{
VLC_COMMON_MEMBERS
......@@ -62,31 +84,36 @@ struct httpd_t
httpd_stream_t *,
uint8_t *, int );
void (*pf_unregister_stream) ( httpd_t *, httpd_stream_t * );
int (*pf_control) ( httpd_t *,
int i_query,
void *arg1, void *arg2 );
};
/*
/*****************************************************************************
* httpd_Find:
*
* Return the running httpd instance
* (if none and b_create then a new one is created)
*/
* Return the running httpd instance (if none and b_create then a new one is created)
* httpd_release:
*****************************************************************************/
static inline httpd_t* httpd_Find( vlc_object_t *p_this, vlc_bool_t b_create )
{
httpd_t *p_httpd = NULL;
vlc_value_t lockval;
var_Get( p_this->p_libvlc, "httpd", &lockval );
vlc_mutex_lock( lockval.p_address );
p_httpd = vlc_object_find( p_this, VLC_OBJECT_HTTPD, FIND_ANYWHERE );
if( !p_httpd )
if( !p_httpd && b_create)
{
msg_Info(p_this, "creating new http daemon" );
if( !b_create )
{
return( NULL );
}
p_httpd = vlc_object_create( p_this, VLC_OBJECT_HTTPD );
if( !p_httpd )
{
msg_Err( p_this, "out of memory" );
vlc_mutex_unlock( lockval.p_address );
return( NULL );
}
......@@ -96,12 +123,14 @@ static inline httpd_t* httpd_Find( vlc_object_t *p_this, vlc_bool_t b_create )
{
msg_Err( p_this, "no suitable httpd module" );
vlc_object_destroy( p_httpd );
vlc_mutex_unlock( lockval.p_address );
return( NULL );
}
vlc_object_yield( p_httpd );
vlc_object_attach( p_httpd, p_this->p_vlc );
}
vlc_mutex_unlock( lockval.p_address );
return( p_httpd );
}
......@@ -118,4 +147,3 @@ static inline void httpd_Release( httpd_t *p_httpd )
vlc_object_destroy( p_httpd );
}
}
This diff is collapsed.
......@@ -2,7 +2,7 @@
* httpd.c
*****************************************************************************
* Copyright (C) 2001-2003 VideoLAN
* $Id: httpd.c,v 1.22 2003/07/10 18:29:41 zorglub Exp $
* $Id: httpd.c,v 1.23 2003/07/10 22:24:09 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -25,15 +25,13 @@
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <vlc/vlc.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <vlc/vlc.h>
#include "httpd.h"
#ifdef HAVE_SYS_TIME_H
......@@ -75,10 +73,6 @@
#define HTTPD_CONNECTION_MAX_UNUSED 10000000
#define HTTP_ADMIN_DEFAULT_USERNAME "admin"
#define HTTP_ADMIN_DEFAULT_PASSWORD "admin"
#define FREE( p ) if( p ) { free( p); (p) = NULL; }
#if defined( WIN32 ) || defined( UNDER_CE )
......@@ -96,24 +90,11 @@ static void Close ( vlc_object_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
#define ADMIN_USER_TEXT N_( "Admin page's username" )
#define ADMIN_USER_LONGTEXT N_( \
"You can set the username for the administration page \
If you do not set it, the default username is \"admin\"" )
#define ADMIN_PASS_TEXT N_( "Admin page's password" )
#define ADMIN_PASS_LONGTEXT N_( \
"You can set the password for the administration page \
If you do not set it, the default password is \"admin\"" )
vlc_module_begin();
set_description( _("HTTP 1.0 daemon") );
set_capability( "httpd", 42 );
add_string( "http-admin-user", NULL, NULL,
ADMIN_USER_TEXT, ADMIN_USER_LONGTEXT, VLC_TRUE );
add_string( "http-admin-pass", NULL, NULL,
ADMIN_PASS_TEXT, ADMIN_PASS_LONGTEXT, VLC_TRUE );
set_callbacks( Open, Close );
var_Create( p_module->p_libvlc, "httpd", VLC_VAR_MUTEX );
vlc_module_end();
/*****************************************************************************
......@@ -137,7 +118,7 @@ static httpd_stream_t *RegisterStream ( httpd_t *,
static int SendStream ( httpd_t *, httpd_stream_t *, uint8_t *, int );
static int HeaderStream ( httpd_t *, httpd_stream_t *, uint8_t *, int );
static void UnregisterStream( httpd_t *, httpd_stream_t* );
static int Control ( httpd_t *, int , void*, void* );
/*****************************************************************************
* Internal definitions
*****************************************************************************/
......@@ -268,6 +249,7 @@ static void httpd_ConnnectionClose( httpd_sys_t *, httpd_connection_t * );
static int httpd_UnbanIP( httpd_sys_t *, httpd_banned_ip_t *);
static int httpd_BanIP( httpd_sys_t *, char *);
static httpd_banned_ip_t *httpd_GetbannedIP( httpd_sys_t *, char * );
/*****************************************************************************
* Open:
*****************************************************************************/
......@@ -330,6 +312,7 @@ static int Open( vlc_object_t *p_this )
p_httpd->pf_header_stream = HeaderStream;
p_httpd->pf_send_stream = SendStream;
p_httpd->pf_unregister_stream=UnregisterStream;
p_httpd->pf_control = Control;
return( VLC_SUCCESS );
}
......@@ -957,224 +940,153 @@ static int HeaderStream( httpd_t *p_httpd, httpd_stream_t *p_stream,
return( VLC_SUCCESS );
}
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static int httpd_page_401_get( httpd_file_callback_args_t *p_args,
uint8_t *p_request, int i_request,
uint8_t **pp_data, int *pi_data )
static void httpd_info_add_ss( httpd_info_t *p_info, char *name, char *value )
{
char *p;
p = *pp_data = malloc( 1024 );
p += sprintf( p, "<html>\n" );
p += sprintf( p, "<head>\n" );
p += sprintf( p, "<title>Error 401</title>\n" );
p += sprintf( p, "</head>\n" );
p += sprintf( p, "<body>\n" );
p += sprintf( p, "<h1><center> 401 authentification needed</center></h1>\n" );
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 ) + 1;
return VLC_SUCCESS;
if( p_info->i_count == 0 )
{
p_info->info = malloc( sizeof( httpd_val_t ) );
}
else
{
p_info->info =
realloc( p_info->info,
sizeof( httpd_val_t ) * ( p_info->i_count + 1 ) );
}
p_info->info[p_info->i_count].psz_name = strdup( name );
p_info->info[p_info->i_count].psz_value = strdup( value );
p_info->i_count++;
}
static int httpd_page_404_get( httpd_file_callback_args_t *p_args,
uint8_t *p_request, int i_request,
uint8_t **pp_data, int *pi_data )
{
char *p;
p = *pp_data = malloc( 1024 );
static void httpd_info_add_si( httpd_info_t *p_info, char *name, int i_value )
{
char v[40];
p += sprintf( p, "<html>\n" );
p += sprintf( p, "<head>\n" );
p += sprintf( p, "<title>Error 404</title>\n" );
p += sprintf( p, "</head>\n" );
p += sprintf( p, "<body>\n" );
p += sprintf( p, "<h1><center> 404 Ressource not found</center></h1>\n" );
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" );
sprintf( v, "%d", i_value );
httpd_info_add_ss( p_info, name, v );
}
*pi_data = strlen( *pp_data ) + 1;
static void httpd_info_add_sp( httpd_info_t *p_info, char *name, void *value )
{
char v[40];
return VLC_SUCCESS;
sprintf( v, "%p", value );
httpd_info_add_ss( p_info, name, v );
}
static int _httpd_page_admin_get_status( httpd_file_callback_args_t *p_args,
uint8_t **pp_data, int *pi_data )
static int Control( httpd_t *p_httpd,
int i_query, void *arg1, void *arg2 )
{
httpd_sys_t *p_httpt = (httpd_sys_t*)p_args;
httpd_sys_t *p_httpt = p_httpd->p_sys;
httpd_info_t *p_info;
httpd_connection_t *p_con;
httpd_banned_ip_t *p_ip;
int i;
char *p;
void *id;
/* FIXME FIXME do not use static size FIXME FIXME*/
p = *pp_data = malloc( 8096 );
p += sprintf( p, "<html>\n" );
p += sprintf( p, "<head>\n" );
p += sprintf( p, "<title>VideoLAN Client Stream Output</title>\n" );
p += sprintf( p, "</head>\n" );
p += sprintf( p, "<body>\n" );
p += sprintf( p, "<h1><center>VideoLAN Client Stream Output</center></h1>\n" );
p += sprintf( p, "<h2><center>Admin page</center></h2>\n" );
/* general */
p += sprintf( p, "<h3>General state</h3>\n" );
p += sprintf( p, "<ul>\n" );
p += sprintf( p, "<li>Connection count: %d</li>\n", p_httpt->i_connection_count );
//p += sprintf( p, "<li>Total bandwith: %d</li>\n", -1 );
/*p += sprintf( p, "<li></li>\n" );*/
p += sprintf( p, "<li>Ban count: %d</li>\n", p_httpt->i_banned_ip_count );
p += sprintf( p, "</ul>\n" );
/* ban list */
/* XXX do not lock on ban_lock */
p += sprintf( p, "<h3>Ban list</h3>\n" );
p += sprintf( p, "<table border=\"1\" cellspacing=\"0\" >\n" );
p += sprintf( p, "<tr>\n<th>IP</th>\n<th>Action</th></tr>\n" );
for( p_ip = p_httpt->p_first_banned_ip;p_ip != NULL; p_ip = p_ip->p_next )
{
p += sprintf( p, "<tr>\n" );
p += sprintf( p, "<td>%s</td>\n", p_ip->psz_ip );
p += sprintf( p, "<td><form method=\"get\" action=\"\">"
"<select name=\"action\">"
"<option selected>unban_ip</option>"
"</select>"
"<input type=\"hidden\" name=\"id\" value=\"%s\"/>"
"<input type=\"submit\" value=\"Do it\" />"
"</form></td>\n", p_ip->psz_ip);
p += sprintf( p, "</tr>\n" );
}
p += sprintf( p, "</table>\n" );
/* host list */
vlc_mutex_lock( &p_httpt->host_lock );
p += sprintf( p, "<h3>Host list</h3>\n" );
p += sprintf( p, "<table border=\"1\" cellspacing=\"0\" >\n" );
p += sprintf( p, "<tr>\n<th>Host</th><th>Port</th><th>IP</th>\n</tr>\n" );
for( i = 0; i < p_httpt->i_host_count; i++ )
switch( i_query )
{
p += sprintf( p, "<tr>\n" );
p += sprintf( p, "<td>%s</td>\n", p_httpt->host[i]->psz_host_addr );
p += sprintf( p, "<td>%d</td>\n", p_httpt->host[i]->i_port );
p += sprintf( p, "<td>%s</td>\n", inet_ntoa( p_httpt->host[i]->sock.sin_addr ) );
p += sprintf( p, "</tr>\n" );
}
p += sprintf( p, "</table>\n" );
vlc_mutex_unlock( &p_httpt->host_lock );
/* file list */
/* XXX do not take lock on file_lock */
p += sprintf( p, "<h3>File list</h3>\n" );
p += sprintf( p, "<table border=\"1\" cellspacing=\"0\" >\n" );
p += sprintf( p, "<tr>\n<th>Name</th><th>Mime</th><th>Protected</th><th>Used</th>\n</tr>\n" );
for( i = 0; i < p_httpt->i_file_count; i++ )
{
if( !p_httpt->file[i]->b_stream )
{
p += sprintf( p, "<tr>\n" );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_file );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_mime );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_user ? "Yes" : "No" );
p += sprintf( p, "<td>%d</td>\n", p_httpt->file[i]->i_ref);
p += sprintf( p, "</tr>\n" );
}
}
p += sprintf( p, "</table>\n" );
/* stream list */
/* XXX do not take lock on file_lock */
p += sprintf( p, "<h3>Stream list</h3>\n" );
p += sprintf( p, "<table border=\"1\" cellspacing=\"0\" >\n" );
p += sprintf( p, "<tr>\n<th>Name</th><th>Mime</th><th>Protected</th><th>Used</th>\n</tr>\n" );
case HTTPD_GET_HOSTS:
p_info = arg1;
p_info->i_count = 0;
vlc_mutex_lock( &p_httpt->host_lock );
for( i = 0; i < p_httpt->i_host_count; i++ )
{
httpd_info_add_sp( p_info,
"id", p_httpt->host[i] );
httpd_info_add_ss( p_info,
"host", p_httpt->host[i]->psz_host_addr );
httpd_info_add_ss( p_info,
"ip",
inet_ntoa(p_httpt->host[i]->sock.sin_addr));
httpd_info_add_si( p_info,
"port", p_httpt->host[i]->i_port );
}
vlc_mutex_unlock( &p_httpt->host_lock );
return VLC_SUCCESS;
case HTTPD_GET_URLS:
p_info = arg1;
p_info->i_count = 0;
/* we can't take file_lock */
for( i = 0; i < p_httpt->i_file_count; i++ )
{
httpd_info_add_sp( p_info,
"id", p_httpt->file[i] );
httpd_info_add_si( p_info,
"stream", p_httpt->file[i]->b_stream ? 1 : 0 );
httpd_info_add_ss( p_info,
"url", p_httpt->file[i]->psz_file );
httpd_info_add_ss( p_info,
"mime", p_httpt->file[i]->psz_mime );
httpd_info_add_si( p_info,
"protected", p_httpt->file[i]->psz_user ? 1 : 0 );
httpd_info_add_si( p_info,
"used", p_httpt->file[i]->i_ref );
}
return VLC_SUCCESS;
case HTTPD_GET_CONNECTIONS:
p_info = arg1;
p_info->i_count = 0;
/* we can't take lock */
for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next )
{
httpd_info_add_sp( p_info,
"id", p_con );
httpd_info_add_ss( p_info,
"ip", inet_ntoa( p_con->sock.sin_addr ) );
httpd_info_add_ss( p_info,
"url", p_con->psz_file );
httpd_info_add_si( p_info,
"status", p_con->i_http_error );
}
return VLC_SUCCESS;
case HTTPD_GET_ACL:
p_info = arg1;
p_info->i_count = 0;
return VLC_EGENERIC;
for( i = 0; i < p_httpt->i_file_count; i++ )
{
if( p_httpt->file[i]->b_stream )
{
p += sprintf( p, "<tr>\n" );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_file );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_mime );
p += sprintf( p, "<td>%s</td>\n", p_httpt->file[i]->psz_user ? "Yes" : "No" );
p += sprintf( p, "<td>%d</td>\n", p_httpt->file[i]->i_ref);
p += sprintf( p, "</tr>\n" );
}
}
p += sprintf( p, "</table>\n" );
case HTTPD_SET_CLOSE:
sscanf( arg1, "%p", &id );
fprintf( stderr, "Control: HTTPD_SET_CLOSE: id=%p", id );
/* connection list */
/* XXX do not take lock on connection_lock */
p += sprintf( p, "<h3>Connection list</h3>\n" );
p += sprintf( p, "<table border=\"1\" cellspacing=\"0\" >\n" );
p += sprintf( p, "<tr>\n<th>IP</th><th>Requested File</th><th>Status</th><th>Action</th>\n</tr>\n" );
for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next )
{
if( (void*)p_con == id )
{
/* XXX don't free p_con as it could be the one that it is sending ... */
p_con->i_state = HTTPD_CONNECTION_TO_BE_CLOSED;
return VLC_SUCCESS;
}
}
return VLC_EGENERIC;
for( p_con = p_httpt->p_first_connection;p_con != NULL; p_con = p_con->p_next )
{
p += sprintf( p, "<tr>\n" );
p += sprintf( p, "<td>%s</td>\n", inet_ntoa( p_con->sock.sin_addr ) );
p += sprintf( p, "<td>%s</td>\n", p_con->psz_file );
p += sprintf( p, "<td>%d</td>\n", p_con->i_http_error );
p += sprintf( p, "<td><form method=\"get\" action=\"\">"
"<select name=\"action\">"
"<option selected>close_connection</option>"
"<option>ban_ip</option>"
"<option>close_connection_and_ban_ip</option>"
"</select>"
"<input type=\"hidden\" name=\"id\" value=\"%p\"/>"
"<input type=\"submit\" value=\"Do it\" />"
"</form></td>\n", p_con);
p += sprintf( p, "</tr>\n" );
case HTTPD_SET_ACL:
sscanf( arg1, "%p", &id );
fprintf( stderr, "Control: %p", id );
default:
return VLC_EGENERIC;
}
p += sprintf( p, "</table>\n" );
/* www.videolan.org */
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 ) + 1;
return( VLC_SUCCESS );
}
static int _httpd_page_admin_get_success( httpd_file_callback_args_t *p_args,
uint8_t **pp_data, int *pi_data,
char *psz_msg )
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
/****************************************************************************/
static int httpd_page_401_get( httpd_file_callback_args_t *p_args,
uint8_t *p_request, int i_request,
uint8_t **pp_data, int *pi_data )
{
char *p;
p = *pp_data = malloc( 8096 );
p = *pp_data = malloc( 1024 );
p += sprintf( p, "<html>\n" );
p += sprintf( p, "<head>\n" );
p += sprintf( p, "<title>VideoLAN Client Stream Output</title>\n" );
p += sprintf( p, "<title>Error 401</title>\n" );
p += sprintf( p, "</head>\n" );
p += sprintf( p, "<body>\n" );
p += sprintf( p, "<h1><center>VideoLAN Client Stream Output</center></h1>\n" );
p += sprintf( p, "<p>Success=`%s'</p>", psz_msg );
p += sprintf( p, "<a href=\"admin.html\">Back to admin page</a>\n" );
p += sprintf( p, "<h1><center> 401 authentification needed</center></h1>\n" );
p += sprintf( p, "<hr />\n" );
p += sprintf( p, "<a href=\"http://www.videolan.org\">VideoLAN</a>\n" );
p += sprintf( p, "</body>\n" );
......@@ -1182,27 +1094,22 @@ static int _httpd_page_admin_get_success( httpd_file_callback_args_t *p_args,
*pi_data = strlen( *pp_data ) + 1;
return( VLC_SUCCESS );
return VLC_SUCCESS;
}
static int _httpd_page_admin_get_error( httpd_file_callback_args_t *p_args,
uint8_t **pp_data, int *pi_data,
char *psz_error )
static int httpd_page_404_get( httpd_file_callback_args_t *p_args,
uint8_t *p_request, int i_request,
uint8_t **pp_data, int *pi_data )
{
char *p;
p = *pp_data = malloc( 8096 );
p = *pp_data = malloc( 1024 );
p += sprintf( p, "<html>\n" );
p += sprintf( p, "<head>\n" );
p += sprintf( p, "<title>VideoLAN Client Stream Output</title>\n" );
p += sprintf( p, "<title>Error 404</title>\n" );
p += sprintf( p, "</head>\n" );
p += sprintf( p, "<body>\n" );
p += sprintf( p, "<h1><center>VideoLAN Client Stream Output</center></h1>\n" );
p += sprintf( p, "<p>Error=`%s'</p>", psz_error );
p += sprintf( p, "<a href=\"admin.html\">Back to admin page</a>\n" );
p += sprintf( p, "<h1><center> 404 Ressource not found</center></h1>\n" );
p += sprintf( p, "<hr />\n" );
p += sprintf( p, "<a href=\"http://www.videolan.org\">VideoLAN</a>\n" );
p += sprintf( p, "</body>\n" );
......@@ -1210,154 +1117,10 @@ static int _httpd_page_admin_get_error( httpd_file_callback_args_t *p_args,
*pi_data = strlen( *pp_data ) + 1;
return( VLC_SUCCESS );
}
static void _httpd_uri_extract_value( char *psz_uri, char *psz_name, char *psz_value, int i_value_max )
{
char *p;
p = strstr( psz_uri, psz_name );
if( p )
{
int i_len;
p += strlen( psz_name );
if( *p == '=' ) p++;
if( strchr( p, '&' ) )
{
i_len = strchr( p, '&' ) - p;
}
else
{
i_len = strlen( p );
}
i_len = __MIN( i_value_max - 1, i_len );
if( i_len > 0 )
{
strncpy( psz_value, p, i_len );
psz_value[i_len] = '\0';
}
else