2008-07-23 20:19:23 +00:00
2008-11-16 20:33:53 +00:00
# include <lighttpd/base.h>
# include <lighttpd/plugin_core.h>
# include <lighttpd/profiler.h>
2008-07-23 20:19:23 +00:00
2009-09-15 22:19:06 +00:00
# include <lighttpd/version.h>
2009-10-07 20:49:40 +00:00
# include <lighttpd/http_range_parser.h>
2008-09-18 07:14:57 +00:00
# include <sys/stat.h>
# include <fcntl.h>
2009-07-08 19:06:07 +00:00
static liAction * core_list ( liServer * srv , liPlugin * p , liValue * val ) {
liAction * a ;
2008-07-24 11:25:40 +00:00
guint i ;
UNUSED ( p ) ;
2008-09-26 14:11:08 +00:00
if ( ! val ) {
2008-08-09 15:20:12 +00:00
ERROR ( srv , " %s " , " need parameter " ) ;
return NULL ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type = = LI_VALUE_ACTION ) {
2008-09-26 14:11:08 +00:00
a = val - > data . val_action . action ;
2009-07-09 20:17:24 +00:00
li_action_acquire ( a ) ;
2008-08-06 18:46:42 +00:00
return a ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_LIST ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected list, got %s " , li_value_type_string ( val - > type ) ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2009-07-09 20:17:24 +00:00
a = li_action_new_list ( ) ;
2008-09-26 14:11:08 +00:00
for ( i = 0 ; i < val - > data . list - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
liValue * oa = g_array_index ( val - > data . list , liValue * , i ) ;
if ( oa - > type ! = LI_VALUE_ACTION ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected action at entry %u of list, got %s " , i , li_value_type_string ( oa - > type ) ) ;
li_action_release ( srv , a ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2008-09-26 14:11:08 +00:00
assert ( srv = = oa - > data . val_action . srv ) ;
2009-07-09 20:17:24 +00:00
li_action_acquire ( oa - > data . val_action . action ) ;
2008-09-26 14:11:08 +00:00
g_array_append_val ( a - > data . list , oa - > data . val_action . action ) ;
2008-07-24 11:25:40 +00:00
}
return a ;
}
2009-07-08 19:06:07 +00:00
static liAction * core_when ( liServer * srv , liPlugin * p , liValue * val ) {
liValue * val_cond , * val_act , * val_act_else ;
liAction * a , * act = NULL , * act_else = NULL ;
2008-07-24 11:25:40 +00:00
UNUSED ( p ) ;
2008-07-25 12:09:03 +00:00
2008-09-26 14:11:08 +00:00
if ( ! val ) {
2008-08-09 15:20:12 +00:00
ERROR ( srv , " %s " , " need parameter " ) ;
return NULL ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_LIST ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected list, got %s " , li_value_type_string ( val - > type ) ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2008-09-26 14:11:08 +00:00
if ( val - > data . list - > len = = 2 ) {
val_act_else = NULL ;
2008-08-27 14:39:30 +00:00
act_else = NULL ;
2008-09-26 14:11:08 +00:00
} else if ( val - > data . list - > len = = 3 ) {
2009-07-08 19:06:07 +00:00
val_act_else = g_array_index ( val - > data . list , liValue * , 2 ) ;
2008-08-27 14:39:30 +00:00
} else {
2008-09-26 14:11:08 +00:00
ERROR ( srv , " expected list with length 2 or 3, has length %u " , val - > data . list - > len ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2009-07-08 19:06:07 +00:00
val_cond = g_array_index ( val - > data . list , liValue * , 0 ) ;
val_act = g_array_index ( val - > data . list , liValue * , 1 ) ;
2008-08-27 14:39:30 +00:00
2009-07-08 19:06:07 +00:00
if ( val_cond - > type ! = LI_VALUE_CONDITION ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected condition as first parameter, got %s " , li_value_type_string ( val_cond - > type ) ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2009-07-08 19:06:07 +00:00
if ( val_act - > type = = LI_VALUE_NONE ) {
2009-01-10 13:46:11 +00:00
act = NULL ;
2009-07-08 19:06:07 +00:00
} else if ( val_act - > type = = LI_VALUE_ACTION ) {
2009-01-10 13:46:11 +00:00
act = val_act - > data . val_action . action ;
} else {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected action as second parameter, got %s " , li_value_type_string ( val_act - > type ) ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
}
2009-01-10 13:46:11 +00:00
if ( val_act_else ) {
2009-07-08 19:06:07 +00:00
if ( val_act_else - > type = = LI_VALUE_NONE ) {
2009-01-10 13:46:11 +00:00
act_else = NULL ;
2009-07-08 19:06:07 +00:00
} else if ( val_act_else - > type = = LI_VALUE_ACTION ) {
2009-01-10 13:46:11 +00:00
act_else = val_act_else - > data . val_action . action ;
} else {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected action as third parameter, got %s " , li_value_type_string ( val_act_else - > type ) ) ;
2009-01-10 13:46:11 +00:00
return NULL ;
}
2008-08-27 14:39:30 +00:00
}
2009-07-09 20:17:24 +00:00
li_condition_acquire ( val_cond - > data . val_cond . cond ) ;
if ( act ) li_action_acquire ( act ) ;
if ( act_else ) li_action_acquire ( act_else ) ;
a = li_action_new_condition ( val_cond - > data . val_cond . cond , act , act_else ) ;
2008-07-24 11:25:40 +00:00
return a ;
}
2009-07-08 19:06:07 +00:00
static liAction * core_set ( liServer * srv , liPlugin * p , liValue * val ) {
liValue * val_val , * val_name ;
liAction * a ;
2008-08-08 16:49:00 +00:00
UNUSED ( p ) ;
2008-09-26 14:11:08 +00:00
if ( ! val ) {
2008-08-09 15:20:12 +00:00
ERROR ( srv , " %s " , " need parameter " ) ;
return NULL ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_LIST ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected list, got %s " , li_value_type_string ( val - > type ) ) ;
2008-08-08 16:49:00 +00:00
return NULL ;
}
2008-09-26 14:11:08 +00:00
if ( val - > data . list - > len ! = 2 ) {
ERROR ( srv , " expected list with length 2, has length %u " , val - > data . list - > len ) ;
2008-08-08 16:49:00 +00:00
return NULL ;
}
2009-07-08 19:06:07 +00:00
val_name = g_array_index ( val - > data . list , liValue * , 0 ) ;
val_val = g_array_index ( val - > data . list , liValue * , 1 ) ;
if ( val_name - > type ! = LI_VALUE_STRING ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected string as first parameter, got %s " , li_value_type_string ( val_name - > type ) ) ;
2008-08-08 16:49:00 +00:00
return NULL ;
}
2009-07-09 20:17:24 +00:00
a = li_option_action ( srv , val_name - > data . string - > str , val_val ) ;
2008-08-08 16:49:00 +00:00
return a ;
2009-06-25 12:22:54 +00:00
}
2008-08-08 16:49:00 +00:00
2009-07-08 19:06:07 +00:00
static gboolean core_setup_set ( liServer * srv , liPlugin * p , liValue * val ) {
liValue * val_val , * val_name ;
2008-10-25 12:53:57 +00:00
UNUSED ( p ) ;
if ( ! val ) {
ERROR ( srv , " %s " , " need parameter " ) ;
return FALSE ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_LIST ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected list, got %s " , li_value_type_string ( val - > type ) ) ;
2008-10-25 12:53:57 +00:00
return FALSE ;
}
if ( val - > data . list - > len ! = 2 ) {
ERROR ( srv , " expected list with length 2, has length %u " , val - > data . list - > len ) ;
return FALSE ;
}
2009-07-08 19:06:07 +00:00
val_name = g_array_index ( val - > data . list , liValue * , 0 ) ;
val_val = g_array_index ( val - > data . list , liValue * , 1 ) ;
if ( val_name - > type ! = LI_VALUE_STRING ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " expected string as first parameter, got %s " , li_value_type_string ( val_name - > type ) ) ;
2008-10-25 12:53:57 +00:00
return FALSE ;
}
2009-07-09 20:17:24 +00:00
return li_plugin_set_default_option ( srv , val_name - > data . string - > str , val_val ) ;
2008-10-25 12:53:57 +00:00
}
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_docroot ( liVRequest * vr , gpointer param , gpointer * context ) {
2008-12-09 23:23:27 +00:00
UNUSED ( context ) ;
2008-08-09 15:20:12 +00:00
2009-01-05 21:24:54 +00:00
g_string_truncate ( vr - > physical . doc_root , 0 ) ;
g_string_append_len ( vr - > physical . doc_root , GSTR_LEN ( ( GString * ) param ) ) ;
2009-10-02 10:13:37 +00:00
if ( CORE_OPTION ( LI_CORE_OPTION_DEBUG_REQUEST_HANDLING ) . boolean ) {
VR_DEBUG ( vr , " docroot: %s " , vr - > physical . doc_root - > str ) ;
}
2008-08-09 15:20:12 +00:00
2009-01-12 00:02:39 +00:00
/* build physical path: docroot + uri.path */
g_string_truncate ( vr - > physical . path , 0 ) ;
g_string_append_len ( vr - > physical . path , GSTR_LEN ( vr - > physical . doc_root ) ) ;
2009-09-15 13:31:00 +00:00
if ( vr - > request . uri . path - > len = = 0 | | vr - > request . uri . path - > str [ 0 ] ! = ' / ' )
li_path_append_slash ( vr - > physical . path ) ;
2009-01-12 00:02:39 +00:00
g_string_append_len ( vr - > physical . path , GSTR_LEN ( vr - > request . uri . path ) ) ;
2009-10-02 10:13:37 +00:00
if ( CORE_OPTION ( LI_CORE_OPTION_DEBUG_REQUEST_HANDLING ) . boolean ) {
VR_DEBUG ( vr , " physical path: %s " , vr - > physical . path - > str ) ;
}
2009-01-12 00:02:39 +00:00
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-01-05 21:24:54 +00:00
}
2009-07-08 19:06:07 +00:00
static void core_docroot_free ( liServer * srv , gpointer param ) {
2009-01-05 21:24:54 +00:00
UNUSED ( srv ) ;
g_string_free ( param , TRUE ) ;
}
2009-07-08 19:06:07 +00:00
static liAction * core_docroot ( liServer * srv , liPlugin * p , liValue * val ) {
2009-01-05 21:24:54 +00:00
UNUSED ( p ) ;
2009-07-08 19:06:07 +00:00
if ( ! val | | val - > type ! = LI_VALUE_STRING ) {
2009-01-05 21:24:54 +00:00
ERROR ( srv , " %s " , " docroot action expects a string parameter " ) ;
return NULL ;
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_docroot , NULL , core_docroot_free , li_value_extract ( val ) . string ) ;
2009-01-05 21:24:54 +00:00
}
2009-06-24 19:14:09 +00:00
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_index ( liVRequest * vr , gpointer param , gpointer * context ) {
liHandlerResult res ;
2009-06-24 19:14:09 +00:00
guint i ;
struct stat st ;
gint err ;
2009-06-25 20:13:58 +00:00
GString * file , * tmp_docroot , * tmp_path ;
2009-06-24 19:14:09 +00:00
GArray * files = param ;
UNUSED ( context ) ;
if ( ! vr - > physical . doc_root - > len ) {
VR_ERROR ( vr , " %s " , " no docroot specified yet but index action called " ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_ERROR ;
2009-06-24 19:14:09 +00:00
}
2009-09-08 22:40:12 +00:00
/* need trailing slash */
if ( vr - > request . uri . path - > len = = 0 | | vr - > request . uri . path - > str [ vr - > request . uri . path - > len - 1 ] ! = ' / ' ) return LI_HANDLER_GO_ON ;
2009-06-24 19:14:09 +00:00
2009-07-09 20:17:24 +00:00
res = li_stat_cache_get ( vr , vr - > physical . path , & st , & err , NULL ) ;
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_WAIT_FOR_EVENT )
return LI_HANDLER_WAIT_FOR_EVENT ;
2009-06-24 19:14:09 +00:00
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_ERROR ) {
2009-06-24 19:14:09 +00:00
/* we ignore errors here so a later action can deal with it (e.g. 'static') */
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-06-24 19:14:09 +00:00
}
if ( ! S_ISDIR ( st . st_mode ) )
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-06-24 19:14:09 +00:00
2009-06-25 20:13:58 +00:00
/* we use two temporary strings here, one to append to docroot and one to append to physical path */
tmp_docroot = vr - > wrk - > tmp_str ;
g_string_truncate ( tmp_docroot , 0 ) ;
g_string_append_len ( vr - > wrk - > tmp_str , GSTR_LEN ( vr - > physical . doc_root ) ) ;
tmp_path = g_string_new_len ( GSTR_LEN ( vr - > physical . path ) ) ;
2009-06-24 19:14:09 +00:00
/* loop through the list to find a possible index file */
for ( i = 0 ; i < files - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
file = g_array_index ( files , liValue * , i ) - > data . string ;
2009-06-24 19:14:09 +00:00
2009-06-25 20:13:58 +00:00
if ( file - > str [ 0 ] = = ' / ' ) {
/* entries beginning with a slash shall be looked up directly at the docroot */
g_string_truncate ( tmp_docroot , vr - > physical . doc_root - > len ) ;
g_string_append_len ( tmp_docroot , GSTR_LEN ( file ) ) ;
2009-07-09 20:17:24 +00:00
res = li_stat_cache_get ( vr , tmp_docroot , & st , & err , NULL ) ;
2009-06-25 20:13:58 +00:00
} else {
g_string_truncate ( tmp_path , vr - > physical . path - > len ) ;
g_string_append_len ( tmp_path , GSTR_LEN ( file ) ) ;
2009-07-09 20:17:24 +00:00
res = li_stat_cache_get ( vr , tmp_path , & st , & err , NULL ) ;
2009-06-25 20:13:58 +00:00
}
2009-06-24 19:14:09 +00:00
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_WAIT_FOR_EVENT ) {
2009-06-25 20:13:58 +00:00
g_string_free ( tmp_path , TRUE ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_WAIT_FOR_EVENT ;
2009-06-25 20:13:58 +00:00
}
2009-06-24 19:14:09 +00:00
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_GO_ON ) {
2009-06-24 19:14:09 +00:00
/* file exists. change physical path */
2009-09-08 22:40:12 +00:00
if ( file - > str [ 0 ] = = ' / ' ) {
2009-06-25 20:13:58 +00:00
g_string_truncate ( vr - > physical . path , vr - > physical . doc_root - > len ) ;
2009-09-08 22:40:12 +00:00
g_string_truncate ( vr - > request . uri . path , 0 ) ;
}
2009-06-25 20:13:58 +00:00
2009-06-24 19:14:09 +00:00
g_string_append_len ( vr - > physical . path , GSTR_LEN ( file ) ) ;
2009-09-08 22:40:12 +00:00
g_string_append_len ( vr - > request . uri . path , GSTR_LEN ( file ) ) ;
2009-06-24 19:14:09 +00:00
2009-07-08 19:06:07 +00:00
if ( CORE_OPTION ( LI_CORE_OPTION_DEBUG_REQUEST_HANDLING ) . boolean ) {
2009-06-24 19:14:09 +00:00
VR_DEBUG ( vr , " using index file: '%s' " , file - > str ) ;
}
2009-06-25 20:13:58 +00:00
g_string_free ( tmp_path , TRUE ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-06-24 19:14:09 +00:00
}
}
2009-06-25 20:13:58 +00:00
g_string_free ( tmp_path , TRUE ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-06-24 19:14:09 +00:00
}
2009-07-08 19:06:07 +00:00
static void core_index_free ( liServer * srv , gpointer param ) {
2009-06-24 19:14:09 +00:00
guint i ;
GArray * files = param ;
UNUSED ( srv ) ;
for ( i = 0 ; i < files - > len ; i + + )
2009-07-09 20:17:24 +00:00
li_value_free ( g_array_index ( files , liValue * , i ) ) ;
2009-06-24 19:14:09 +00:00
g_array_free ( files , TRUE ) ;
}
2009-07-08 19:06:07 +00:00
static liAction * core_index ( liServer * srv , liPlugin * p , liValue * val ) {
2009-06-24 19:14:09 +00:00
GArray * files ;
guint i ;
UNUSED ( p ) ;
2009-07-08 19:06:07 +00:00
if ( ! val | | val - > type ! = LI_VALUE_LIST ) {
2009-06-24 19:14:09 +00:00
ERROR ( srv , " %s " , " index action expects a list of strings as parameter " ) ;
return NULL ;
}
files = val - > data . list ;
for ( i = 0 ; i < files - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
if ( g_array_index ( files , liValue * , i ) - > type ! = LI_VALUE_STRING ) {
2009-06-24 19:14:09 +00:00
ERROR ( srv , " %s " , " index action expects a list of strings as parameter " ) ;
return NULL ;
}
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_index , NULL , core_index_free , li_value_extract ( val ) . list ) ;
2009-06-24 19:14:09 +00:00
}
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_static ( liVRequest * vr , gpointer param , gpointer * context ) {
2009-09-17 07:54:34 +00:00
int fd = - 1 ;
2009-03-26 22:05:17 +00:00
struct stat st ;
int err ;
2009-07-08 19:06:07 +00:00
liHandlerResult res ;
2009-10-07 20:49:40 +00:00
static const gchar boundary [ ] = " fkj49sn38dcn3 " ;
2009-03-01 20:16:58 +00:00
2009-01-05 21:24:54 +00:00
UNUSED ( param ) ;
UNUSED ( context ) ;
2009-03-17 13:21:20 +00:00
switch ( vr - > request . http_method ) {
2009-07-08 19:06:07 +00:00
case LI_HTTP_METHOD_GET :
case LI_HTTP_METHOD_HEAD :
2009-03-17 13:21:20 +00:00
break ;
default :
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-03-17 13:21:20 +00:00
}
2009-07-09 20:17:24 +00:00
if ( li_vrequest_is_handled ( vr ) ) return LI_HANDLER_GO_ON ;
2009-03-17 13:21:20 +00:00
2009-07-08 19:06:07 +00:00
if ( vr - > physical . path - > len = = 0 ) return LI_HANDLER_GO_ON ;
2008-08-09 15:20:12 +00:00
2009-07-09 20:17:24 +00:00
res = li_stat_cache_get ( vr , vr - > physical . path , & st , & err , & fd ) ;
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_WAIT_FOR_EVENT )
2009-03-26 22:05:17 +00:00
return res ;
2008-08-09 15:20:12 +00:00
2009-07-08 19:06:07 +00:00
if ( CORE_OPTION ( LI_CORE_OPTION_DEBUG_REQUEST_HANDLING ) . boolean ) {
2009-03-17 13:21:20 +00:00
VR_DEBUG ( vr , " try serving static file: '%s' " , vr - > physical . path - > str ) ;
}
2009-01-11 23:24:27 +00:00
2009-07-08 19:06:07 +00:00
if ( res = = LI_HANDLER_ERROR ) {
2009-03-26 22:05:17 +00:00
/* open or fstat failed */
2009-03-26 22:33:28 +00:00
if ( fd ! = - 1 )
2009-03-26 22:16:41 +00:00
close ( fd ) ;
2009-07-09 20:17:24 +00:00
if ( ! li_vrequest_handle_direct ( vr ) ) {
2009-07-08 19:06:07 +00:00
return LI_HANDLER_ERROR ;
2009-03-26 22:05:17 +00:00
}
2009-03-01 20:16:58 +00:00
2009-03-26 22:05:17 +00:00
switch ( err ) {
2009-03-01 20:16:58 +00:00
case ENOENT :
2009-03-17 13:21:20 +00:00
case ENOTDIR :
2009-03-26 22:05:17 +00:00
vr - > response . http_status = 404 ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-03-01 20:16:58 +00:00
case EACCES :
2009-03-17 13:21:20 +00:00
vr - > response . http_status = 403 ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-03-01 20:16:58 +00:00
default :
2009-03-26 22:05:17 +00:00
VR_ERROR ( vr , " stat() or open() for '%s' failed: %s " , vr - > physical . path - > str , g_strerror ( err ) ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_ERROR ;
2009-03-17 13:21:20 +00:00
}
2009-03-26 22:05:17 +00:00
} else if ( S_ISDIR ( st . st_mode ) ) {
2009-03-26 22:33:28 +00:00
if ( fd ! = - 1 )
2009-03-26 22:16:41 +00:00
close ( fd ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-03-26 22:05:17 +00:00
} else if ( ! S_ISREG ( st . st_mode ) ) {
2009-07-08 19:06:07 +00:00
if ( CORE_OPTION ( LI_CORE_OPTION_DEBUG_REQUEST_HANDLING ) . boolean ) {
2009-03-17 13:21:20 +00:00
VR_DEBUG ( vr , " not a regular file: '%s' " , vr - > physical . path - > str ) ;
2009-03-01 20:16:58 +00:00
}
2009-03-26 22:16:41 +00:00
2009-03-26 22:33:28 +00:00
if ( fd ! = - 1 )
2009-03-26 22:16:41 +00:00
close ( fd ) ;
2009-07-09 20:17:24 +00:00
if ( ! li_vrequest_handle_direct ( vr ) ) {
2009-07-08 19:06:07 +00:00
return LI_HANDLER_ERROR ;
2009-03-18 14:30:13 +00:00
}
2009-03-17 13:21:20 +00:00
vr - > response . http_status = 403 ;
2008-08-09 15:20:12 +00:00
} else {
2009-10-07 20:49:40 +00:00
const GString * mime_str ;
2009-03-17 13:21:20 +00:00
gboolean cachable ;
2009-10-07 20:49:40 +00:00
gboolean ranged_response = FALSE ;
liHttpHeader * hh_range ;
liChunkFile * cf ;
static const GString default_mime_str = { CONST_STR_LEN ( " application/octet-stream " ) , 0 } ;
2008-08-09 15:20:12 +00:00
# ifdef FD_CLOEXEC
fcntl ( fd , F_SETFD , FD_CLOEXEC ) ;
# endif
2009-01-29 16:36:30 +00:00
2009-07-09 20:17:24 +00:00
if ( ! li_vrequest_handle_direct ( vr ) ) {
2008-09-08 00:28:55 +00:00
close ( fd ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_ERROR ;
2009-03-17 13:21:20 +00:00
}
2009-07-09 20:17:24 +00:00
li_etag_set_header ( vr , & st , & cachable ) ;
2009-03-17 13:21:20 +00:00
if ( cachable ) {
vr - > response . http_status = 304 ;
2009-03-18 03:12:51 +00:00
close ( fd ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2008-09-08 00:28:55 +00:00
}
2009-03-17 13:21:20 +00:00
2009-10-07 20:49:40 +00:00
cf = li_chunkfile_new ( NULL , fd , FALSE ) ;
2009-07-09 20:17:24 +00:00
mime_str = li_mimetype_get ( vr , vr - > physical . path ) ;
2009-10-07 20:49:40 +00:00
if ( ! mime_str ) mime_str = & default_mime_str ;
if ( CORE_OPTION ( LI_CORE_OPTION_STATIC_RANGE_REQUESTS ) . boolean ) {
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Accept-Ranges " ) , CONST_STR_LEN ( " bytes " ) ) ;
hh_range = li_http_header_lookup ( vr - > request . headers , CONST_STR_LEN ( " range " ) ) ;
if ( hh_range ) {
/* TODO: Check If-Range: header */
GString range_str = { HEADER_VALUE_LEN ( hh_range ) , 0 } ;
liParseHttpRangeState rs ;
gboolean is_multipart = FALSE , done = FALSE ;
li_parse_http_range_init ( & rs , & range_str , st . st_size ) ;
do {
switch ( li_parse_http_range_next ( & rs ) ) {
case LI_PARSE_HTTP_RANGE_OK :
if ( ! is_multipart & & ! rs . last_range ) {
is_multipart = TRUE ;
}
2009-10-07 20:53:50 +00:00
g_string_printf ( vr - > wrk - > tmp_str , " bytes % " G_GINT64_FORMAT " -% " G_GINT64_FORMAT " /% " G_GINT64_FORMAT , rs . range_start , rs . range_end , ( goffset ) st . st_size ) ;
2009-10-07 20:49:40 +00:00
if ( is_multipart ) {
GString * subheader = g_string_sized_new ( 1023 ) ;
g_string_append_printf ( subheader , " \r \n --%s \r \n Content-Type: %s \r \n Content-Range: %s \r \n \r \n " , boundary , mime_str - > str , vr - > wrk - > tmp_str - > str ) ;
li_chunkqueue_append_string ( vr - > out , subheader ) ;
li_chunkqueue_append_chunkfile ( vr - > out , cf , rs . range_start , rs . range_length ) ;
} else {
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Content-Range " ) , GSTR_LEN ( vr - > wrk - > tmp_str ) ) ;
li_chunkqueue_append_chunkfile ( vr - > out , cf , rs . range_start , rs . range_length ) ;
}
break ;
case LI_PARSE_HTTP_RANGE_DONE :
ranged_response = TRUE ;
done = TRUE ;
vr - > response . http_status = 206 ;
if ( is_multipart ) {
GString * subheader = g_string_sized_new ( 1023 ) ;
g_string_append_printf ( subheader , " \r \n --%s-- \r \n " , boundary ) ;
li_chunkqueue_append_string ( vr - > out , subheader ) ;
g_string_printf ( vr - > wrk - > tmp_str , " multipart/byteranges; boundary=%s " , boundary ) ;
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Content-Type " ) , GSTR_LEN ( vr - > wrk - > tmp_str ) ) ;
} else {
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Content-Type " ) , GSTR_LEN ( mime_str ) ) ;
}
break ;
case LI_PARSE_HTTP_RANGE_INVALID :
done = TRUE ;
li_chunkqueue_reset ( vr - > out ) ;
break ;
case LI_PARSE_HTTP_RANGE_NOT_SATISFIABLE :
ranged_response = TRUE ;
done = TRUE ;
li_chunkqueue_reset ( vr - > out ) ; vr - > out - > is_closed = TRUE ;
2009-10-07 20:53:50 +00:00
g_string_printf ( vr - > wrk - > tmp_str , " bytes */% " G_GINT64_FORMAT , ( goffset ) st . st_size ) ;
2009-10-07 20:49:40 +00:00
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Content-Range " ) , GSTR_LEN ( vr - > wrk - > tmp_str ) ) ;
vr - > response . http_status = 416 ;
break ;
}
} while ( ! done ) ;
li_parse_http_range_clear ( & rs ) ;
}
}
if ( ! ranged_response ) {
vr - > response . http_status = 200 ;
2009-07-09 20:17:24 +00:00
li_http_header_overwrite ( vr - > response . headers , CONST_STR_LEN ( " Content-Type " ) , GSTR_LEN ( mime_str ) ) ;
2009-10-07 21:07:05 +00:00
li_chunkqueue_append_chunkfile ( vr - > out , cf , 0 , st . st_size ) ;
2009-10-07 20:49:40 +00:00
}
li_chunkfile_release ( cf ) ;
2008-08-09 15:20:12 +00:00
}
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2008-07-23 20:25:16 +00:00
}
2009-07-08 19:06:07 +00:00
static liAction * core_static ( liServer * srv , liPlugin * p , liValue * val ) {
2008-07-24 11:25:40 +00:00
UNUSED ( p ) ;
2008-09-26 14:11:08 +00:00
if ( val ) {
2008-07-23 20:25:16 +00:00
ERROR ( srv , " %s " , " static action doesn't have parameters " ) ;
2008-07-24 11:25:40 +00:00
return NULL ;
2008-07-23 20:25:16 +00:00
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_static , NULL , NULL , NULL ) ;
2008-07-23 20:25:16 +00:00
}
2008-07-23 20:19:23 +00:00
2009-04-16 15:02:53 +00:00
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_status ( liVRequest * vr , gpointer param , gpointer * context ) {
2009-04-16 15:02:53 +00:00
UNUSED ( param ) ;
UNUSED ( context ) ;
vr - > response . http_status = GPOINTER_TO_INT ( param ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-04-16 15:02:53 +00:00
}
2009-07-08 19:06:07 +00:00
static liAction * core_status ( liServer * srv , liPlugin * p , liValue * val ) {
2009-04-16 15:02:53 +00:00
gpointer ptr ;
UNUSED ( p ) ;
2009-07-16 10:57:11 +00:00
if ( ! val | | val - > type ! = LI_VALUE_NUMBER ) {
2009-10-07 19:08:28 +00:00
ERROR ( srv , " %s " , " set_status action expects a number as parameter " ) ;
2009-04-16 15:02:53 +00:00
return NULL ;
}
2009-07-09 20:17:24 +00:00
ptr = GINT_TO_POINTER ( ( gint ) li_value_extract ( val ) . number ) ;
2009-04-16 15:02:53 +00:00
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_status , NULL , NULL , ptr ) ;
2009-04-16 15:02:53 +00:00
}
2009-07-08 19:06:07 +00:00
static void core_log_write_free ( liServer * srv , gpointer param ) {
2009-03-06 18:19:36 +00:00
UNUSED ( srv ) ;
g_string_free ( param , TRUE ) ;
}
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_log_write ( liVRequest * vr , gpointer param , gpointer * context ) {
2009-01-06 23:01:20 +00:00
GString * msg = param ;
UNUSED ( context ) ;
VR_INFO ( vr , " %s " , msg - > str ) ;
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2009-01-06 23:01:20 +00:00
}
2009-07-08 19:06:07 +00:00
static liAction * core_log_write ( liServer * srv , liPlugin * p , liValue * val ) {
2009-01-06 23:01:20 +00:00
UNUSED ( p ) ;
2009-07-08 19:06:07 +00:00
if ( ! val | | val - > type ! = LI_VALUE_STRING ) {
2009-01-06 23:01:20 +00:00
ERROR ( srv , " %s " , " log.write expects a string parameter " ) ;
return NULL ;
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_log_write , NULL , core_log_write_free , li_value_extract ( val ) . string ) ;
2009-01-06 23:01:20 +00:00
}
2008-08-06 18:46:42 +00:00
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_blank ( liVRequest * vr , gpointer param , gpointer * context ) {
2008-08-16 22:23:52 +00:00
UNUSED ( param ) ;
2008-12-09 23:23:27 +00:00
UNUSED ( context ) ;
2008-08-16 22:23:52 +00:00
2009-07-09 20:17:24 +00:00
if ( ! li_vrequest_handle_direct ( vr ) ) return LI_HANDLER_GO_ON ;
2008-08-16 22:23:52 +00:00
2008-10-25 12:53:57 +00:00
vr - > response . http_status = 200 ;
2008-08-16 22:23:52 +00:00
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2008-08-16 22:23:52 +00:00
}
2009-07-08 19:06:07 +00:00
static liAction * core_blank ( liServer * srv , liPlugin * p , liValue * val ) {
2008-08-16 22:23:52 +00:00
UNUSED ( p ) ;
2008-09-26 14:11:08 +00:00
if ( val ) {
2009-03-15 23:37:46 +00:00
ERROR ( srv , " %s " , " 'blank' action doesn't have parameters " ) ;
2008-08-16 22:23:52 +00:00
return NULL ;
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_blank , NULL , NULL , NULL ) ;
2008-08-16 22:23:52 +00:00
}
2009-07-08 19:06:07 +00:00
static liHandlerResult core_handle_profile_mem ( liVRequest * vr , gpointer param , gpointer * context ) {
2008-10-25 16:01:02 +00:00
UNUSED ( vr ) ;
2008-10-17 16:08:40 +00:00
UNUSED ( param ) ;
2008-12-09 23:23:27 +00:00
UNUSED ( context ) ;
2008-10-17 16:08:40 +00:00
2008-10-17 22:06:06 +00:00
/*g_mem_profile();*/
profiler_dump ( ) ;
2008-10-17 16:08:40 +00:00
2009-07-08 19:06:07 +00:00
return LI_HANDLER_GO_ON ;
2008-10-17 16:08:40 +00:00
}
2009-07-08 19:06:07 +00:00
static liAction * core_profile_mem ( liServer * srv , liPlugin * p , liValue * val ) {
2008-10-17 16:08:40 +00:00
UNUSED ( p ) ;
if ( val ) {
ERROR ( srv , " %s " , " 'profile_mem' action doesn't have parameters " ) ;
return NULL ;
}
2009-07-09 20:17:24 +00:00
return li_action_new_function ( core_handle_profile_mem , NULL , NULL , NULL ) ;
2008-10-17 16:08:40 +00:00
}
2009-07-08 19:06:07 +00:00
static gboolean core_listen ( liServer * srv , liPlugin * p , liValue * val ) {
2008-09-27 15:06:43 +00:00
GString * ipstr ;
2008-07-24 11:25:40 +00:00
UNUSED ( p ) ;
2008-09-27 15:06:43 +00:00
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_STRING ) {
2008-07-23 20:19:23 +00:00
ERROR ( srv , " %s " , " listen expects a string as parameter " ) ;
return FALSE ;
}
2008-12-20 15:25:02 +00:00
ipstr = val - > data . string ;
2009-09-08 17:09:39 +00:00
li_angel_listen ( srv , ipstr , NULL , NULL ) ;
2008-12-20 15:25:02 +00:00
2008-07-23 20:19:23 +00:00
return TRUE ;
}
2008-08-13 17:57:19 +00:00
2009-07-08 19:06:07 +00:00
static gboolean core_workers ( liServer * srv , liPlugin * p , liValue * val ) {
2008-09-09 09:31:08 +00:00
gint workers ;
UNUSED ( p ) ;
2008-09-26 14:11:08 +00:00
workers = val - > data . number ;
2009-07-08 19:06:07 +00:00
if ( val - > type ! = LI_VALUE_NUMBER | | workers < 1 ) {
2008-09-09 09:31:08 +00:00
ERROR ( srv , " %s " , " workers expects a positive integer as parameter " ) ;
return FALSE ;
}
if ( srv - > worker_count ! = 0 ) {
ERROR ( srv , " workers already called with '%i', overwriting " , srv - > worker_count ) ;
}
srv - > worker_count = workers ;
return TRUE ;
}
2009-07-08 19:06:07 +00:00
static gboolean core_module_load ( liServer * srv , liPlugin * p , liValue * val ) {
2009-07-09 20:17:24 +00:00
liValue * mods = li_value_new_list ( ) ;
2009-10-04 14:58:31 +00:00
2008-10-22 14:54:44 +00:00
UNUSED ( p ) ;
if ( ! g_module_supported ( ) ) {
ERROR ( srv , " %s " , " module loading not supported on this platform " ) ;
2009-07-09 20:17:24 +00:00
li_value_free ( mods ) ;
2008-10-22 14:54:44 +00:00
return FALSE ;
}
2009-07-08 19:06:07 +00:00
if ( val - > type = = LI_VALUE_STRING ) {
2008-10-22 14:54:44 +00:00
/* load only one module */
2009-07-09 20:17:24 +00:00
liValue * name = li_value_new_string ( li_value_extract ( val ) . string ) ;
2008-10-22 14:54:44 +00:00
g_array_append_val ( mods - > data . list , name ) ;
2009-07-08 19:06:07 +00:00
} else if ( val - > type = = LI_VALUE_LIST ) {
2008-10-22 14:54:44 +00:00
/* load a list of modules */
for ( guint i = 0 ; i < val - > data . list - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
liValue * v = g_array_index ( val - > data . list , liValue * , i ) ;
if ( v - > type ! = LI_VALUE_STRING ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " module_load takes either a string or a list of strings as parameter, list with %s entry given " , li_value_type_string ( v - > type ) ) ;
li_value_free ( mods ) ;
2008-10-22 14:54:44 +00:00
return FALSE ;
}
}
2009-03-06 17:52:48 +00:00
g_array_free ( mods - > data . list , TRUE ) ;
2009-07-09 20:17:24 +00:00
mods - > data . list = li_value_extract ( val ) . list ;
2008-10-22 14:54:44 +00:00
} else {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " module_load takes either a string or a list of strings as parameter, %s given " , li_value_type_string ( val - > type ) ) ;
2008-10-22 14:54:44 +00:00
return FALSE ;
}
/* parameter types ok, load modules */
for ( guint i = 0 ; i < mods - > data . list - > len ; i + + ) {
2009-10-04 15:00:19 +00:00
GString * name = g_array_index ( mods - > data . list , liValue * , i ) - > data . string ;
2009-10-04 14:58:31 +00:00
if ( li_module_lookup ( srv - > modules , name - > str ) ) {
DEBUG ( srv , " module_load: module '%s' already loaded " , name - > str ) ;
continue ;
}
2009-07-09 20:17:24 +00:00
if ( ! li_module_load ( srv - > modules , name - > str ) ) {
2008-10-22 14:54:44 +00:00
ERROR ( srv , " could not load module '%s': %s " , name - > str , g_module_error ( ) ) ;
2009-07-09 20:17:24 +00:00
li_value_free ( mods ) ;
2008-10-22 14:54:44 +00:00
return FALSE ;
}
2008-12-30 13:24:33 +00:00
DEBUG ( srv , " loaded module '%s' " , name - > str ) ;
2008-10-22 14:54:44 +00:00
}
2009-07-09 20:17:24 +00:00
li_value_free ( mods ) ;
2008-10-22 14:54:44 +00:00
return TRUE ;
}
2009-07-08 19:06:07 +00:00
static gboolean core_io_timeout ( liServer * srv , liPlugin * p , liValue * val ) {
2008-11-10 14:39:03 +00:00
UNUSED ( p ) ;
2009-07-08 19:06:07 +00:00
if ( ! val | | val - > type ! = LI_VALUE_NUMBER | | val - > data . number < 1 ) {
2009-10-07 19:08:28 +00:00
ERROR ( srv , " %s " , " io.timeout expects a positive number as parameter " ) ;
2008-11-10 14:39:03 +00:00
return FALSE ;
}
2009-07-09 20:17:24 +00:00
srv - > io_timeout = li_value_extract ( val ) . number ;
2008-11-10 14:39:03 +00:00
return TRUE ;
}
2009-07-08 19:06:07 +00:00
static gboolean core_stat_cache_ttl ( liServer * srv , liPlugin * p , liValue * val ) {
2009-03-04 01:54:38 +00:00
UNUSED ( p ) ;
2009-07-08 19:06:07 +00:00
if ( ! val | | val - > type ! = LI_VALUE_NUMBER | | val - > data . number < 1 ) {
2009-03-04 01:54:38 +00:00
ERROR ( srv , " %s " , " stat_cache.ttl expects a positive number as parameter " ) ;
return FALSE ;
}
2009-07-09 20:17:24 +00:00
srv - > stat_cache_ttl = ( gdouble ) li_value_extract ( val ) . number ;
2009-03-04 01:54:38 +00:00
return TRUE ;
}
2008-10-22 14:54:44 +00:00
/*
* OPTIONS
*/
2009-07-08 19:06:07 +00:00
static gboolean core_option_log_parse ( liServer * srv , liPlugin * p , size_t ndx , liValue * val , liOptionValue * oval ) {
2008-09-24 21:43:22 +00:00
GHashTableIter iter ;
gpointer k , v ;
2009-07-08 19:06:07 +00:00
liLogLevel level ;
2008-09-24 21:43:22 +00:00
GString * path ;
GString * level_str ;
2009-07-08 19:06:07 +00:00
GArray * arr = g_array_sized_new ( FALSE , TRUE , sizeof ( liLog * ) , 6 ) ;
2008-09-26 14:11:08 +00:00
UNUSED ( p ) ;
UNUSED ( ndx ) ;
2008-09-26 15:09:30 +00:00
oval - > list = arr ;
2008-12-31 01:50:32 +00:00
g_array_set_size ( arr , 6 ) ;
2008-10-01 20:20:31 +00:00
/* default value */
if ( ! val ) {
2009-07-08 19:06:07 +00:00
/* default: log LI_LOG_LEVEL_WARNING, LI_LOG_LEVEL_ERROR and LI_LOG_LEVEL_BACKEND to stderr */
liLog * log = srv - > logs . stderr ;
2008-10-01 20:20:31 +00:00
log_ref ( srv , log ) ;
2009-07-08 19:06:07 +00:00
g_array_index ( arr , liLog * , LI_LOG_LEVEL_WARNING ) = log ;
2008-10-01 20:20:31 +00:00
log_ref ( srv , log ) ;
2009-07-08 19:06:07 +00:00
g_array_index ( arr , liLog * , LI_LOG_LEVEL_ERROR ) = log ;
2008-12-31 01:50:32 +00:00
log_ref ( srv , log ) ;
2009-07-08 19:06:07 +00:00
g_array_index ( arr , liLog * , LI_LOG_LEVEL_BACKEND ) = log ;
2008-10-01 20:20:31 +00:00
return TRUE ;
}
2008-08-13 17:57:19 +00:00
2008-09-26 14:11:08 +00:00
g_hash_table_iter_init ( & iter , val - > data . hash ) ;
2008-09-24 21:43:22 +00:00
while ( g_hash_table_iter_next ( & iter , & k , & v ) ) {
2009-07-08 19:06:07 +00:00
if ( ( ( liValue * ) v ) - > type ! = LI_VALUE_STRING ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " log expects a hashtable with string values, %s given " , li_value_type_string ( ( ( liValue * ) v ) - > type ) ) ;
2008-10-02 22:59:59 +00:00
g_array_free ( arr , TRUE ) ;
return FALSE ;
}
2009-07-08 19:06:07 +00:00
path = ( ( liValue * ) v ) - > data . string ;
2008-09-24 21:43:22 +00:00
level_str = ( GString * ) k ;
if ( g_str_equal ( level_str - > str , " * " ) ) {
for ( guint i = 0 ; i < arr - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
liLog * log ;
2009-01-01 15:44:42 +00:00
2009-07-08 19:06:07 +00:00
if ( NULL ! = g_array_index ( arr , liLog * , i ) )
2008-09-24 21:43:22 +00:00
continue ;
2009-01-01 15:44:42 +00:00
log = log_new ( srv , log_type_from_path ( path ) , path ) ;
2009-07-08 19:06:07 +00:00
g_array_index ( arr , liLog * , i ) = log ;
2008-09-24 21:43:22 +00:00
}
}
else {
2009-07-08 19:06:07 +00:00
liLog * log = log_new ( srv , log_type_from_path ( path ) , path ) ;
2008-09-24 21:43:22 +00:00
level = log_level_from_string ( level_str ) ;
2009-07-08 19:06:07 +00:00
g_array_index ( arr , liLog * , level ) = log ;
2008-09-24 21:43:22 +00:00
}
}
2008-08-13 17:57:19 +00:00
return TRUE ;
}
2009-07-08 19:06:07 +00:00
static void core_option_log_free ( liServer * srv , liPlugin * p , size_t ndx , liOptionValue oval ) {
2009-01-01 15:44:42 +00:00
GArray * arr = oval . list ;
2008-08-13 17:57:19 +00:00
UNUSED ( p ) ;
UNUSED ( ndx ) ;
2008-09-24 21:43:22 +00:00
2008-09-26 15:09:30 +00:00
if ( ! arr ) return ;
2008-09-24 21:43:22 +00:00
for ( guint i = 0 ; i < arr - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
if ( NULL ! = g_array_index ( arr , liLog * , i ) )
log_unref ( srv , g_array_index ( arr , liLog * , i ) ) ;
2008-09-24 21:43:22 +00:00
}
2008-09-26 15:09:30 +00:00
g_array_free ( arr , TRUE ) ;
2008-08-13 17:57:19 +00:00
}
2009-07-08 19:06:07 +00:00
static gboolean core_option_log_timestamp_parse ( liServer * srv , liPlugin * p , size_t ndx , liValue * val , liOptionValue * oval ) {
2008-08-22 18:51:25 +00:00
UNUSED ( p ) ;
UNUSED ( ndx ) ;
2008-09-26 15:09:30 +00:00
if ( ! val ) return TRUE ;
2009-07-09 20:17:24 +00:00
oval - > ptr = li_log_timestamp_new ( srv , li_value_extract ( val ) . string ) ;
2008-09-24 21:43:22 +00:00
return TRUE ;
2008-08-22 18:51:25 +00:00
}
2009-07-08 19:06:07 +00:00
static void core_option_log_timestamp_free ( liServer * srv , liPlugin * p , size_t ndx , liOptionValue oval ) {
2008-08-22 18:51:25 +00:00
UNUSED ( p ) ;
UNUSED ( ndx ) ;
2008-09-26 14:11:08 +00:00
2008-09-26 15:09:30 +00:00
if ( ! oval . ptr ) return ;
2009-07-09 20:17:24 +00:00
li_log_timestamp_free ( srv , oval . ptr ) ;
2008-08-22 18:51:25 +00:00
}
2009-07-08 19:06:07 +00:00
static gboolean core_option_mime_types_parse ( liServer * srv , liPlugin * p , size_t ndx , liValue * val , liOptionValue * oval ) {
2008-12-09 23:23:27 +00:00
GArray * arr ;
2008-10-02 19:46:06 +00:00
UNUSED ( srv ) ;
UNUSED ( p ) ;
UNUSED ( ndx ) ;
/* default value */
if ( ! val ) {
2009-07-08 19:06:07 +00:00
oval - > list = g_array_new ( FALSE , TRUE , sizeof ( liValue ) ) ;
2008-10-02 19:46:06 +00:00
return TRUE ;
}
/* check if the passed val is of type (("a", "b"), ("x", y")) */
arr = val - > data . list ;
for ( guint i = 0 ; i < arr - > len ; i + + ) {
2009-07-08 19:06:07 +00:00
liValue * v = g_array_index ( arr , liValue * , i ) ;
liValue * v1 , * v2 ;
if ( v - > type ! = LI_VALUE_LIST ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " mime_types option expects a list of string tuples, entry #%u is of type %s " , i , li_value_type_string ( v - > type ) ) ;
2008-10-02 19:46:06 +00:00
return FALSE ;
}
if ( v - > data . list - > len ! = 2 ) {
ERROR ( srv , " mime_types option expects a list of string tuples, entry #%u is not a tuple " , i ) ;
return FALSE ;
}
2009-07-08 19:06:07 +00:00
v1 = g_array_index ( v - > data . list , liValue * , 0 ) ;
v2 = g_array_index ( v - > data . list , liValue * , 1 ) ;
if ( v1 - > type ! = LI_VALUE_STRING | | v2 - > type ! = LI_VALUE_STRING ) {
2009-07-09 20:17:24 +00:00
ERROR ( srv , " mime_types option expects a list of string tuples, entry #%u is a (%s,%s) tuple " , i , li_value_type_string ( v1 - > type ) , li_value_type_string ( v2 - > type ) ) ;
2008-10-02 19:46:06 +00:00
return FALSE ;
}
}
/* everything ok */
2009-07-09 20:17:24 +00:00
oval - > list = li_value_extract ( val ) . list ;
2008-10-02 19:46:06 +00:00
return TRUE ;
}
2009-07-08 19:06:07 +00:00
static void core_option_mime_types_free ( liServer * srv , liPlugin * p , size_t ndx , liOptionValue oval ) {
2008-10-02 19:46:06 +00:00
UNUSED ( srv ) ;
UNUSED ( p ) ;
UNUSED ( ndx ) ;
for ( guint i = 0 ; i < oval . list - > len ; i + + )