@ -112,59 +112,6 @@ ngx_fancyindex_timefmt_calc_size (const ngx_str_t *fmt)
# undef DATETIME_CASE
}
static ngx_str_t
ngx_fancyindex_get_file ( ngx_http_request_t * r , ngx_str_t * fname )
{
ngx_file_t file ;
ngx_file_info_t fi ;
ssize_t size , n ;
ngx_str_t ret = { 0 , NULL } ;
ngx_memzero ( & file , sizeof ( ngx_file_t ) ) ;
file . log = r - > connection - > log ;
file . fd = ngx_open_file ( ( const char * ) fname - > data , NGX_FILE_RDONLY , 0 , 0 ) ;
if ( file . fd = = NGX_INVALID_FILE ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: '%s' is not regular file. " , fname - > data ) ;
return ret ;
}
if ( ngx_fd_info ( file . fd , & fi ) = = NGX_FILE_ERROR ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: can't get information of local file '%s'. " , fname - > data ) ;
ngx_close_file ( file . fd ) ;
return ret ;
}
size = ( ssize_t ) ngx_file_size ( & fi ) ;
ngx_log_debug2 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: '%s' -> size %d. " , fname - > data , size ) ;
ret . data = ( u_char * ) ngx_calloc ( size + 1 , r - > connection - > log ) ;
if ( ret . data = = NULL ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: memory allocation failed on %s " , __FUNCTION__ ) ;
ngx_close_file ( file . fd ) ;
return ret ;
}
n = ngx_read_file ( & file , ret . data , size , 0 ) ;
if ( n = = NGX_ERROR ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: failed read of footer file '%s'. " , fname - > data ) ;
ngx_close_file ( file . fd ) ;
ngx_free ( ret . data ) ;
ret . len = 0 ;
ret . data = NULL ;
return ret ;
}
ret . len = n ;
ngx_close_file ( file . fd ) ;
return ret ;
}
static u_char *
ngx_fancyindex_timefmt ( u_char * buffer , const ngx_str_t * fmt , const ngx_tm_t * tm )
@ -193,6 +140,10 @@ ngx_fancyindex_timefmt (u_char *buffer, const ngx_str_t *fmt, const ngx_tm_t *tm
# undef DATETIME_CASE
}
typedef struct {
ngx_str_t path ;
ngx_str_t local ;
} ngx_fancyindex_headerfooter_conf_t ;
/**
* Configuration structure for the fancyindex module . The configuration
@ -210,12 +161,13 @@ typedef struct {
ngx_flag_t hide_parent ; /**< Hide parent directory. */
ngx_flag_t show_dot_files ; /**< Show files that start with a dot.*/
ngx_str_t header ; /**< File name for header, or empty if none. */
ngx_str_t footer ; /**< File name for footer, or empty if none. */
ngx_str_t css_href ; /**< Link to a CSS stylesheet, or empty if none. */
ngx_str_t time_format ; /**< Format used for file timestamps. */
ngx_array_t * ignore ; /**< List of files to ignore in listings. */
ngx_fancyindex_headerfooter_conf_t header ;
ngx_fancyindex_headerfooter_conf_t footer ;
} ngx_http_fancyindex_loc_conf_t ;
# define NGX_HTTP_FANCYINDEX_SORT_CRITERION_NAME 0
@ -235,6 +187,106 @@ static ngx_conf_enum_t ngx_http_fancyindex_sort_criteria[] = {
{ ngx_null_string , 0 }
} ;
enum {
NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST ,
NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL ,
} ;
static ngx_uint_t
headerfooter_kind ( const ngx_str_t * value )
{
static const struct {
ngx_str_t name ;
ngx_uint_t value ;
} values [ ] = {
{ ngx_string ( " subrequest " ) , NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST } ,
{ ngx_string ( " local " ) , NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL } ,
} ;
unsigned i ;
for ( i = 0 ; i < sizeof ( values ) / sizeof ( values [ 0 ] ) ; i + + ) {
if ( value - > len = = values [ i ] . name . len & &
ngx_strcasecmp ( value - > data , values [ i ] . name . data ) = = 0 )
{
return values [ i ] . value ;
}
}
return NGX_CONF_UNSET_UINT ;
}
static char *
ngx_fancyindex_conf_set_headerfooter ( ngx_conf_t * cf , ngx_command_t * cmd , void * conf )
{
ngx_fancyindex_headerfooter_conf_t * item =
( void * ) ( ( ( char * ) conf ) + cmd - > offset ) ;
ngx_str_t * values = cf - > args - > elts ;
if ( item - > path . data )
return " is duplicate " ;
item - > path = values [ 1 ] ;
/* Kind of path. Default is "subrequest". */
ngx_uint_t kind = NGX_HTTP_FANCYINDEX_HEADERFOOTER_SUBREQUEST ;
if ( cf - > args - > nelts = = 2 ) {
kind = headerfooter_kind ( & values [ 2 ] ) ;
if ( kind = = NGX_CONF_UNSET_UINT ) {
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 ,
" unknown header/footer kind \" %V \" " , & values [ 2 ] ) ;
return NGX_CONF_ERROR ;
}
}
if ( kind = = NGX_HTTP_FANCYINDEX_HEADERFOOTER_LOCAL ) {
ngx_file_t file ;
ngx_file_info_t fi ;
ssize_t n ;
ngx_memzero ( & file , sizeof ( ngx_file_t ) ) ;
file . log = cf - > log ;
file . fd = ngx_open_file ( item - > path . data , NGX_FILE_RDONLY , 0 , 0 ) ;
if ( file . fd = = NGX_INVALID_FILE ) {
ngx_conf_log_error ( NGX_LOG_EMERG , cf , ngx_errno ,
" cannot open file \" %V \" " , & values [ 1 ] ) ;
return NGX_CONF_ERROR ;
}
if ( ngx_fd_info ( file . fd , & fi ) = = NGX_FILE_ERROR ) {
ngx_close_file ( file . fd ) ;
ngx_conf_log_error ( NGX_LOG_EMERG , cf , ngx_errno ,
" cannot get info for file \" %V \" " , & values [ 1 ] ) ;
return NGX_CONF_ERROR ;
}
item - > local . len = ngx_file_size ( & fi ) ;
item - > local . data = ngx_pcalloc ( cf - > pool , item - > local . len + 1 ) ;
if ( item - > local . data = = NULL ) {
ngx_close_file ( file . fd ) ;
return NGX_CONF_ERROR ;
}
n = item - > local . len ;
while ( n > 0 ) {
ssize_t r = ngx_read_file ( & file ,
item - > local . data + file . offset ,
n ,
file . offset ) ;
if ( r = = NGX_ERROR ) {
ngx_close_file ( file . fd ) ;
ngx_conf_log_error ( NGX_LOG_EMERG , cf , ngx_errno ,
" cannot read file \" %V \" " , & values [ 1 ] ) ;
return NGX_CONF_ERROR ;
}
n - = r ;
}
item - > local . data [ item - > local . len ] = ' \0 ' ;
}
return NGX_CONF_OK ;
}
# define NGX_HTTP_FANCYINDEX_PREALLOCATE 50
@ -319,14 +371,9 @@ static uintptr_t
* above ) .
*/
static ngx_inline ngx_buf_t *
make_header_buf ( ngx_http_request_t * r , const ngx_str_t css_href , ngx_str_t local )
make_header_buf ( ngx_http_request_t * r , const ngx_str_t css_href )
ngx_force_inline ;
static ngx_inline ngx_buf_t *
make_footer_buf ( ngx_http_request_t * r , ngx_str_t local )
ngx_force_inline ;
static ngx_command_t ngx_http_fancyindex_commands [ ] = {
@ -373,15 +420,15 @@ static ngx_command_t ngx_http_fancyindex_commands[] = {
NULL } ,
{ ngx_string ( " fancyindex_header " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_ FLAG ,
ngx_ conf_set_str_slot ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_ TAKE12 ,
ngx_ fancyindex_conf_set_headerfooter ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_fancyindex_loc_conf_t , header ) ,
NULL } ,
{ ngx_string ( " fancyindex_footer " ) ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_ FLAG ,
ngx_ conf_set_str_slot ,
NGX_HTTP_MAIN_CONF | NGX_HTTP_SRV_CONF | NGX_HTTP_LOC_CONF | NGX_CONF_ TAKE12 ,
ngx_ fancyindex_conf_set_headerfooter ,
NGX_HTTP_LOC_CONF_OFFSET ,
offsetof ( ngx_http_fancyindex_loc_conf_t , footer ) ,
NULL } ,
@ -573,20 +620,10 @@ ngx_fancyindex_escape_filename(u_char *dst, u_char *src, size_t size)
static ngx_inline ngx_buf_t *
make_header_buf ( ngx_http_request_t * r , const ngx_str_t css_href , ngx_str_t local )
make_header_buf ( ngx_http_request_t * r , const ngx_str_t css_href )
{
size_t blen ;
ngx_buf_t * b ;
if ( local . len > 0 ) {
blen = local . len ;
if ( ( b = ngx_create_temp_buf ( r - > pool , blen ) ) = = NULL )
return NULL ;
b - > last = ngx_cpymem ( b - > last , local . data , local . len ) ;
return b ;
}
blen = r - > uri . len
size_t blen = r - > uri . len
+ ngx_sizeof_ssz ( t01_head1 )
+ ngx_sizeof_ssz ( t02_head2 )
+ ngx_sizeof_ssz ( t03_head3 )
@ -620,34 +657,6 @@ make_header_buf(ngx_http_request_t *r, const ngx_str_t css_href, ngx_str_t local
}
static ngx_inline ngx_buf_t *
make_footer_buf ( ngx_http_request_t * r , ngx_str_t local )
{
/*
* TODO : Make this buffer static ( i . e . readonly and reusable from
* one request to another .
*/
ngx_buf_t * b ;
// ngx_str_t local :: contents of local footer file
if ( local . len > 0 ) {
if ( ( b = ngx_create_temp_buf ( r - > pool , local . len ) ) = = NULL )
return NULL ;
b - > last = ngx_cpymem ( b - > last , local . data , local . len ) ;
return b ;
}
if ( ( b = ngx_create_temp_buf ( r - > pool , ngx_sizeof_ssz ( t08_foot1 ) ) ) = = NULL )
return NULL ;
b - > last = ngx_cpymem_ssz ( b - > last , t08_foot1 ) ;
return b ;
}
static ngx_inline ngx_int_t
make_content_buf (
ngx_http_request_t * r , ngx_buf_t * * pb ,
@ -1155,8 +1164,6 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r)
ngx_http_request_t * sr ;
ngx_str_t * sr_uri ;
ngx_str_t rel_uri ;
ngx_str_t lheader = { 0 , NULL } ;
ngx_str_t lfooter = { 0 , NULL } ;
ngx_int_t rc ;
ngx_http_fancyindex_loc_conf_t * alcf ;
ngx_chain_t out [ 3 ] = {
@ -1200,24 +1207,19 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r)
if ( rc = = NGX_ERROR | | rc > NGX_OK | | r - > header_only )
return rc ;
if ( alcf - > header . len > 0 ) {
/* if header is local file */
lheader = ngx_fancyindex_get_file ( r , & ( alcf - > header ) ) ;
if ( lheader . len > 0 )
goto add_builtin_header ;
if ( alcf - > header . path . len > 0 & & alcf - > header . local . len = = 0 ) {
/* URI is configured, make Nginx take care of with a subrequest. */
sr_uri = & alcf - > header ;
sr_uri = & alcf - > header . path ;
if ( * sr_uri - > data ! = ' / ' ) {
/* Relative path */
rel_uri . len = r - > uri . len + alcf - > header . len;
rel_uri . len = r - > uri . len + alcf - > header . path. len;
rel_uri . data = ngx_palloc ( r - > pool , rel_uri . len ) ;
if ( rel_uri . data = = NULL ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
ngx_memcpy ( ngx_cpymem ( rel_uri . data , r - > uri . data , r - > uri . len ) ,
alcf - > header . data, alcf - > header . len ) ;
alcf - > header . path. data, alcf - > header . path . len ) ;
sr_uri = & rel_uri ;
}
@ -1245,45 +1247,41 @@ ngx_http_fancyindex_handler(ngx_http_request_t *r)
}
else {
add_builtin_header :
if ( lheader . len > 0 ) {
ngx_log_debug0 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: adding local filesystem header " ) ;
} else {
ngx_log_debug0 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: adding built-in header " ) ;
}
/* Make space before */
out [ 1 ] . next = out [ 0 ] . next ;
out [ 1 ] . buf = out [ 0 ] . buf ;
/* Chain header buffer */
out [ 0 ] . next = & out [ 1 ] ;
out [ 0 ] . buf = make_header_buf ( r , alcf - > css_href , lheader ) ;
if ( lheader . data ! = NULL ) {
/* lheader.len is used by the local footer and should not be initialized. */
ngx_free ( lheader . data ) ;
lheader . data = NULL ;
if ( alcf - > header . local . len > 0 ) {
/* Header buffer is local, make a buffer pointing to the data. */
out [ 0 ] . buf = ngx_calloc_buf ( r - > pool ) ;
if ( out [ 0 ] . buf = = NULL )
return NGX_ERROR ;
out [ 0 ] . buf - > memory = 1 ;
out [ 0 ] . buf - > pos = alcf - > header . local . data ;
out [ 0 ] . buf - > last = alcf - > header . local . data + alcf - > header . local . len ;
} else {
/* Prepare a buffer with the contents of the builtin header. */
out [ 0 ] . buf = make_header_buf ( r , alcf - > css_href ) ;
}
}
add_local_footer :
/* If footer is disabled, chain up footer buffer. */
if ( alcf - > footer . len = = 0 | | lfooter . len > 0 ) {
ngx_uint_t last = ( alcf - > header . len = = 0 | | lheader . len > 0 ) ? 2 : 1 ;
if ( lfooter . len > 0 ) {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: adding local filesystem footer at %i " , last ) ;
} else {
ngx_log_debug1 ( NGX_LOG_DEBUG_HTTP , r - > connection - > log , 0 ,
" http fancyindex: adding built-in footer at %i " , last ) ;
}
if ( alcf - > footer . path . len = = 0 | | alcf - > footer . local . len > 0 ) {
ngx_uint_t last = ( alcf - > header . path . len = = 0 ) ? 2 : 1 ;
out [ last - 1 ] . next = & out [ last ] ;
out [ last ] . buf = make_footer_buf ( r , lfooter ) ;
if ( lfooter . data ! = NULL ) {
ngx_free ( lfooter . data ) ;
lfooter . len = 0 ;
lfooter . data = NULL ;
out [ last ] . buf = ngx_calloc_buf ( r - > pool ) ;
if ( out [ last ] . buf = = NULL )
return NGX_ERROR ;
out [ last ] . buf - > memory = 1 ;
if ( alcf - > footer . local . len > 0 ) {
out [ last ] . buf - > pos = alcf - > footer . local . data ;
out [ last ] . buf - > last = alcf - > footer . local . data + alcf - > footer . local . len ;
} else {
out [ last ] . buf - > pos = ( u_char * ) t08_foot1 ;
out [ last ] . buf - > last = ( u_char * ) t08_foot1 + sizeof ( t08_foot1 ) - 1 ;
}
out [ last - 1 ] . buf - > last_in_chain = 0 ;
@ -1291,10 +1289,6 @@ add_local_footer:
out [ last ] . buf - > last_buf = 1 ;
/* Send everything with a single call :D */
return ngx_http_output_filter ( r , & out [ 0 ] ) ;
} else {
lfooter = ngx_fancyindex_get_file ( r , & ( alcf - > footer ) ) ;
if ( lfooter . len > 0 )
goto add_local_footer ;
}
/*
@ -1309,17 +1303,17 @@ add_local_footer:
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
/* URI is configured, make Nginx take care of with a subrequest. */
sr_uri = & alcf - > footer ;
sr_uri = & alcf - > footer .path ;
if ( * sr_uri - > data ! = ' / ' ) {
/* Relative path */
rel_uri . len = r - > uri . len + alcf - > footer . len;
rel_uri . len = r - > uri . len + alcf - > footer . path. len;
rel_uri . data = ngx_palloc ( r - > pool , rel_uri . len ) ;
if ( rel_uri . data = = NULL ) {
return NGX_HTTP_INTERNAL_SERVER_ERROR ;
}
ngx_memcpy ( ngx_cpymem ( rel_uri . data , r - > uri . data , r - > uri . len ) ,
alcf - > footer . data, alcf - > footer . len ) ;
alcf - > footer . path. data, alcf - > footer . path . len ) ;
sr_uri = & rel_uri ;
}
@ -1344,7 +1338,12 @@ add_local_footer:
* we get something different from a 404 ?
*/
out [ 0 ] . next = NULL ;
out [ 0 ] . buf = make_footer_buf ( r , lfooter ) ;
out [ 0 ] . buf = ngx_calloc_buf ( r - > pool ) ;
if ( out [ 0 ] . buf = = NULL )
return NGX_ERROR ;
out [ 0 ] . buf - > memory = 1 ;
out [ 0 ] . buf - > pos = ( u_char * ) t08_foot1 ;
out [ 0 ] . buf - > last = ( u_char * ) t08_foot1 + sizeof ( t08_foot1 ) - 1 ;
out [ 0 ] . buf - > last_in_chain = 1 ;
out [ 0 ] . buf - > last_buf = 1 ;
/* Directly send out the builtin footer */
@ -1439,10 +1438,10 @@ ngx_http_fancyindex_create_loc_conf(ngx_conf_t *cf)
/*
* Set by ngx_pcalloc :
* conf - > header . len = 0
* conf - > header . data = NULL
* conf - > footer . len = 0
* conf - > footer . data = NULL
* conf - > header . * . len = 0
* conf - > header . * . data = NULL
* conf - > footer . * . len = 0
* conf - > footer . * . data = NULL
* conf - > css_href . len = 0
* conf - > css_href . data = NULL
* conf - > time_format . len = 0
@ -1481,8 +1480,11 @@ ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value ( conf - > show_dot_files , prev - > show_dot_files , 0 ) ;
ngx_conf_merge_uint_value ( conf - > name_length , prev - > name_length , 50 ) ;
ngx_conf_merge_str_value ( conf - > header , prev - > header , " " ) ;
ngx_conf_merge_str_value ( conf - > footer , prev - > footer , " " ) ;
ngx_conf_merge_str_value ( conf - > header . path , prev - > header . path , " " ) ;
ngx_conf_merge_str_value ( conf - > header . path , prev - > header . local , " " ) ;
ngx_conf_merge_str_value ( conf - > footer . path , prev - > footer . path , " " ) ;
ngx_conf_merge_str_value ( conf - > footer . path , prev - > footer . local , " " ) ;
ngx_conf_merge_str_value ( conf - > css_href , prev - > css_href , " " ) ;
ngx_conf_merge_str_value ( conf - > time_format , prev - > time_format , " %Y-%b-%d %H:%M " ) ;
@ -1491,7 +1493,7 @@ ngx_http_fancyindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value ( conf - > hide_parent , prev - > hide_parent , 0 ) ;
/* Just make sure we haven't disabled the show_path directive without providing a custom header */
if ( conf - > show_path = = 0 & & conf - > header . len = = 0 )
if ( conf - > show_path = = 0 & & conf - > header . path. len = = 0 )
{
ngx_conf_log_error ( NGX_LOG_EMERG , cf , 0 , " FancyIndex : cannot set show_path to off without providing a custom header ! " ) ;
return NGX_CONF_ERROR ;