--- nginx-1.1.14/src/http/modules/ngx_http_autoindex_module.c.orig 2012-02-05 23:50:58.000000000 -0800 +++ nginx-1.1.14/src/http/modules/ngx_http_autoindex_module.c 2012-02-06 06:28:11.000000000 -0800 @@ -37,9 +37,11 @@ typedef struct { - ngx_flag_t enable; - ngx_flag_t localtime; - ngx_flag_t exact_size; + ngx_flag_t enable; + ngx_flag_t localtime; + ngx_flag_t exact_size; + ngx_flag_t omit_index_of; + ngx_http_complex_value_t dirname_to_display; } ngx_http_autoindex_loc_conf_t; @@ -56,6 +58,8 @@ static void *ngx_http_autoindex_create_loc_conf(ngx_conf_t *cf); static char *ngx_http_autoindex_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child); +static char *ngx_http_autoindex_dirname_to_display(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); static ngx_command_t ngx_http_autoindex_commands[] = { @@ -81,6 +85,20 @@ offsetof(ngx_http_autoindex_loc_conf_t, exact_size), NULL }, + { ngx_string("autoindex_omit_index_of"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_autoindex_loc_conf_t, omit_index_of), + NULL }, + + { ngx_string("autoindex_dirname_to_display"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_http_autoindex_dirname_to_display, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_autoindex_loc_conf_t, dirname_to_display), + NULL }, + ngx_null_command }; @@ -116,18 +134,28 @@ }; -static u_char title[] = +static u_char title_with_index_of[] = "" CRLF "Index of " ; +static u_char title_without_index_of[] = +"<html>" CRLF +"<head><title>" +; -static u_char header[] = +static u_char header_with_index_of[] = "" CRLF "" CRLF "

Index of " ; +static u_char header_without_index_of[] = +"" CRLF +"" CRLF +"

" +; + static u_char tail[] = "" CRLF "" CRLF @@ -153,6 +181,8 @@ ngx_array_t entries; ngx_http_autoindex_entry_t *entry; ngx_http_autoindex_loc_conf_t *alcf; + ngx_str_t dirname_to_display = ngx_null_string; + ngx_str_t header, title; static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; @@ -360,12 +390,53 @@ ngx_close_dir_n " \"%s\" failed", &path); } - escape_html = ngx_escape_html(NULL, r->uri.data, r->uri.len); + if (alcf->dirname_to_display.value.len == 0) { + + dirname_to_display.data = ngx_pstrdup(r->pool, &r->uri); + + if (dirname_to_display.data == NULL) + { + ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, + "http autoindex: dirname_to_display.data == NULL"); + return NGX_ERROR; + } + + dirname_to_display.len = r->uri.len; + + } else if (ngx_http_complex_value(r, &alcf->dirname_to_display, + &dirname_to_display) != NGX_OK) { + + ngx_log_error(NGX_LOG_CRIT, r->connection->log, err, + "http autoindex: ngx_http_complex_value() call failed"); + + return NGX_ERROR; + } + + dirname_to_display.data[dirname_to_display.len] = '\0'; + + escape_html = ngx_escape_html(NULL, dirname_to_display.data, + dirname_to_display.len); - len = sizeof(title) - 1 - + r->uri.len + escape_html - + sizeof(header) - 1 - + r->uri.len + escape_html + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http autoindex dirname_to_display: \"%s\"", + dirname_to_display.data); + + header.data = (alcf->omit_index_of ? &header_without_index_of : + &header_with_index_of); + + header.len = (alcf->omit_index_of ? sizeof(header_without_index_of) -1 : + sizeof(header_with_index_of) - 1); + + title.data = (alcf->omit_index_of ? &title_without_index_of : + &title_with_index_of); + + title.len = (alcf->omit_index_of ? sizeof(title_without_index_of) - 1 : + sizeof(title_with_index_of) - 1); + + len = title.len + + dirname_to_display.len + escape_html + + header.len + + dirname_to_display.len + escape_html + sizeof("

") - 1 + sizeof("
../" CRLF) - 1
           + sizeof("

") - 1 @@ -397,17 +468,24 @@ ngx_http_autoindex_cmp_entries); } - b->last = ngx_cpymem(b->last, title, sizeof(title) - 1); - + b->last = ngx_cpymem(b->last, title.data, title.len); + if (escape_html) { - b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); - b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); - b->last = (u_char *) ngx_escape_html(b->last, r->uri.data, r->uri.len); - + b->last = (u_char *) ngx_escape_html(b->last, + dirname_to_display.data, + dirname_to_display.len); + b->last = ngx_cpymem(b->last, header.data, header.len); + b->last = (u_char *) ngx_escape_html(b->last, + dirname_to_display.data, + dirname_to_display.len); } else { - b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); - b->last = ngx_cpymem(b->last, header, sizeof(header) - 1); - b->last = ngx_cpymem(b->last, r->uri.data, r->uri.len); + b->last = ngx_cpymem(b->last, + dirname_to_display.data, + dirname_to_display.len); + b->last = ngx_cpymem(b->last, header.data, header.len); + b->last = ngx_cpymem(b->last, + dirname_to_display.data, + dirname_to_display.len); } b->last = ngx_cpymem(b->last, "", sizeof("") - 1); @@ -663,6 +741,7 @@ conf->enable = NGX_CONF_UNSET; conf->localtime = NGX_CONF_UNSET; conf->exact_size = NGX_CONF_UNSET; + conf->omit_index_of = NGX_CONF_UNSET; return conf; } @@ -677,6 +756,11 @@ ngx_conf_merge_value(conf->enable, prev->enable, 0); ngx_conf_merge_value(conf->localtime, prev->localtime, 0); ngx_conf_merge_value(conf->exact_size, prev->exact_size, 1); + ngx_conf_merge_value(conf->omit_index_of, prev->omit_index_of, 0); + + if (conf->dirname_to_display.value.len == 0) { + conf->dirname_to_display = prev->dirname_to_display; + } return NGX_CONF_OK; } @@ -699,3 +783,33 @@ return NGX_OK; } + + +static char * +ngx_http_autoindex_dirname_to_display(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf) +{ + ngx_http_autoindex_loc_conf_t *alcf = conf; + ngx_str_t *value; + ngx_http_compile_complex_value_t ccv; + + if (alcf->dirname_to_display.value.len) { + return "is duplicate"; + } + + value = cf->args->elts; + + ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); + + ccv.cf = cf; + ccv.value = &value[1]; + ccv.complex_value = &alcf->dirname_to_display; + ccv.zero = 0; + ccv.conf_prefix = 0; + + if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { + return NGX_CONF_ERROR; + } + + return NGX_CONF_OK; +}