summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES13
-rw-r--r--CHANGES.ru13
-rw-r--r--auto/cc/msvc8
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/core/ngx_hash.c8
-rw-r--r--src/core/ngx_inet.c4
-rw-r--r--src/http/modules/ngx_http_access_module.c6
-rw-r--r--src/http/modules/ngx_http_addition_filter_module.c24
-rw-r--r--src/http/modules/ngx_http_auth_basic_module.c7
-rw-r--r--src/http/modules/ngx_http_referer_module.c2
-rw-r--r--src/http/modules/ngx_http_rewrite_module.c76
-rw-r--r--src/http/modules/perl/nginx.xs35
-rw-r--r--src/http/ngx_http.c8
-rw-r--r--src/http/ngx_http_config.h3
-rw-r--r--src/http/ngx_http_core_module.c142
-rw-r--r--src/http/ngx_http_core_module.h5
-rw-r--r--src/http/ngx_http_parse.c.orig1166
-rw-r--r--src/http/ngx_http_request.c2
-rw-r--r--src/http/ngx_http_request.h7
-rw-r--r--src/http/ngx_http_script.c85
-rw-r--r--src/http/ngx_http_script.h15
21 files changed, 414 insertions, 1217 deletions
diff --git a/CHANGES b/CHANGES
index a023a459f..2808a46ef 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,17 @@
+Changes with nginx 0.3.37 07 Apr 2006
+
+ *) Feature: the "limit_except" directive.
+
+ *) Feature: the "if" directive supports the "!~", "!~*", "-f", and
+ "!-f" operators.
+
+ *) Feature: the ngx_http_perl_module supports the $r->request_body
+ method.
+
+ *) Bugfix: in the ngx_http_addition_filter_module.
+
+
Changes with nginx 0.3.36 05 Apr 2006
*) Feature: the ngx_http_addition_filter_module.
diff --git a/CHANGES.ru b/CHANGES.ru
index a89bfc8a6..2f8a986d4 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,17 @@
+Изменения в nginx 0.3.37 07.04.2006
+
+ *) Добавление: директива limit_except.
+
+ *) Добавление: директива if поддерживает операторы "!~", "!~*", "-f" и
+ "!-f".
+
+ *) Добавление: модуль ngx_http_perl_module поддерживает метод
+ $r->request_body.
+
+ *) Исправление: в модуле ngx_http_addition_filter_module.
+
+
Изменения в nginx 0.3.36 05.04.2006
*) Добавление: модуль ngx_http_addition_filter_module.
diff --git a/auto/cc/msvc b/auto/cc/msvc
index a890234e0..2f1e8bcd5 100644
--- a/auto/cc/msvc
+++ b/auto/cc/msvc
@@ -116,6 +116,12 @@ ngx_binout="-Fe"
ngx_objext="obj"
ngx_binext=".exe"
+# Borland make
+#ngx_long_start='@&&|
+# '
+#ngx_long_end='|'
+
+# MS nmake
ngx_long_start='@<<
'
ngx_long_end='<<'
@@ -123,6 +129,6 @@ ngx_long_regex_cont=' \
'
ngx_long_cont='
'
-
+# MSVC understand / in path
#ngx_regex_dirsep='\\'
#ngx_dirsep="\\"
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 3f910cb26..06e46c0c6 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.3.36"
+#define NGINX_VER "nginx/0.3.37"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/core/ngx_hash.c b/src/core/ngx_hash.c
index 2876318a3..0ee5e77ca 100644
--- a/src/core/ngx_hash.c
+++ b/src/core/ngx_hash.c
@@ -164,10 +164,14 @@ ngx_hash_init(ngx_hash_init_t *hinit, ngx_hash_key_t *names, ngx_uint_t nelts)
return NGX_ERROR;
}
- start = nelts / (ngx_cacheline_size / (2 * sizeof(void *)) - 1);
+ bucket_size = hinit->bucket_size - sizeof(void *);
+
+ start = nelts / (bucket_size / (2 * sizeof(void *)) - 1);
start = start ? start : 1;
- bucket_size = hinit->bucket_size - sizeof(void *);
+ if (hinit->max_size > 10000 && hinit->max_size / nelts < 100) {
+ start = hinit->max_size - 1000;
+ }
for (size = start; size < hinit->max_size; size++) {
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c
index ee68fc1c2..a42df699b 100644
--- a/src/core/ngx_inet.c
+++ b/src/core/ngx_inet.c
@@ -21,8 +21,8 @@
*/
-static
-ngx_inline size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len)
+static ngx_inline size_t
+ngx_sprint_uchar(u_char *text, u_char c, size_t len)
{
size_t n;
ngx_uint_t c1, c2;
diff --git a/src/http/modules/ngx_http_access_module.c b/src/http/modules/ngx_http_access_module.c
index 0e3430385..710dd248e 100644
--- a/src/http/modules/ngx_http_access_module.c
+++ b/src/http/modules/ngx_http_access_module.c
@@ -35,14 +35,16 @@ static ngx_int_t ngx_http_access_init(ngx_cycle_t *cycle);
static ngx_command_t ngx_http_access_commands[] = {
{ ngx_string("allow"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
+ |NGX_CONF_TAKE1,
ngx_http_access_rule,
NGX_HTTP_LOC_CONF_OFFSET,
0,
NULL },
{ ngx_string("deny"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
+ |NGX_CONF_TAKE1,
ngx_http_access_rule,
NGX_HTTP_LOC_CONF_OFFSET,
0,
diff --git a/src/http/modules/ngx_http_addition_filter_module.c b/src/http/modules/ngx_http_addition_filter_module.c
index efd622e5a..842124d91 100644
--- a/src/http/modules/ngx_http_addition_filter_module.c
+++ b/src/http/modules/ngx_http_addition_filter_module.c
@@ -16,8 +16,7 @@ typedef struct {
typedef struct {
- unsigned before_body_sent:1;
- unsigned after_body_sent:1;
+ ngx_uint_t before_body_sent;
} ngx_http_addition_ctx_t;
@@ -92,6 +91,12 @@ ngx_http_addition_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
+ conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
+
+ if (conf->before_body.len == 0 && conf->after_body.len == 0) {
+ return ngx_http_next_header_filter(r);
+ }
+
if (ngx_strncasecmp(r->headers_out.content_type.data, "text/html",
sizeof("text/html") - 1)
!= 0)
@@ -99,12 +104,6 @@ ngx_http_addition_header_filter(ngx_http_request_t *r)
return ngx_http_next_header_filter(r);
}
- conf = ngx_http_get_module_loc_conf(r, ngx_http_addition_filter_module);
-
- if (conf->before_body.len == 0 && conf->after_body.len == 0) {
- return ngx_http_next_header_filter(r);
- }
-
ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_addition_ctx_t));
if (ctx == NULL) {
return NGX_ERROR;
@@ -155,17 +154,14 @@ ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
for (cl = in; cl; cl = cl->next) {
if (cl->buf->last_buf) {
cl->buf->last_buf = 0;
+ cl->buf->sync = 1;
last = 1;
}
}
rc = ngx_http_next_body_filter(r, in);
- if (rc == NGX_ERROR
- || !last
- || ctx->after_body_sent
- || conf->after_body.len == 0)
- {
+ if (rc == NGX_ERROR || !last || conf->after_body.len == 0) {
return rc;
}
@@ -173,7 +169,7 @@ ngx_http_addition_body_filter(ngx_http_request_t *r, ngx_chain_t *in)
return NGX_ERROR;
}
- ctx->after_body_sent = 1;
+ ngx_http_set_ctx(r, NULL, ngx_http_addition_filter_module);
return ngx_http_send_special(r, NGX_HTTP_LAST);
}
diff --git a/src/http/modules/ngx_http_auth_basic_module.c b/src/http/modules/ngx_http_auth_basic_module.c
index 48192cad1..d33e7f6cf 100644
--- a/src/http/modules/ngx_http_auth_basic_module.c
+++ b/src/http/modules/ngx_http_auth_basic_module.c
@@ -41,14 +41,16 @@ static ngx_conf_post_handler_pt ngx_http_auth_basic_p = ngx_http_auth_basic;
static ngx_command_t ngx_http_auth_basic_commands[] = {
{ ngx_string("auth_basic"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
+ |NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_auth_basic_loc_conf_t, realm),
&ngx_http_auth_basic_p },
{ ngx_string("auth_basic_user_file"),
- NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LMT_CONF
+ |NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_auth_basic_loc_conf_t, user_file),
@@ -58,7 +60,6 @@ static ngx_command_t ngx_http_auth_basic_commands[] = {
};
-
ngx_http_module_t ngx_http_auth_basic_module_ctx = {
NULL, /* preconfiguration */
NULL, /* postconfiguration */
diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c
index 3ad419b39..eb01857ab 100644
--- a/src/http/modules/ngx_http_referer_module.c
+++ b/src/http/modules/ngx_http_referer_module.c
@@ -217,7 +217,7 @@ ngx_http_referer_merge_conf(ngx_conf_t *cf, void *parent, void *child)
}
if ((conf->no_referer == 1 || conf->blocked_referer == 1)
- && conf->keys->keys.nelts == 0 && conf->keys->dns_wildcards.nelts)
+ && conf->keys->keys.nelts == 0 && conf->keys->dns_wildcards.nelts == 0)
{
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"the \"none\" or \"blocked\" referers are specified "
diff --git a/src/http/modules/ngx_http_rewrite_module.c b/src/http/modules/ngx_http_rewrite_module.c
index 2c895c520..5709b5652 100644
--- a/src/http/modules/ngx_http_rewrite_module.c
+++ b/src/http/modules/ngx_http_rewrite_module.c
@@ -578,7 +578,7 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
elts = lcf->codes->elts;
- /* the inside directives must compile to the same code array */
+ /* the inner directives must be compiled to the same code array */
nlcf = ctx->loc_conf[ngx_http_rewrite_module.ctx_index];
nlcf->codes = lcf->codes;
@@ -629,9 +629,12 @@ ngx_http_rewrite_if(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
static char *
ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
{
+ u_char *p;
+ size_t len;
ngx_str_t *value, err;
ngx_uint_t cur, last, n;
ngx_http_script_code_pt *code;
+ ngx_http_script_file_code_t *fop;
ngx_http_script_regex_code_t *regex;
u_char errstr[NGX_MAX_CONF_ERRSTR];
@@ -667,11 +670,14 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
value[last].data[value[last].len] = '\0';
}
- if (value[cur].len > 1 && value[cur].data[0] == '$') {
+ len = value[cur].len;
+ p = value[cur].data;
+
+ if (len > 1 && p[0] == '$') {
if (cur != last && cur + 2 != last) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "invalid condition \"%V\"", &value[cur]);
+ "invalid condition \"%V\"", &value[cur]);
return NGX_CONF_ERROR;
}
@@ -685,7 +691,10 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
cur++;
- if (value[cur].len == 1 && value[cur].data[0] == '=') {
+ len = value[cur].len;
+ p = value[cur].data;
+
+ if (len == 1 && p[0] == '=') {
if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
return NGX_CONF_ERROR;
@@ -702,9 +711,8 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
return NGX_CONF_OK;
}
- if (value[cur].len == 2
- && value[cur].data[0] == '!' && value[cur].data[1] == '=')
- {
+ if (len == 2 && p[0] == '!' && p[1] == '=') {
+
if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
return NGX_CONF_ERROR;
}
@@ -719,9 +727,10 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
return NGX_CONF_OK;
}
- if ((value[cur].len == 1 && value[cur].data[0] == '~')
- || (value[cur].len == 2
- && value[cur].data[0] == '~' && value[cur].data[1] == '*'))
+ if ((len == 1 && p[0] == '~')
+ || (len == 2 && p[0] == '~' && p[1] == '*')
+ || (len == 2 && p[0] == '!' && p[1] == '~')
+ || (len == 3 && p[0] == '!' && p[1] == '~' && p[2] == '*'))
{
regex = ngx_http_script_start_code(cf->pool, &lcf->codes,
sizeof(ngx_http_script_regex_code_t));
@@ -735,8 +744,8 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
err.data = errstr;
regex->regex = ngx_regex_compile(&value[last],
- (value[cur].len == 2) ? NGX_REGEX_CASELESS : 0,
- cf->pool, &err);
+ (p[len - 1] == '*') ? NGX_REGEX_CASELESS : 0,
+ cf->pool, &err);
if (regex->regex == NULL) {
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "%s", err.data);
@@ -746,6 +755,9 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
regex->code = ngx_http_script_regex_start_code;
regex->next = sizeof(ngx_http_script_regex_code_t);
regex->test = 1;
+ if (p[0] == '!') {
+ regex->negative_test = 1;
+ }
regex->name = value[last];
n = ngx_regex_capture_count(regex->regex);
@@ -764,6 +776,46 @@ ngx_http_rewrite_if_condition(ngx_conf_t *cf, ngx_http_rewrite_loc_conf_t *lcf)
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
"unexpected \"%V\" in condition", &value[cur]);
return NGX_CONF_ERROR;
+
+ } else if ((len == 2 && p[0] == '-')
+ || (len == 3 && p[0] == '!' && p[1] == '-'))
+ {
+ if (cur + 1 != last) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid condition \"%V\"", &value[cur]);
+ return NGX_CONF_ERROR;
+ }
+
+ value[last].data[value[last].len] = '\0';
+ value[last].len++;
+
+ if (ngx_http_rewrite_value(cf, lcf, &value[last]) != NGX_CONF_OK) {
+ return NGX_CONF_ERROR;
+ }
+
+ fop = ngx_http_script_start_code(cf->pool, &lcf->codes,
+ sizeof(ngx_http_script_file_code_t));
+ if (fop == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ fop->code = ngx_http_script_file_code;
+
+ if (p[1] == 'f') {
+ fop->op = ngx_http_script_file_plain;
+ return NGX_CONF_OK;
+ }
+
+ if (p[0] == '!') {
+ if (p[2] == 'f') {
+ fop->op = ngx_http_script_file_not_plain;
+ return NGX_CONF_OK;
+ }
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid condition \"%V\"", &value[cur]);
+ return NGX_CONF_ERROR;
}
ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
diff --git a/src/http/modules/perl/nginx.xs b/src/http/modules/perl/nginx.xs
index d0453ea8d..7e2cec30e 100644
--- a/src/http/modules/perl/nginx.xs
+++ b/src/http/modules/perl/nginx.xs
@@ -261,6 +261,41 @@ header_in(r, key)
RETVAL
+SV *
+request_body(r)
+ nginx r
+
+ PREINIT:
+
+ STRLEN len;
+ ngx_chain_t *cl;
+
+ CODE:
+
+ len = 0;
+
+ for (cl = r->request_body->bufs; cl; cl = cl->next) {
+ if (cl->buf->in_file) {
+ XSRETURN_UNDEF;
+ }
+
+ len += cl->buf->last - cl->buf->pos;
+ }
+
+ if (len == 0) {
+ XSRETURN_UNDEF;
+ }
+
+ RETVAL = newSV(len);
+
+ for (cl = r->request_body->bufs; cl; cl = cl->next) {
+ sv_catpvn(RETVAL, cl->buf->pos, cl->buf->last - cl->buf->pos);
+ }
+
+ OUTPUT:
+ RETVAL
+
+
int
header_out(r, key, value)
nginx r
diff --git a/src/http/ngx_http.c b/src/http/ngx_http.c
index b50d580c5..5a23d1dbb 100644
--- a/src/http/ngx_http.c
+++ b/src/http/ngx_http.c
@@ -595,8 +595,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
- "conflicting server name \"%V\", ignored",
- &name[s].name);
+ "conflicting server name \"%V\" on %s, ignored",
+ &name[s].name, in_addr[a].listen_conf->addr);
}
}
@@ -617,8 +617,8 @@ ngx_http_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
if (rc == NGX_BUSY) {
ngx_log_error(NGX_LOG_WARN, cf->log, 0,
- "conflicting server name \"%V\", ignored",
- &name[s].name);
+ "conflicting server name \"%V\" on %s, ignored",
+ &name[s].name, in_addr[a].listen_conf->addr);
}
}
diff --git a/src/http/ngx_http_config.h b/src/http/ngx_http_config.h
index 84816ae27..66292105a 100644
--- a/src/http/ngx_http_config.h
+++ b/src/http/ngx_http_config.h
@@ -42,7 +42,8 @@ typedef struct {
#define NGX_HTTP_LOC_CONF 0x08000000
#define NGX_HTTP_UPS_CONF 0x10000000
#define NGX_HTTP_SIF_CONF 0x20000000
-#define NGX_HTTP_LIF_CONF 0x80000000
+#define NGX_HTTP_LIF_CONF 0x40000000
+#define NGX_HTTP_LMT_CONF 0x80000000
#define NGX_HTTP_MAIN_CONF_OFFSET offsetof(ngx_http_conf_ctx_t, main_conf)
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index 6e55c4074..62e172b62 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -11,6 +11,12 @@
#include <nginx.h>
+typedef struct {
+ char *name;
+ uint32_t method;
+} ngx_http_method_name_t;
+
+
#define NGX_HTTP_LOCATION_EXACT 1
#define NGX_HTTP_LOCATION_AUTO_REDIRECT 2
#define NGX_HTTP_LOCATION_NOREGEX 3
@@ -48,6 +54,8 @@ static char *ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd,
static char *ngx_http_core_server_name(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
+static char *ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd,
+ void *conf);
static char *ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd,
void *conf);
static char *ngx_http_core_error_log(ngx_conf_t *cf, ngx_command_t *cmd,
@@ -225,6 +233,13 @@ static ngx_command_t ngx_http_core_commands[] = {
0,
NULL },
+ { ngx_string("limit_except"),
+ NGX_HTTP_LOC_CONF|NGX_CONF_BLOCK|NGX_CONF_1MORE,
+ ngx_http_core_limit_except,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ 0,
+ NULL },
+
{ ngx_string("client_max_body_size"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_size_slot,
@@ -711,6 +726,11 @@ ngx_http_update_location_config(ngx_http_request_t *r)
clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ if (r->method & clcf->limit_except) {
+ r->loc_conf = clcf->limit_except_loc_conf;
+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+ }
+
r->connection->log->file = clcf->err_log->file;
if (!(r->connection->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
r->connection->log->log_level = clcf->err_log->log_level;
@@ -1949,6 +1969,7 @@ ngx_http_core_create_loc_conf(ngx_conf_t *cf)
* set by ngx_pcalloc():
*
* lcf->root = { 0, NULL };
+ * lcf->limit_except = 0;
* lcf->post_action = { 0, NULL };
* lcf->types = NULL;
* lcf->default_type = { 0, NULL };
@@ -2245,6 +2266,9 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
ls->addr = INADDR_ANY;
}
+ n = ngx_inet_ntop(AF_INET, &ls->addr, ls->conf.addr, INET_ADDRSTRLEN + 6);
+ ngx_sprintf(&ls->conf.addr[n], ":%ui", ls->port);
+
if (cf->args->nelts == 2) {
return NGX_CONF_OK;
}
@@ -2480,6 +2504,124 @@ ngx_http_core_root(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
}
+static ngx_http_method_name_t ngx_methods_names[] = {
+ { "GET", (uint32_t) ~NGX_HTTP_GET },
+ { "HEAD", (uint32_t) ~NGX_HTTP_HEAD },
+ { NULL, 0 }
+};
+
+
+static char *
+ngx_http_core_limit_except(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+ ngx_http_core_loc_conf_t *clcf = conf;
+
+ char *rv;
+ void *mconf;
+ ngx_str_t *value;
+ ngx_uint_t i;
+ ngx_conf_t save;
+ ngx_http_module_t *module;
+ ngx_http_conf_ctx_t *ctx, *pctx;
+ ngx_http_method_name_t *name;
+ ngx_http_core_loc_conf_t *lcf, **clcfp;
+
+ if (clcf->limit_except) {
+ return "duplicate";
+ }
+
+ clcf->limit_except = 0xffffffff;
+
+ value = cf->args->elts;
+
+ for (i = 1; i < cf->args->nelts; i++) {
+ for (name = ngx_methods_names; name->name; name++) {
+
+ if (ngx_strcasecmp(value[i].data, name->name) == 0) {
+ clcf->limit_except &= name->method;
+ goto next;
+ }
+ }
+
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "invalid method \"%V\"", &value[i]);
+ return NGX_CONF_ERROR;
+
+ next:
+ continue;
+ }
+
+ if (!(clcf->limit_except & NGX_HTTP_GET)) {
+ clcf->limit_except &= (uint32_t) ~NGX_HTTP_HEAD;
+ }
+
+ ctx = ngx_pcalloc(cf->pool, sizeof(ngx_http_conf_ctx_t));
+ if (ctx == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ pctx = cf->ctx;
+ ctx->main_conf = pctx->main_conf;
+ ctx->srv_conf = pctx->srv_conf;
+
+ ctx->loc_conf = ngx_pcalloc(cf->pool, sizeof(void *) * ngx_http_max_module);
+ if (ctx->loc_conf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ for (i = 0; ngx_modules[i]; i++) {
+ if (ngx_modules[i]->type != NGX_HTTP_MODULE) {
+ continue;
+ }
+
+ module = ngx_modules[i]->ctx;
+
+ if (module->create_loc_conf) {
+
+ mconf = module->create_loc_conf(cf);
+ if (mconf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ctx->loc_conf[ngx_modules[i]->ctx_index] = mconf;
+ }
+ }
+
+
+ lcf = ctx->loc_conf[ngx_http_core_module.ctx_index];
+ clcf->limit_except_loc_conf = ctx->loc_conf;
+ lcf->loc_conf = ctx->loc_conf;
+ lcf->name = clcf->name;
+ lcf->noname = 1;
+
+ if (clcf->locations.elts == NULL) {
+ if (ngx_array_init(&clcf->locations, cf->pool, 4, sizeof(void *))
+ == NGX_ERROR)
+ {
+ return NGX_CONF_ERROR;
+ }
+ }
+
+ clcfp = ngx_array_push(&clcf->locations);
+ if (clcfp == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ *clcfp = lcf;
+
+
+ save = *cf;
+ cf->ctx = ctx;
+ cf->cmd_type = NGX_HTTP_LMT_CONF;
+
+ rv = ngx_conf_parse(cf, NULL);
+
+ *cf = save;
+
+ return rv;
+}
+
+
static char *
ngx_http_core_error_page(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
{
diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h
index 9f5b65c96..6e19ebf8c 100644
--- a/src/http/ngx_http_core_module.h
+++ b/src/http/ngx_http_core_module.h
@@ -28,6 +28,8 @@ typedef struct {
ngx_uint_t deferred_accept;
#endif
+ u_char addr[INET_ADDRSTRLEN + 6];
+
} ngx_http_listen_conf_t;
@@ -196,6 +198,9 @@ struct ngx_http_core_loc_conf_s {
/* pointer to the modules' loc_conf */
void **loc_conf ;
+ uint32_t limit_except;
+ void **limit_except_loc_conf ;
+
ngx_http_handler_pt handler;
ngx_str_t root; /* root, alias */
diff --git a/src/http/ngx_http_parse.c.orig b/src/http/ngx_http_parse.c.orig
deleted file mode 100644
index 2ec6979d0..000000000
--- a/src/http/ngx_http_parse.c.orig
+++ /dev/null
@@ -1,1166 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- */
-
-
-#include <ngx_config.h>
-#include <ngx_core.h>
-#include <ngx_http.h>
-
-
-ngx_int_t
-ngx_http_parse_request_line(ngx_http_request_t *r, ngx_buf_t *b)
-{
- u_char c, ch, *p, *m;
- enum {
- sw_start = 0,
- sw_method,
- sw_space_after_method,
- sw_spaces_before_uri,
- sw_schema,
- sw_schema_slash,
- sw_schema_slash_slash,
- sw_host,
- sw_port,
- sw_after_slash_in_uri,
- sw_check_uri,
- sw_uri,
- sw_http_09,
- sw_http_H,
- sw_http_HT,
- sw_http_HTT,
- sw_http_HTTP,
- sw_first_major_digit,
- sw_major_digit,
- sw_first_minor_digit,
- sw_minor_digit,
- sw_almost_done
- } state;
-
- state = r->state;
-
- for (p = b->pos; p < b->last; p++) {
- ch = *p;
-
- /* gcc 2.95.2 and msvc 6.0 compile this switch as an jump table */
-
- switch (state) {
-
- /* HTTP methods: GET, HEAD, POST */
- case sw_start:
- r->request_start = p;
-
- if (ch == CR || ch == LF) {
- break;
- }
-
- if (ch < 'A' || ch > 'Z') {
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
-
- state = sw_method;
- break;
-
- case sw_method:
- if (ch == ' ') {
- r->method_end = p - 1;
- m = r->request_start;
-
- if (p - m == 3) {
-
- if (m[0] == 'G' && m[1] == 'E' && m[2] == 'T') {
- r->method = NGX_HTTP_GET;
- }
-
- } else if (p - m == 4) {
-
- if (m[0] == 'P' && m[1] == 'O'
- && m[2] == 'S' && m[3] == 'T')
- {
- r->method = NGX_HTTP_POST;
-
- } else if (m[0] == 'H' && m[1] == 'E'
- && m[2] == 'A' && m[3] == 'D')
- {
- r->method = NGX_HTTP_HEAD;
- }
- }
-
- state = sw_spaces_before_uri;
- break;
- }
-
- if (ch < 'A' || ch > 'Z') {
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
-
- break;
-
- /* single space after method */
- case sw_space_after_method:
- switch (ch) {
- case ' ':
- state = sw_spaces_before_uri;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_METHOD;
- }
- break;
-
- /* space* before URI */
- case sw_spaces_before_uri:
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- r->schema_start = p;
- state = sw_schema;
- break;
- }
-
- switch (ch) {
- case '/':
- r->uri_start = p;
- state = sw_after_slash_in_uri;
- break;
- case ' ':
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_schema:
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- break;
- }
-
- switch (ch) {
- case ':':
- r->schema_end = p;
- state = sw_schema_slash;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_schema_slash:
- switch (ch) {
- case '/':
- state = sw_schema_slash_slash;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_schema_slash_slash:
- switch (ch) {
- case '/':
- r->host_start = p;
- state = sw_host;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_host:
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- break;
- }
-
- if ((ch >= '0' && ch <= '9') || ch == '.' || ch == '-')
- {
- break;
- }
-
- switch (ch) {
- case ':':
- r->host_end = p;
- state = sw_port;
- break;
- case '/':
- r->host_end = p;
- r->uri_start = p;
- state = sw_after_slash_in_uri;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_port:
- if (ch >= '0' && ch <= '9') {
- break;
- }
-
- switch (ch) {
- case '/':
- r->port_end = p;
- r->uri_start = p;
- state = sw_after_slash_in_uri;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- /* check "/.", "//", "%", and "\" (Win32) in URI */
- case sw_after_slash_in_uri:
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- state = sw_check_uri;
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- state = sw_check_uri;
- break;
- }
-
- switch (ch) {
- case ' ':
- r->uri_end = p;
- state = sw_http_09;
- break;
- case CR:
- r->uri_end = p;
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->uri_end = p;
- r->http_minor = 9;
- goto done;
- case '.':
- r->complex_uri = 1;
- state = sw_uri;
- break;
- case '%':
- r->quoted_uri = 1;
- state = sw_uri;
- break;
- case '/':
- r->complex_uri = 1;
- state = sw_uri;
- break;
-#if (NGX_WIN32)
- case '\\':
- r->complex_uri = 1;
- state = sw_uri;
- break;
-#endif
- case '?':
- r->args_start = p + 1;
- state = sw_uri;
- break;
- case '+':
- r->plus_in_uri = 1;
- break;
- case '\0':
- r->zero_in_uri = 1;
- break;
- default:
- state = sw_check_uri;
- break;
- }
- break;
-
- /* check "/", "%" and "\" (Win32) in URI */
- case sw_check_uri:
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- break;
- }
-
- switch (ch) {
- case '/':
- r->uri_ext = NULL;
- state = sw_after_slash_in_uri;
- break;
- case '.':
- r->uri_ext = p + 1;
- break;
- case ' ':
- r->uri_end = p;
- state = sw_http_09;
- break;
- case CR:
- r->uri_end = p;
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->uri_end = p;
- r->http_minor = 9;
- goto done;
-#if (NGX_WIN32)
- case '\\':
- r->complex_uri = 1;
- state = sw_after_slash_in_uri;
- break;
-#endif
- case '%':
- r->quoted_uri = 1;
- state = sw_uri;
- break;
- case '+':
- r->plus_in_uri = 1;
- break;
- case '?':
- r->args_start = p + 1;
- state = sw_uri;
- break;
- case '\0':
- r->zero_in_uri = 1;
- break;
- }
- break;
-
- /* URI */
- case sw_uri:
- switch (ch) {
- case ' ':
- r->uri_end = p;
- state = sw_http_09;
- break;
- case CR:
- r->uri_end = p;
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->uri_end = p;
- r->http_minor = 9;
- goto done;
- case '+':
- r->plus_in_uri = 1;
- break;
- case '\0':
- r->zero_in_uri = 1;
- break;
- }
- break;
-
- /* space+ after URI */
- case sw_http_09:
- switch (ch) {
- case ' ':
- break;
- case CR:
- r->http_minor = 9;
- state = sw_almost_done;
- break;
- case LF:
- r->http_minor = 9;
- goto done;
- case 'H':
- r->http_protocol.data = p;
- state = sw_http_H;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_http_H:
- switch (ch) {
- case 'T':
- state = sw_http_HT;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_http_HT:
- switch (ch) {
- case 'T':
- state = sw_http_HTT;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_http_HTT:
- switch (ch) {
- case 'P':
- state = sw_http_HTTP;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- case sw_http_HTTP:
- switch (ch) {
- case '/':
- state = sw_first_major_digit;
- break;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- break;
-
- /* first digit of major HTTP version */
- case sw_first_major_digit:
- if (ch < '1' || ch > '9') {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
-
- r->http_major = ch - '0';
- state = sw_major_digit;
- break;
-
- /* major HTTP version or dot */
- case sw_major_digit:
- if (ch == '.') {
- state = sw_first_minor_digit;
- break;
- }
-
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
-
- r->http_major = r->http_major * 10 + ch - '0';
- break;
-
- /* first digit of minor HTTP version */
- case sw_first_minor_digit:
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
-
- r->http_minor = ch - '0';
- state = sw_minor_digit;
- break;
-
- /* minor HTTP version or end of request line */
- case sw_minor_digit:
- if (ch == CR) {
- state = sw_almost_done;
- break;
- }
-
- if (ch == LF) {
- goto done;
- }
-
- if (ch < '0' || ch > '9') {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
-
- r->http_minor = r->http_minor * 10 + ch - '0';
- break;
-
- /* end of request line */
- case sw_almost_done:
- r->request_end = p - 1;
- switch (ch) {
- case LF:
- goto done;
- default:
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- }
- }
-
- b->pos = p;
- r->state = state;
-
- return NGX_AGAIN;
-
-done:
-
- b->pos = p + 1;
-
- if (r->request_end == NULL) {
- r->request_end = p;
- }
-
- r->http_version = r->http_major * 1000 + r->http_minor;
- r->state = sw_start;
-
- if (r->http_version == 9 && r->method != NGX_HTTP_GET) {
- return NGX_HTTP_PARSE_INVALID_09_METHOD;
- }
-
- return NGX_OK;
-}
-
-
-ngx_int_t
-ngx_http_parse_header_line(ngx_http_request_t *r, ngx_buf_t *b)
-{
- u_char c, ch, *p;
- ngx_uint_t hash;
- enum {
- sw_start = 0,
- sw_name,
- sw_space_before_value,
- sw_value,
- sw_space_after_value,
- sw_ignore_line,
- sw_almost_done,
- sw_header_almost_done
- } state;
-
- state = r->state;
- hash = r->header_hash;
-
- for (p = b->pos; p < b->last; p++) {
- ch = *p;
-
- switch (state) {
-
- /* first char */
- case sw_start:
- r->invalid_header = 0;
-
- switch (ch) {
- case CR:
- r->header_end = p;
- state = sw_header_almost_done;
- break;
- case LF:
- r->header_end = p;
- goto header_done;
- default:
- state = sw_name;
- r->header_name_start = p;
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- hash = c;
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- hash = ch;
- break;
- }
-
- r->invalid_header = 1;
-
- break;
-
- }
- break;
-
- /* header name */
- case sw_name:
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'z') {
- hash += c;
- break;
- }
-
- if (ch == ':') {
- r->header_name_end = p;
- state = sw_space_before_value;
- break;
- }
-
- if (ch == '-') {
- hash += ch;
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- hash += ch;
- break;
- }
-
- if (ch == CR) {
- r->header_name_end = p;
- r->header_start = p;
- r->header_end = p;
- state = sw_almost_done;
- break;
- }
-
- if (ch == LF) {
- r->header_name_end = p;
- r->header_start = p;
- r->header_end = p;
- goto done;
- }
-
- /* IIS may send the duplicate "HTTP/1.1 ..." lines */
- if (ch == '/'
- && r->upstream
- && p - r->header_name_start == 4
- && ngx_strncmp(r->header_name_start, "HTTP", 4) == 0)
- {
- state = sw_ignore_line;
- break;
- }
-
- r->invalid_header = 1;
-
- break;
-
- /* space* before header value */
- case sw_space_before_value:
- switch (ch) {
- case ' ':
- break;
- case CR:
- r->header_start = p;
- r->header_end = p;
- state = sw_almost_done;
- break;
- case LF:
- r->header_start = p;
- r->header_end = p;
- goto done;
- default:
- r->header_start = p;
- state = sw_value;
- break;
- }
- break;
-
- /* header value */
- case sw_value:
- switch (ch) {
- case ' ':
- r->header_end = p;
- state = sw_space_after_value;
- break;
- case CR:
- r->header_end = p;
- state = sw_almost_done;
- break;
- case LF:
- r->header_end = p;
- goto done;
- }
- break;
-
- /* space* before end of header line */
- case sw_space_after_value:
- switch (ch) {
- case ' ':
- break;
- case CR:
- state = sw_almost_done;
- break;
- case LF:
- goto done;
- default:
- state = sw_value;
- break;
- }
- break;
-
- /* ignore header line */
- case sw_ignore_line:
- switch (ch) {
- case LF:
- state = sw_start;
- break;
- default:
- break;
- }
- break;
-
- /* end of header line */
- case sw_almost_done:
- switch (ch) {
- case CR:
- break;
- case LF:
- goto done;
- default:
- return NGX_HTTP_PARSE_INVALID_HEADER;
- }
-
- /* end of header */
- case sw_header_almost_done:
- switch (ch) {
- case LF:
- goto header_done;
- default:
- return NGX_HTTP_PARSE_INVALID_HEADER;
- }
- }
- }
-
- b->pos = p;
- r->state = state;
- r->header_hash = hash;
-
- return NGX_AGAIN;
-
-done:
-
- b->pos = p + 1;
- r->state = sw_start;
- r->header_hash = hash;
-
- return NGX_OK;
-
-header_done:
-
- b->pos = p + 1;
- r->state = sw_start;
-
- return NGX_HTTP_PARSE_HEADER_DONE;
-}
-
-
-ngx_int_t
-ngx_http_parse_complex_uri(ngx_http_request_t *r)
-{
- u_char c, ch, decoded, *p, *u;
- enum {
- sw_usual = 0,
- sw_slash,
- sw_dot,
- sw_dot_dot,
-#if (NGX_WIN32)
- sw_dot_dot_dot,
-#endif
- sw_quoted,
- sw_quoted_second
- } state, quoted_state;
-
-#if (NGX_SUPPRESS_WARN)
- decoded = '\0';
- quoted_state = sw_usual;
-#endif
-
- state = sw_usual;
- p = r->uri_start;
- u = r->uri.data;
- r->uri_ext = NULL;
- r->args_start = NULL;
-
- ch = *p++;
-
- while (p <= r->uri_end) {
-
- /*
- * we use "ch = *p++" inside the cycle, but this operation is safe,
- * because after the URI there is always at least one charcter:
- * the line feed
- */
-
- ngx_log_debug4(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "s:%d in:'%Xd:%c', out:'%c'", state, ch, ch, *u);
-
- switch (state) {
-
- case sw_usual:
- switch(ch) {
-#if (NGX_WIN32)
- case '\\':
- r->uri_ext = NULL;
-
- if (p == r->uri_start + r->uri.len) {
-
- /*
- * we omit the last "\" to cause redirect because
- * the browsers do not treat "\" as "/" in relative URL path
- */
-
- break;
- }
-
- state = sw_slash;
- *u++ = '/';
- break;
-#endif
- case '/':
- r->uri_ext = NULL;
- state = sw_slash;
- *u++ = ch;
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto done;
- case '.':
- r->uri_ext = u + 1;
- *u++ = ch;
- break;
- default:
- *u++ = ch;
- break;
- }
- ch = *p++;
- break;
-
- case sw_slash:
- switch(ch) {
-#if (NGX_WIN32)
- case '\\':
-#endif
- case '/':
- break;
- case '.':
- state = sw_dot;
- *u++ = ch;
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto done;
- default:
- state = sw_usual;
- *u++ = ch;
- break;
- }
- ch = *p++;
- break;
-
- case sw_dot:
- switch(ch) {
-#if (NGX_WIN32)
- case '\\':
-#endif
- case '/':
- state = sw_slash;
- u--;
- break;
- case '.':
- state = sw_dot_dot;
- *u++ = ch;
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto done;
- default:
- state = sw_usual;
- *u++ = ch;
- break;
- }
- ch = *p++;
- break;
-
- case sw_dot_dot:
- switch(ch) {
-#if (NGX_WIN32)
- case '\\':
-#endif
- case '/':
- state = sw_slash;
- u -= 4;
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*(u - 1) != '/') {
- u--;
- }
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto done;
-#if (NGX_WIN32)
- case '.':
- state = sw_dot_dot_dot;
- *u++ = ch;
- break;
-#endif
- default:
- state = sw_usual;
- *u++ = ch;
- break;
- }
- ch = *p++;
- break;
-
-#if (NGX_WIN32)
- case sw_dot_dot_dot:
- switch(ch) {
- case '\\':
- case '/':
- state = sw_slash;
- u -= 5;
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*u != '/') {
- u--;
- }
- if (u < r->uri.data) {
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- while (*(u - 1) != '/') {
- u--;
- }
- break;
- case '%':
- quoted_state = state;
- state = sw_quoted;
- break;
- case '?':
- r->args_start = p;
- goto done;
- default:
- state = sw_usual;
- *u++ = ch;
- break;
- }
- ch = *p++;
- break;
-#endif
-
- case sw_quoted:
- if (ch >= '0' && ch <= '9') {
- decoded = (u_char) (ch - '0');
- state = sw_quoted_second;
- ch = *p++;
- break;
- }
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'f') {
- decoded = (u_char) (c - 'a' + 10);
- state = sw_quoted_second;
- ch = *p++;
- break;
- }
-
- return NGX_HTTP_PARSE_INVALID_REQUEST;
-
- case sw_quoted_second:
- if (ch >= '0' && ch <= '9') {
- ch = (u_char) ((decoded << 4) + ch - '0');
-
- if (ch == '%') {
- state = sw_usual;
- *u++ = ch;
- ch = *p++;
- break;
- }
-
- if (ch == '\0') {
- r->zero_in_uri = 1;
- *u++ = ch;
- ch = *p++;
- }
-
- state = quoted_state;
- break;
- }
-
- c = (u_char) (ch | 0x20);
- if (c >= 'a' && c <= 'f') {
- ch = (u_char) ((decoded << 4) + c - 'a' + 10);
- if (ch == '?') {
- *u++ = ch;
- ch = *p++;
- }
- state = quoted_state;
- break;
- }
-
- return NGX_HTTP_PARSE_INVALID_REQUEST;
- }
- }
-
-done:
-
- r->uri.len = u - r->uri.data;
- r->uri.data[r->uri.len] = '\0';
-
- if (r->uri_ext) {
- r->exten.len = u - r->uri_ext;
- r->exten.data = r->uri_ext;
- }
-
- r->uri_ext = NULL;
-
- return NGX_OK;
-}
-
-
-ngx_int_t
-ngx_http_parse_unsafe_uri(ngx_http_request_t *r, ngx_str_t *uri,
- ngx_str_t *args, ngx_uint_t *flags)
-{
- u_char ch, *p;
- size_t len;
-
- len = uri->len;
- p = uri->data;
-
- if (len == 0 || p[0] == '?') {
- goto unsafe;
- }
-
- if (p[0] == '.' && len == 3 && p[1] == '.' && (p[2] == '/'
-#if (NGX_WIN32)
- || p[2] == '\\'
-#endif
- ))
- {
- goto unsafe;
- }
-
- for ( /* void */ ; len; len--) {
-
- ch = *p++;
-
- if (ch == '?') {
- args->len = len - 1;
- args->data = p;
- uri->len -= len;
-
- return NGX_OK;
- }
-
- if (ch == '\0') {
- *flags |= NGX_HTTP_ZERO_IN_URI;
- continue;
- }
-
- if (ch != '/'
-#if (NGX_WIN32)
- && ch != '\\'
-#endif
- )
- {
- continue;
- }
-
- if (len > 2) {
-
- /* detect "/../" */
-
- if (p[0] == '.' && p[1] == '.' && p[2] == '/') {
- goto unsafe;
- }
-
-#if (NGX_WIN32)
-
- if (p[2] == '\\') {
- goto unsafe;
- }
-
- if (len > 3) {
-
- /* detect "/.../" */
-
- if (p[0] == '.' && p[1] == '.' && p[2] == '.'
- && (p[3] == '/' || p[3] == '\\'))
- {
- goto unsafe;
- }
- }
-#endif
- }
- }
-
- return NGX_OK;
-
-unsafe:
-
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "unsafe URI \"%V\" was detected", uri);
-
- return NGX_ERROR;
-}
-
-
-ngx_int_t
-ngx_http_parse_multi_header_lines(ngx_array_t *headers, ngx_str_t *name,
- ngx_str_t *value)
-{
- ngx_uint_t i;
- u_char *start, *last, *end, ch;
- ngx_table_elt_t **h;
-
- h = headers->elts;
-
- for (i = 0; i < headers->nelts; i++) {
-
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, headers->pool->log, 0,
- "parse header: \"%V: %V\"", &h[i]->key, &h[i]->value);
-
- if (name->len > h[i]->value.len) {
- continue;
- }
-
- start = h[i]->value.data;
- end = h[i]->value.data + h[i]->value.len;
-
- while (start < end) {
-
- if (ngx_strncasecmp(start, name->data, name->len) != 0) {
- goto skip;
- }
-
- for (start += name->len; start < end && *start == ' '; start++) {
- /* void */
- }
-
- if (value == NULL) {
- if (start == end || *start == ',') {
- return i;
- }
-
- goto skip;
- }
-
- if (start == end || *start++ != '=') {
- /* the invalid header value */
- goto skip;
- }
-
- while (start < end && *start == ' ') { start++; }
-
- for (last = start; last < end && *last != ';'; last++) {
- /* void */
- }
-
- value->len = last - start;
- value->data = start;
-
- return i;
-
- skip:
-
- while (start < end) {
- ch = *start++;
- if (ch == ';' || ch == ',') {
- break;
- }
- }
-
- while (start < end && *start == ' ') { start++; }
- }
- }
-
- return NGX_DECLINED;
-}
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 514658ca2..103db1788 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -410,6 +410,8 @@ void ngx_http_init_request(ngx_event_t *rev)
r->start_time = ngx_time();
+ r->method = NGX_HTTP_UNKNOWN;
+
r->headers_in.content_length_n = -1;
r->headers_in.keep_alive_n = -1;
r->headers_out.content_length_n = -1;
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
index 7e1a43b5d..2e4ec22b9 100644
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -19,9 +19,10 @@
#define NGX_HTTP_VERSION_10 1000
#define NGX_HTTP_VERSION_11 1001
-#define NGX_HTTP_GET 1
-#define NGX_HTTP_HEAD 2
-#define NGX_HTTP_POST 3
+#define NGX_HTTP_UNKNOWN 1
+#define NGX_HTTP_GET 2
+#define NGX_HTTP_HEAD 4
+#define NGX_HTTP_POST 8
#define NGX_HTTP_CONNECTION_CLOSE 1
#define NGX_HTTP_CONNECTION_KEEP_ALIVE 2
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index dc7b89538..ab6f3a0e4 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -588,8 +588,15 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
e->ncaptures = 0;
if (code->test) {
- e->sp->len = 0;
- e->sp->data = (u_char *) "";
+ if (code->negative_test) {
+ e->sp->len = 1;
+ e->sp->data = (u_char *) "1";
+
+ } else {
+ e->sp->len = 0;
+ e->sp->data = (u_char *) "";
+ }
+
e->sp++;
e->ip += sizeof(ngx_http_script_regex_code_t);
@@ -618,8 +625,15 @@ ngx_http_script_regex_start_code(ngx_http_script_engine_t *e)
e->ncaptures = code->ncaptures;
if (code->test) {
- e->sp->len = 1;
- e->sp->data = (u_char *) "1";
+ if (code->negative_test) {
+ e->sp->len = 0;
+ e->sp->data = (u_char *) "";
+
+ } else {
+ e->sp->len = 1;
+ e->sp->data = (u_char *) "1";
+ }
+
e->sp++;
e->ip += sizeof(ngx_http_script_regex_code_t);
@@ -911,6 +925,69 @@ ngx_http_script_not_equal_code(ngx_http_script_engine_t *e)
void
+ngx_http_script_file_code(ngx_http_script_engine_t *e)
+{
+ ngx_err_t err;
+ ngx_file_info_t fi;
+ ngx_http_variable_value_t *value;
+ ngx_http_script_file_code_t *code;
+
+ value = e->sp - 1;
+
+ code = (ngx_http_script_file_code_t *) e->ip;
+ e->ip += sizeof(ngx_http_script_file_code_t);
+
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script file op %p", code->op);
+
+ if (ngx_file_info(value->data, &fi) == -1) {
+ err = ngx_errno;
+
+ if (err != NGX_ENOENT && err != NGX_ENOTDIR) {
+ ngx_log_error(NGX_LOG_CRIT, e->request->connection->log, err,
+ ngx_file_info_n " \"%s\" failed", value->data);
+ }
+
+ switch (code->op) {
+ case ngx_http_script_file_plain:
+ goto false;
+ case ngx_http_script_file_not_plain:
+ goto true;
+ }
+
+ goto false;
+ }
+
+ switch (code->op) {
+ case ngx_http_script_file_plain:
+ if (ngx_is_file(&fi)) {
+ goto true;
+ }
+ goto false;
+
+ case ngx_http_script_file_not_plain:
+ if (ngx_is_file(&fi)) {
+ goto false;
+ }
+ goto true;
+ }
+
+false:
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script file op false");
+
+ *value = ngx_http_variable_null_value;
+ return;
+
+true:
+
+ *value = ngx_http_variable_true_value;
+ return;
+}
+
+
+void
ngx_http_script_complex_value_code(ngx_http_script_engine_t *e)
{
size_t len;
diff --git a/src/http/ngx_http_script.h b/src/http/ngx_http_script.h
index 5c53aec59..abbbf43f4 100644
--- a/src/http/ngx_http_script.h
+++ b/src/http/ngx_http_script.h
@@ -52,7 +52,6 @@ typedef struct {
void *main;
unsigned compile_args:1;
- unsigned compile_null:1;
unsigned complete_lengths:1;
unsigned complete_values:1;
@@ -94,6 +93,7 @@ typedef struct {
uintptr_t next;
uintptr_t test:1;
+ uintptr_t negative_test:1;
uintptr_t uri:1;
uintptr_t args:1;
@@ -129,6 +129,18 @@ typedef struct {
} ngx_http_script_return_code_t;
+typedef enum {
+ ngx_http_script_file_plain = 0,
+ ngx_http_script_file_not_plain
+} ngx_http_script_file_op_e;
+
+
+typedef struct {
+ ngx_http_script_code_pt code;
+ uintptr_t op;
+} ngx_http_script_file_code_t;
+
+
typedef struct {
ngx_http_script_code_pt code;
uintptr_t next;
@@ -177,6 +189,7 @@ void ngx_http_script_break_code(ngx_http_script_engine_t *e);
void ngx_http_script_if_code(ngx_http_script_engine_t *e);
void ngx_http_script_equal_code(ngx_http_script_engine_t *e);
void ngx_http_script_not_equal_code(ngx_http_script_engine_t *e);
+void ngx_http_script_file_code(ngx_http_script_engine_t *e);
void ngx_http_script_complex_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_value_code(ngx_http_script_engine_t *e);
void ngx_http_script_set_var_code(ngx_http_script_engine_t *e);