# HG changeset patch # User Igor Sysoev # Date 1135717200 -10800 # Node ID e1c6ac408b6844b75d8733877f8c670260452c14 # Parent c2fa0caa07f20bb6dd83391a316e370a4541957b nginx 0.3.19 *) Feature: the "path" and "alias" directives support the variables. *) Change: now the "valid_referers" directive again checks the URI part. *) Bugfix: in SSI handling. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,12 @@ + +Changes with nginx 0.3.19 28 Dec 2005 + + *) Feature: the "path" and "alias" directives support the variables. + + *) Change: now the "valid_referers" directive again checks the URI part. + + *) Bugfix: in SSI handling. + Changes with nginx 0.3.18 26 Dec 2005 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,12 @@ + +Изменения в nginx 0.3.19 28.12.2005 + + *) Добавление: директивы path и alias поддерживают переменные. + + *) Изменение: теперь директива valid_referers опять учитывает URI. + + *) Исправление: ошибки в обработке SSI. + Изменения в nginx 0.3.18 26.12.2005 diff --git a/auto/cc/icc b/auto/cc/icc --- a/auto/cc/icc +++ b/auto/cc/icc @@ -114,11 +114,17 @@ case "$NGX_ICC_VER" in # conversion from pointer to same-sized integral type, # warning on offsetof() CFLAGS="$CFLAGS -wd1684" + # floating-point equality and inequality comparisons are unreliable, + # warning on SvTRUE() + CFLAGS="$CFLAGS -wd1572" ;; 8.*) # "cc" clobber ignored, warnings for Liunx's htonl()/htons() CFLAGS="$CFLAGS -wd1469" + # floating-point equality and inequality comparisons are unreliable, + # warning on SvTRUE() + CFLAGS="$CFLAGS -wd1572" ;; *) diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.18" +#define NGINX_VER "nginx/0.3.19" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_buf.h b/src/core/ngx_buf.h --- a/src/core/ngx_buf.h +++ b/src/core/ngx_buf.h @@ -105,10 +105,15 @@ typedef struct { #define ngx_buf_in_memory(b) (b->temporary || b->memory || b->mmap) #define ngx_buf_in_memory_only(b) (ngx_buf_in_memory(b) && !b->in_file) + #define ngx_buf_special(b) \ ((b->flush || b->last_buf || b->sync) \ && !ngx_buf_in_memory(b) && !b->in_file) +#define ngx_buf_sync_only(b) \ + (b->sync \ + && !ngx_buf_in_memory(b) && !b->in_file && !b->flush && !b->last_buf) + #define ngx_buf_size(b) \ (ngx_buf_in_memory(b) ? (off_t) (b->last - b->pos): \ (b->file_last - b->file_pos)) diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c --- a/src/core/ngx_hash.c +++ b/src/core/ngx_hash.c @@ -129,13 +129,14 @@ ngx_hash_find_wildcard(ngx_hash_wildcard #define NGX_HASH_ELT_SIZE(name) \ - sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *)) + (sizeof(void *) + ngx_align((name)->key.len + 1, sizeof(void *))) ngx_int_t ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts) { u_char *elts; - size_t *test, len; + size_t len; + u_short *test; ngx_uint_t i, n, key, size, start, bucket_size; ngx_hash_elt_t *elt, **buckets; @@ -151,14 +152,14 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng if (hinit->bucket_size < NGX_HASH_ELT_SIZE(&names[n]) + sizeof(void *)) { ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, - "could not build the %s hash, you should " + "could not build the %s, you should " "increase %s_bucket_size: %i", hinit->name, hinit->name, hinit->bucket_size); return NGX_ERROR; } } - test = ngx_alloc(hinit->max_size * sizeof(size_t), hinit->pool->log); + test = ngx_alloc(hinit->max_size * sizeof(u_short), hinit->pool->log); if (test == NULL) { return NGX_ERROR; } @@ -170,7 +171,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng for (size = start; size < hinit->max_size; size++) { - ngx_memzero(test, size * sizeof(size_t)); + ngx_memzero(test, size * sizeof(u_short)); for (n = 0; n < nelts; n++) { if (names[n].key.data == NULL) { @@ -178,7 +179,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng } key = names[n].key_hash % size; - test[key] += NGX_HASH_ELT_SIZE(&names[n]); + test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); #if 0 ngx_log_error(NGX_LOG_ALERT, hinit->pool->log, 0, @@ -186,7 +187,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng size, key, test[key], &names[n].key); #endif - if (test[key] > bucket_size) { + if (test[key] > (u_short) bucket_size) { goto next; } } @@ -199,7 +200,7 @@ ngx_hash_init(ngx_hash_init_t *hinit, ng } ngx_log_error(NGX_LOG_EMERG, hinit->pool->log, 0, - "could not build the %s hash, you should increase " + "could not build the %s, you should increase " "either %s_max_size: %i or %s_bucket_size: %i", hinit->name, hinit->name, hinit->max_size, hinit->name, hinit->bucket_size); @@ -220,7 +221,7 @@ found: } key = names[n].key_hash % size; - test[key] += NGX_HASH_ELT_SIZE(&names[n]); + test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); } len = 0; @@ -230,7 +231,7 @@ found: continue; } - test[i] = ngx_align(test[i], ngx_cacheline_size); + test[i] = (u_short) (ngx_align(test[i], ngx_cacheline_size)); len += test[i]; } @@ -291,7 +292,7 @@ found: elt->name[i] = ngx_tolower(names[n].key.data[i]); } - test[key] += NGX_HASH_ELT_SIZE(&names[n]); + test[key] = (u_short) (test[key] + NGX_HASH_ELT_SIZE(&names[n])); } for (i = 0; i < size; i++) { diff --git a/src/http/modules/ngx_http_index_module.c b/src/http/modules/ngx_http_index_module.c --- a/src/http/modules/ngx_http_index_module.c +++ b/src/http/modules/ngx_http_index_module.c @@ -291,7 +291,7 @@ ngx_http_index_handler(ngx_http_request_ uri.len = r->uri.len + ctx->index.len - 1; if (!clcf->alias) { - uri.data = ctx->path.data + clcf->root.len; + uri.data = ctx->path.data + r->root_length; } else { uri.data = ngx_palloc(r->pool, uri.len); diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -9,6 +9,8 @@ #include +#define NGX_HTTP_REFERER_NO_URI_PART ((void *) 4) + typedef struct { ngx_hash_t hash; ngx_hash_wildcard_t *dns_wildcards; @@ -26,7 +28,7 @@ static char * ngx_http_referer_merge_con static char *ngx_http_valid_referers(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, - ngx_str_t *value); + ngx_str_t *value, ngx_str_t *uri); static int ngx_libc_cdecl ngx_http_cmp_referer_wildcards(const void *one, const void *two); @@ -79,9 +81,12 @@ static ngx_int_t ngx_http_referer_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { - u_char *p, *ref; + u_char *p, *ref, *last; size_t len; + ngx_str_t *uri; + ngx_uint_t i, key; ngx_http_referer_conf_t *rlcf; + u_char buf[256]; rlcf = ngx_http_get_module_loc_conf(r, ngx_http_referer_module); @@ -89,19 +94,15 @@ ngx_http_referer_variable(ngx_http_reque && rlcf->dns_wildcards == NULL && rlcf->dns_wildcards->hash.buckets == NULL) { - *v = ngx_http_variable_null_value; - return NGX_OK; + goto valid; } if (r->headers_in.referer == NULL) { if (rlcf->no_referer) { - *v = ngx_http_variable_null_value; - return NGX_OK; + goto valid; + } - } else { - *v = ngx_http_variable_true_value; - return NGX_OK; - } + goto invalid; } len = r->headers_in.referer->value.len; @@ -111,43 +112,79 @@ ngx_http_referer_variable(ngx_http_reque || (ngx_strncasecmp(ref, "http://", 7) != 0)) { if (rlcf->blocked_referer) { - *v = ngx_http_variable_null_value; - return NGX_OK; + goto valid; + } - } else { - *v = ngx_http_variable_true_value; - return NGX_OK; - } + goto invalid; } - len -= 7; + last = ref + len; ref += 7; + i = 0; + key = 0; - for (p = ref; p < ref + len; p++) { + for (p = ref; p < last; p++) { if (*p == '/' || *p == ':') { break; } + + buf[i] = ngx_tolower(*p); + key = ngx_hash(key, buf[i++]); + + if (i == 256) { + goto invalid; + } } len = p - ref; if (rlcf->hash.buckets) { - if (ngx_hash_find(&rlcf->hash, ngx_hash_key_lc(ref, len), ref, len)) { - *v = ngx_http_variable_null_value; - return NGX_OK; + uri = ngx_hash_find(&rlcf->hash, key, buf, len); + if (uri) { + goto uri; } } if (rlcf->dns_wildcards && rlcf->dns_wildcards->hash.buckets) { - if (ngx_hash_find_wildcard(rlcf->dns_wildcards, ref, len)) { - *v = ngx_http_variable_null_value; - return NGX_OK; + uri = ngx_hash_find_wildcard(rlcf->dns_wildcards, buf, len); + if (uri) { + goto uri; } } +invalid: + *v = ngx_http_variable_true_value; return NGX_OK; + +uri: + + for ( /* void */ ; p < last; p++) { + if (*p == '/') { + break; + } + } + + len = last - p; + + if (len == 0) { + goto invalid; + } + + if (uri == NGX_HTTP_REFERER_NO_URI_PART) { + goto valid; + } + + if (len < uri->len || ngx_strncmp(uri->data, p, uri->len) != 0) { + goto invalid; + } + +valid: + + *v = ngx_http_variable_null_value; + + return NGX_OK; } @@ -241,7 +278,7 @@ ngx_http_valid_referers(ngx_conf_t *cf, ngx_http_referer_conf_t *rlcf = conf; u_char *p; - ngx_str_t *value, name; + ngx_str_t *value, uri, name; ngx_uint_t i, n; ngx_http_variable_t *var; ngx_http_server_name_t *sn; @@ -291,13 +328,17 @@ ngx_http_valid_referers(ngx_conf_t *cf, continue; } + uri.len = 0; + if (ngx_strcmp(value[i].data, "server_names") == 0) { cscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_core_module); sn = cscf->server_names.elts; for (n = 0; n < cscf->server_names.nelts; n++) { - if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name) != NGX_OK) { + if (ngx_http_add_referer(cf, rlcf->keys, &sn[n].name, &uri) + != NGX_OK) + { return NGX_CONF_ERROR; } } @@ -308,13 +349,12 @@ ngx_http_valid_referers(ngx_conf_t *cf, p = (u_char *) ngx_strstr(value[i].data, "/"); if (p) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "URI part \"%s\" is deprecated, ignored", p); - + uri.len = (value[i].data + value[i].len) - p; + uri.data = p; value[i].len = p - value[i].data; } - if (ngx_http_add_referer(cf, rlcf->keys, &value[i]) != NGX_OK) { + if (ngx_http_add_referer(cf, rlcf->keys, &value[i], &uri) != NGX_OK) { return NGX_CONF_ERROR; } } @@ -325,11 +365,12 @@ ngx_http_valid_referers(ngx_conf_t *cf, static char * ngx_http_add_referer(ngx_conf_t *cf, ngx_hash_keys_arrays_t *keys, - ngx_str_t *value) + ngx_str_t *value, ngx_str_t *uri) { - u_char ch; - ngx_int_t rc; - ngx_uint_t flags; + u_char ch; + ngx_int_t rc; + ngx_str_t *u; + ngx_uint_t flags; ch = value->data[0]; @@ -344,7 +385,19 @@ ngx_http_add_referer(ngx_conf_t *cf, ngx flags = (ch == '*' || ch == '.') ? NGX_HASH_WILDCARD_KEY : 0; - rc = ngx_hash_add_key(keys, value, (void *) 4, flags); + if (uri->len == 0) { + u = NGX_HTTP_REFERER_NO_URI_PART; + + } else { + u = ngx_palloc(cf->pool, sizeof(ngx_str_t)); + if (u == NULL) { + return NGX_CONF_ERROR; + } + + *u = *uri; + } + + rc = ngx_hash_add_key(keys, value, u, flags); if (rc == NGX_OK) { return NGX_CONF_OK; diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c --- a/src/http/ngx_http.c +++ b/src/http/ngx_http.c @@ -11,8 +11,6 @@ static char *ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); -static int ngx_libc_cdecl ngx_cmp_server_names(const void *one, - const void *two); static ngx_int_t ngx_http_add_address(ngx_conf_t *cf, ngx_http_conf_in_port_t *in_port, ngx_http_listen_t *lscf, ngx_http_core_srv_conf_t *cscf); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -984,23 +984,66 @@ u_char * ngx_http_map_uri_to_path(ngx_http_request_t *r, ngx_str_t *path, size_t reserved) { - u_char *last; - size_t alias; - ngx_http_core_loc_conf_t *clcf; + u_char *last; + size_t alias, len; + ngx_http_script_code_pt code; + ngx_http_script_engine_t e; + ngx_http_core_loc_conf_t *clcf; + ngx_http_script_len_code_pt lcode; clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module); alias = clcf->alias ? clcf->name.len : 0; - path->len = clcf->root.len + r->uri.len - alias + 1 + reserved; - - path->data = ngx_palloc(r->pool, path->len); + if (clcf->root_lengths == NULL) { + + r->root_length = clcf->root.len; + + path->len = clcf->root.len + r->uri.len - alias + 1 + reserved; + + path->data = ngx_palloc(r->pool, path->len); + if (path->data == NULL) { + return NULL; + } + + last = ngx_copy(path->data, clcf->root.data, clcf->root.len); + last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1); + + return last; + } + + ngx_memzero(&e, sizeof(ngx_http_script_engine_t)); + + e.ip = clcf->root_lengths->elts; + e.request = r; + e.flushed = 1; + + len = 0; + + while (*(uintptr_t *) e.ip) { + lcode = *(ngx_http_script_len_code_pt *) e.ip; + len += lcode(&e); + } + + r->root_length = len; + + len += r->uri.len - alias + 1 + reserved; + + path->len = len; + path->data = ngx_palloc(r->pool, len); if (path->data == NULL) { return NULL; } - last = ngx_copy(path->data, clcf->root.data, clcf->root.len); - last = ngx_cpystrn(last, r->uri.data + alias, r->uri.len - alias + 1); + e.ip = clcf->root_values->elts; + e.pos = path->data; + + while (*(uintptr_t *) e.ip) { + code = *(ngx_http_script_code_pt *) e.ip; + code((ngx_http_script_engine_t *) &e); + } + + last = ngx_cpystrn(e.pos, r->uri.data + alias, r->uri.len - alias + 1); return last; } @@ -1957,7 +2000,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t } ngx_conf_merge_unsigned_value(conf->types_hash_max_size, - prev->types_hash_max_size, 512); + prev->types_hash_max_size, 1024); ngx_conf_merge_unsigned_value(conf->types_hash_bucket_size, prev->types_hash_bucket_size, @@ -1977,7 +2020,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t types_hash.key = ngx_hash_key_lc; types_hash.max_size = conf->types_hash_max_size; types_hash.bucket_size = conf->types_hash_bucket_size; - types_hash.name = "mime_types"; + types_hash.name = "types_hash"; types_hash.pool = cf->pool; types_hash.temp_pool = NULL; @@ -2019,7 +2062,7 @@ ngx_http_core_merge_loc_conf(ngx_conf_t types_hash.key = ngx_hash_key_lc; types_hash.max_size = conf->types_hash_max_size; types_hash.bucket_size = conf->types_hash_bucket_size; - types_hash.name = "mime_types"; + types_hash.name = "mime_types_hash"; types_hash.pool = cf->pool; types_hash.temp_pool = NULL; @@ -2340,8 +2383,9 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c { ngx_http_core_loc_conf_t *lcf = conf; - ngx_uint_t alias; - ngx_str_t *value; + ngx_str_t *value; + ngx_uint_t alias, n; + ngx_http_script_compile_t sc; alias = (cmd->name.len == sizeof("alias") - 1) ? 1 : 0; @@ -2372,6 +2416,26 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_c lcf->root.len--; } + n = ngx_http_script_variables_count(&value[1]); + + if (n == 0) { + return NGX_CONF_OK; + } + + ngx_memzero(&sc, sizeof(ngx_http_script_compile_t)); + + sc.cf = cf; + sc.source = &value[1]; + sc.lengths = &lcf->root_lengths; + sc.values = &lcf->root_values; + sc.variables = n; + sc.complete_lengths = 1; + sc.complete_values = 1; + + if (ngx_http_script_compile(&sc) != NGX_OK) { + return NGX_CONF_ERROR; + } + return NGX_CONF_OK; } diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -197,6 +197,9 @@ struct ngx_http_core_loc_conf_s { ngx_str_t root; /* root, alias */ ngx_str_t post_action; + ngx_array_t *root_lengths; + ngx_array_t *root_values; + ngx_array_t *types; ngx_hash_t types_hash; ngx_str_t default_type; diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c --- a/src/http/ngx_http_postpone_filter_module.c +++ b/src/http/ngx_http_postpone_filter_module.c @@ -102,18 +102,22 @@ ngx_http_postpone_filter(ngx_http_reques out = in; } - if (out == NULL && r->main->out == NULL && !r->main->connection->buffered) { - return NGX_OK; - } + rc = NGX_OK; + + if (out || r->main->out || r->main->connection->buffered) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http postpone filter out \"%V?%V\"", &r->uri, &r->args); - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http postpone filter out \"%V?%V\"", &r->uri, &r->args); + if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { + + rc = ngx_http_next_filter(r->main, out); - rc = ngx_http_next_filter(r->main, out); - - if (rc == NGX_ERROR) { - /* NGX_ERROR may be returned by any filter */ - r->connection->error = 1; + if (rc == NGX_ERROR) { + /* NGX_ERROR may be returned by any filter */ + r->connection->error = 1; + } + } } if (r->postponed == NULL) { @@ -135,6 +139,7 @@ static ngx_int_t ngx_http_postpone_filter_output_postponed_request(ngx_http_request_t *r) { ngx_int_t rc; + ngx_chain_t *out; ngx_http_postponed_request_t *pr; for ( ;; ) { @@ -165,13 +170,17 @@ ngx_http_postpone_filter_output_postpone pr = r->postponed; } - if (pr->out) { + out = pr->out; + + if (out) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http postpone filter out postponed \"%V?%V\"", &r->uri, &r->args); - if (ngx_http_next_filter(r->main, pr->out) == NGX_ERROR) { - return NGX_ERROR; + if (!(out && out->next == NULL && ngx_buf_sync_only(out->buf))) { + if (ngx_http_next_filter(r->main, out) == NGX_ERROR) { + return NGX_ERROR; + } } } diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h --- a/src/http/ngx_http_request.h +++ b/src/http/ngx_http_request.h @@ -340,6 +340,8 @@ struct ngx_http_request_s { ngx_http_variable_value_t *variables; + size_t root_length; + size_t limit_rate; /* used to learn the Apache compatible response length without a header */