summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES14
-rw-r--r--CHANGES.ru15
-rw-r--r--src/core/nginx.h2
-rw-r--r--src/http/modules/ngx_http_autoindex_module.c2
-rw-r--r--src/http/modules/ngx_http_chunked_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_geo_module.c40
-rw-r--r--src/http/modules/ngx_http_gzip_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_headers_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_not_modified_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_range_filter_module.c2
-rw-r--r--src/http/modules/ngx_http_ssi_filter_module.c633
-rw-r--r--src/http/modules/ngx_http_static_module.c2
-rw-r--r--src/http/modules/ngx_http_userid_filter_module.c2
-rw-r--r--src/http/ngx_http_core_module.c4
-rw-r--r--src/http/ngx_http_header_filter_module.c2
-rw-r--r--src/http/ngx_http_postpone_filter_module.c7
-rw-r--r--src/http/ngx_http_request.c13
-rw-r--r--src/http/ngx_http_script.c36
-rw-r--r--src/http/ngx_http_special_response.c2
-rw-r--r--src/http/ngx_http_upstream.c6
-rw-r--r--src/http/ngx_http_variables.c2
21 files changed, 493 insertions, 299 deletions
diff --git a/CHANGES b/CHANGES
index 184c5718c..90d5ef030 100644
--- a/CHANGES
+++ b/CHANGES
@@ -1,4 +1,18 @@
+Changes with nginx 0.2.5 04 Oct 2005
+
+ *) Change: the duplicate value of the ngx_http_geo_module variable now
+ causes the warning and changes old value.
+
+ *) Feature: the ngx_http_ssi_module supports the "set" command.
+
+ *) Feature: the ngx_http_ssi_module supports the "file" parameter in
+ the "include" command.
+
+ *) Feature: the ngx_http_ssi_module supports the variable value
+ substitutions in epxiressions of the "if" command.
+
+
Changes with nginx 0.2.4 03 Oct 2005
*) Feature: the ngx_http_ssi_module supports "$var=text", "$var!=text",
diff --git a/CHANGES.ru b/CHANGES.ru
index 7b3faa438..73fe83835 100644
--- a/CHANGES.ru
+++ b/CHANGES.ru
@@ -1,4 +1,19 @@
+Изменения в nginx 0.2.5 04.10.2005
+
+ *) Изменение: дублирующее значение переменной модуля
+ ngx_http_geo_module теперь выдаёт предупреждение и изменяёт старое
+ значение.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает команду set.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает параметр file в
+ команде include.
+
+ *) Добавление: модуль ngx_http_ssi_module поддерживает подстановку
+ значений переменных в выражениях команды if.
+
+
Изменения в nginx 0.2.4 03.10.2005
*) Добавление: модуль ngx_http_ssi_module поддерживает выражения
diff --git a/src/core/nginx.h b/src/core/nginx.h
index 567a18802..b36e94417 100644
--- a/src/core/nginx.h
+++ b/src/core/nginx.h
@@ -8,7 +8,7 @@
#define _NGINX_H_INCLUDED_
-#define NGINX_VER "nginx/0.2.4"
+#define NGINX_VER "nginx/0.2.5"
#define NGINX_VAR "NGINX"
#define NGX_OLDPID_EXT ".oldbin"
diff --git a/src/http/modules/ngx_http_autoindex_module.c b/src/http/modules/ngx_http_autoindex_module.c
index d5a6b69ba..f56896489 100644
--- a/src/http/modules/ngx_http_autoindex_module.c
+++ b/src/http/modules/ngx_http_autoindex_module.c
@@ -514,7 +514,7 @@ ngx_http_autoindex_handler(ngx_http_request_t *r)
b->last = ngx_cpymem(b->last, tail, sizeof(tail) - 1);
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/modules/ngx_http_chunked_filter_module.c b/src/http/modules/ngx_http_chunked_filter_module.c
index bfa362408..85ca93486 100644
--- a/src/http/modules/ngx_http_chunked_filter_module.c
+++ b/src/http/modules/ngx_http_chunked_filter_module.c
@@ -50,7 +50,7 @@ static ngx_http_output_body_filter_pt ngx_http_next_body_filter;
static ngx_int_t
ngx_http_chunked_header_filter(ngx_http_request_t *r)
{
- if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->main) {
+ if (r->headers_out.status == NGX_HTTP_NOT_MODIFIED || r->main != r) {
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
index 2031a4c0b..eedc1f7b2 100644
--- a/src/http/modules/ngx_http_geo_module.c
+++ b/src/http/modules/ngx_http_geo_module.c
@@ -182,11 +182,11 @@ static char *
ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
{
ngx_int_t rc, n;
- ngx_uint_t i;
ngx_str_t *value, file;
+ ngx_uint_t i;
ngx_inet_cidr_t cidrin;
ngx_http_geo_conf_t *geo;
- ngx_http_variable_value_t *var, **v;
+ ngx_http_variable_value_t *var, *old, **v;
geo = cf->ctx;
@@ -274,17 +274,33 @@ ngx_http_geo(ngx_conf_t *cf, ngx_command_t *dummy, void *conf)
*v = var;
}
- rc = ngx_radix32tree_insert(geo->tree, cidrin.addr, cidrin.mask,
- (uintptr_t) var);
- if (rc == NGX_ERROR) {
- return NGX_CONF_ERROR;
- }
+ for (i = 2; i; i--) {
+ rc = ngx_radix32tree_insert(geo->tree, cidrin.addr, cidrin.mask,
+ (uintptr_t) var);
+ if (rc == NGX_OK) {
+ return NGX_CONF_OK;
+ }
- if (rc == NGX_BUSY) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "duplicate parameter \"%V\"",
- &value[0]);
- return NGX_CONF_ERROR;
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
+
+ /* rc == NGX_BUSY */
+
+ old = (ngx_http_variable_value_t *)
+ ngx_radix32tree_find(geo->tree, cidrin.addr & cidrin.mask);
+
+ ngx_conf_log_error(NGX_LOG_WARN, cf, 0,
+ "duplicate parameter \"%V\", value: \"%V\", "
+ "old value: \"%V\"",
+ &value[0], &var->text, &old->text);
+
+ rc = ngx_radix32tree_delete(geo->tree, cidrin.addr, cidrin.mask);
+
+ if (rc == NGX_ERROR) {
+ return NGX_CONF_ERROR;
+ }
}
- return NGX_CONF_OK;
+ return NGX_CONF_ERROR;
}
diff --git a/src/http/modules/ngx_http_gzip_filter_module.c b/src/http/modules/ngx_http_gzip_filter_module.c
index 012ea4581..923dd1724 100644
--- a/src/http/modules/ngx_http_gzip_filter_module.c
+++ b/src/http/modules/ngx_http_gzip_filter_module.c
@@ -280,7 +280,7 @@ ngx_http_gzip_header_filter(ngx_http_request_t *r)
&& r->headers_out.status != NGX_HTTP_FORBIDDEN
&& r->headers_out.status != NGX_HTTP_NOT_FOUND)
|| r->header_only
- || r->main
+ || r->main != r
|| r->http_version < conf->http_version
|| r->headers_out.content_type.len == 0
|| (r->headers_out.content_encoding
diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
index 43cb5c8cd..0855990a5 100644
--- a/src/http/modules/ngx_http_headers_filter_module.c
+++ b/src/http/modules/ngx_http_headers_filter_module.c
@@ -84,7 +84,7 @@ ngx_http_headers_filter(ngx_http_request_t *r)
if ((r->headers_out.status != NGX_HTTP_OK
&& r->headers_out.status != NGX_HTTP_NOT_MODIFIED)
- || r->main)
+ || r->main != r)
{
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/modules/ngx_http_not_modified_filter_module.c b/src/http/modules/ngx_http_not_modified_filter_module.c
index 6712a917d..1e2db62cd 100644
--- a/src/http/modules/ngx_http_not_modified_filter_module.c
+++ b/src/http/modules/ngx_http_not_modified_filter_module.c
@@ -52,7 +52,7 @@ static ngx_int_t ngx_http_not_modified_header_filter(ngx_http_request_t *r)
time_t ims;
if (r->headers_out.status != NGX_HTTP_OK
- || r->main
+ || r->main != r
|| r->headers_in.if_modified_since == NULL
|| r->headers_out.last_modified_time == -1)
{
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
index c62649595..c8b30b850 100644
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -134,7 +134,7 @@ ngx_http_range_header_filter(ngx_http_request_t *r)
if (r->http_version < NGX_HTTP_VERSION_10
|| r->headers_out.status != NGX_HTTP_OK
- || r->main
+ || r->main != r
|| r->headers_out.content_length_n == -1
|| !r->filter_allow_ranges)
{
diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c
index 885d29817..acbae29eb 100644
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -8,15 +8,18 @@
#include <ngx_core.h>
#include <ngx_http.h>
-#define NGX_HTTP_SSI_MAX_PARAMS 16
+#define NGX_HTTP_SSI_MAX_PARAMS 16
-#define NGX_HTTP_SSI_COMMAND_LEN 31
-#define NGX_HTTP_SSI_PARAM_LEN 31
-#define NGX_HTTP_SSI_PARAMS_N 4
+#define NGX_HTTP_SSI_COMMAND_LEN 31
+#define NGX_HTTP_SSI_PARAM_LEN 31
+#define NGX_HTTP_SSI_PARAMS_N 4
-#define NGX_HTTP_SSI_ERROR 1
+#define NGX_HTTP_SSI_ERROR 1
-#define NGX_HTTP_SSI_DATE_LEN 2048
+#define NGX_HTTP_SSI_DATE_LEN 2048
+
+
+#define NGX_HTTP_SSI_ADD_PREFIX 1
typedef struct {
@@ -32,6 +35,12 @@ typedef struct {
typedef struct {
+ ngx_str_t name;
+ ngx_str_t value;
+} ngx_http_ssi_var_t;
+
+
+typedef struct {
ngx_buf_t *buf;
u_char *pos;
@@ -56,6 +65,8 @@ typedef struct {
size_t value_len;
+ ngx_array_t variables;
+
ngx_uint_t output; /* unsigned output:1; */
ngx_str_t timefmt;
@@ -113,12 +124,18 @@ static ngx_int_t ngx_http_ssi_output(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx);
static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx);
+static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r,
+ ngx_str_t *name);
+static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
+static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
+ ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
static ngx_int_t ngx_http_ssi_config(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
-static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
+static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
static ngx_int_t ngx_http_ssi_if(ngx_http_request_t *r,
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
@@ -221,6 +238,8 @@ static u_char ngx_http_ssi_string[] = "<!--";
static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
+#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
+#define NGX_HTTP_SSI_INCLUDE_FILE 1
#define NGX_HTTP_SSI_ECHO_VAR 0
#define NGX_HTTP_SSI_ECHO_DEFAULT 1
@@ -228,23 +247,22 @@ static ngx_str_t ngx_http_ssi_none = ngx_string("(none)");
#define NGX_HTTP_SSI_CONFIG_ERRMSG 0
#define NGX_HTTP_SSI_CONFIG_TIMEFMT 1
-#define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
-#define NGX_HTTP_SSI_INCLUDE_FILE 1
+#define NGX_HTTP_SSI_SET_VAR 0
+#define NGX_HTTP_SSI_SET_VALUE 1
#define NGX_HTTP_SSI_IF_EXPR 0
-static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
- { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1 },
- { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0 },
- { ngx_null_string, 0, 0 }
-};
-
static ngx_http_ssi_param_t ngx_http_ssi_include_params[] = {
{ ngx_string("virtual"), NGX_HTTP_SSI_INCLUDE_VIRTUAL, 0 },
-#if 0
{ ngx_string("file"), NGX_HTTP_SSI_INCLUDE_FILE, 0 },
-#endif
+ { ngx_null_string, 0, 0 }
+};
+
+
+static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = {
+ { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1 },
+ { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0 },
{ ngx_null_string, 0, 0 }
};
@@ -256,8 +274,15 @@ static ngx_http_ssi_param_t ngx_http_ssi_config_params[] = {
};
+static ngx_http_ssi_param_t ngx_http_ssi_set_params[] = {
+ { ngx_string("var"), NGX_HTTP_SSI_SET_VAR, 1 },
+ { ngx_string("value"), NGX_HTTP_SSI_SET_VALUE, 1 },
+ { ngx_null_string, 0, 0 }
+};
+
+
static ngx_http_ssi_param_t ngx_http_ssi_if_params[] = {
- { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 0 },
+ { ngx_string("expr"), NGX_HTTP_SSI_IF_EXPR, 1 },
{ ngx_null_string, 0, 0 }
};
@@ -268,11 +293,12 @@ static ngx_http_ssi_param_t ngx_http_ssi_no_params[] = {
static ngx_http_ssi_command_t ngx_http_ssi_commands[] = {
+ { ngx_string("include"), ngx_http_ssi_include,
+ ngx_http_ssi_include_params, 0, 1 },
{ ngx_string("echo"), ngx_http_ssi_echo, ngx_http_ssi_echo_params, 0, 0 },
{ ngx_string("config"), ngx_http_ssi_config,
ngx_http_ssi_config_params, 0, 0 },
- { ngx_string("include"), ngx_http_ssi_include,
- ngx_http_ssi_include_params, 0, 1 },
+ { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
{ ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
{ ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
@@ -355,7 +381,7 @@ found:
r->filter_need_in_memory = 1;
- if (r->main == NULL) {
+ if (r->main == r) {
r->headers_out.content_length_n = -1;
if (r->headers_out.content_length) {
r->headers_out.content_length->hash = 0;
@@ -1301,223 +1327,197 @@ ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx)
}
-static ngx_int_t
-ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
+static ngx_str_t *
+ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name)
{
- ngx_uint_t i;
- ngx_buf_t *b;
- ngx_str_t *var, *value;
- ngx_chain_t *cl;
- ngx_http_variable_value_t *vv;
-
- var = params[NGX_HTTP_SSI_ECHO_VAR];
+ ngx_uint_t i;
+ ngx_http_ssi_var_t *var;
+ ngx_http_ssi_ctx_t *ctx;
- for (i = 0; i < var->len; i++) {
- var->data[i] = ngx_tolower(var->data[i]);
- }
-
- vv = ngx_http_get_variable(r, var);
-
- if (vv == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
+ ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
- if (vv == NGX_HTTP_VAR_NOT_FOUND) {
- value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
-
- if (value == NULL) {
- value = &ngx_http_ssi_none;
-
- } else if (value->len == 0) {
- return NGX_OK;
+ var = ctx->variables.elts;
+ for (i = 0; i < ctx->variables.nelts; i++) {
+ if (name->len != var[i].name.len) {
+ continue;
}
- } else {
- value = &vv->text;
-
- if (value->len == 0) {
- return NGX_OK;
+ if (ngx_strncasecmp(name->data, var[i].name.data, name->len) == 0) {
+ return &var[i].value;
}
}
- b = ngx_calloc_buf(r->pool);
- if (b == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- cl = ngx_alloc_chain_link(r->pool);
- if (cl == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
-
- b->memory = 1;
- b->pos = value->data;
- b->last = value->data + value->len;
-
- cl->buf = b;
- cl->next = NULL;
- *ctx->last_out = cl;
- ctx->last_out = &cl->next;
-
- return NGX_OK;
+ return NULL;
}
static ngx_int_t
-ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
-{
- ngx_str_t *value;
-
- value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT];
-
- if (value) {
- ctx->timefmt = *value;
- }
-
- value = params[NGX_HTTP_SSI_CONFIG_ERRMSG];
-
- if (value) {
- ctx->errmsg = *value;
- }
-
- return NGX_OK;
-}
-
-
-static ngx_int_t
-ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
- ngx_str_t **params)
+ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t *text, ngx_uint_t flags)
{
u_char ch, *p, **value, *data;
size_t *size, len, prefix;
+ ngx_str_t var, part, *val;
ngx_uint_t i, j, n, bracket;
- ngx_str_t uri, args, name;
ngx_array_t lengths, values;
ngx_http_variable_value_t *vv;
- /* TODO: file, virtual vs file */
+ n = ngx_http_script_variables_count(text);
- uri = *params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
- args.len = 0;
- args.data = NULL;
- prefix = 0;
+ if (n == 0) {
- n = ngx_http_script_variables_count(&uri);
+ if (!(flags & NGX_HTTP_SSI_ADD_PREFIX)) {
+ return NGX_OK;
+ }
- if (n > 0) {
+ if (text->data[0] != '/') {
+ for (prefix = r->uri.len; prefix; prefix--) {
+ if (r->uri.data[prefix - 1] == '/') {
+ break;
+ }
+ }
- if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
- }
+ if (prefix) {
+ len = prefix + text->len;
- if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
- return NGX_HTTP_SSI_ERROR;
+ data = ngx_palloc(r->pool, len);
+ if (data == NULL) {
+ return NGX_ERROR;
+ }
+
+ p = ngx_cpymem(data, r->uri.data, prefix);
+ ngx_memcpy(p, text->data, text->len);
+
+ text->len = len;
+ text->data = data;
+ }
}
- len = 0;
+ return NGX_OK;
+ }
- for (i = 0; i < uri.len; /* void */ ) {
+ if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
+ return NGX_ERROR;
+ }
- name.len = 0;
+ if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
+ return NGX_ERROR;
+ }
- if (uri.data[i] == '$') {
+ len = 0;
+ i = 0;
- if (++i == uri.len) {
- goto invalid_variable;
- }
+ while (i < text->len) {
- if (uri.data[i] == '{') {
- bracket = 1;
+ if (text->data[i] == '$') {
- if (++i == uri.len) {
- goto invalid_variable;
- }
+ var.len = 0;
- name.data = &uri.data[i];
+ if (++i == text->len) {
+ goto invalid_variable;
+ }
- } else {
- bracket = 0;
- name.data = &uri.data[i];
+ if (text->data[i] == '{') {
+ bracket = 1;
+
+ if (++i == text->len) {
+ goto invalid_variable;
}
- for ( /* void */ ; i < uri.len; i++, name.len++) {
- ch = uri.data[i];
+ var.data = &text->data[i];
- if (ch == '}' && bracket) {
- i++;
- bracket = 0;
- break;
- }
+ } else {
+ bracket = 0;
+ var.data = &text->data[i];
+ }
- if ((ch >= 'A' && ch <= 'Z')
- || (ch >= 'a' && ch <= 'z')
- || (ch >= '0' && ch <= '9')
- || ch == '_')
- {
- continue;
- }
+ for ( /* void */ ; i < text->len; i++, var.len++) {
+ ch = text->data[i];
+ if (ch == '}' && bracket) {
+ i++;
+ bracket = 0;
break;
}
- if (bracket) {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "the closing bracket in \"%V\" "
- "variable is missing", &name);
- return NGX_HTTP_SSI_ERROR;
+ if ((ch >= 'A' && ch <= 'Z')
+ || (ch >= 'a' && ch <= 'z')
+ || (ch >= '0' && ch <= '9')
+ || ch == '_')
+ {
+ continue;
}
- if (name.len == 0) {
- goto invalid_variable;
- }
+ break;
+ }
- for (j = 0; j < name.len; j++) {
- name.data[j] = ngx_tolower(name.data[j]);
- }
+ if (bracket) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "the closing bracket in \"%V\" "
+ "variable is missing", &var);
+ return NGX_ERROR;
+ }
- vv = ngx_http_get_variable(r, &name);
+ if (var.len == 0) {
+ goto invalid_variable;
+ }
+
+ for (j = 0; j < var.len; j++) {
+ var.data[j] = ngx_tolower(var.data[j]);
+ }
+
+ val = ngx_http_ssi_get_variable(r, &var);
+
+ if (val == NULL) {
+ vv = ngx_http_get_variable(r, &var);
if (vv == NULL) {
- return NGX_HTTP_SSI_ERROR;
+ return NGX_ERROR;
}
if (vv == NGX_HTTP_VAR_NOT_FOUND) {
continue;
}
- name = vv->text;
+ part = vv->text;
} else {
- name.data = &uri.data[i];
-
- while (i < uri.len && uri.data[i] != '$') {
- i++;
- name.len++;
- }
+ part = *val;
}
- len += name.len;
+ } else {
+ part.len = 0;
+ part.data = &text->data[i];
- size = ngx_array_push(&lengths);
- if (size == NULL) {
- return NGX_HTTP_SSI_ERROR;
+ while (i < text->len && text->data[i] != '$') {
+ i++;
+ part.len++;
}
+ }
- *size = name.len;
+ len += part.len;
- value = ngx_array_push(&values);
- if (value == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
+ size = ngx_array_push(&lengths);
+ if (size == NULL) {
+ return NGX_ERROR;
+ }
- *value = name.data;
+ *size = part.len;
+
+ value = ngx_array_push(&values);
+ if (value == NULL) {
+ return NGX_ERROR;
}
- size = lengths.elts;
- value = values.elts;
+ *value = part.data;
+ }
+
+ prefix = 0;
+
+ size = lengths.elts;
+ value = values.elts;
+ if (flags & NGX_HTTP_SSI_ADD_PREFIX) {
for (i = 0; i < values.nelts; i++) {
if (size[i] != 0) {
if (*value[i] != '/') {
@@ -1532,70 +1532,226 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
break;
}
}
+ }
- p = ngx_palloc(r->pool, len);
- if (p == NULL) {
- return NGX_HTTP_SSI_ERROR;
+ p = ngx_palloc(r->pool, len);
+ if (p == NULL) {
+ return NGX_ERROR;
+ }
+
+ text->len = len;
+ text->data = p;
+
+ if (prefix) {
+ p = ngx_cpymem(p, r->uri.data, prefix);
+ }
+
+ for (i = 0; i < values.nelts; i++) {
+ p = ngx_cpymem(p, value[i], size[i]);
+ }
+
+ return NGX_OK;
+
+invalid_variable:
+
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "invalid variable name in \"%V\"", text);
+
+ return NGX_ERROR;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *uri, *file, args;
+ ngx_uint_t i;
+
+ uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
+ file = params[NGX_HTTP_SSI_INCLUDE_FILE];
+
+ if (uri && file) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "inlcusion may be either virtual=\"%V\" or file=\"%V\"",
+ uri, file);
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (uri == NULL && file == NULL) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "no parameter in \"include\" SSI command");
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ if (uri == NULL) {
+ uri = file;
+ }
+
+ if (ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX)
+ != NGX_OK)
+ {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ args.len = 0;
+ args.data = NULL;
+
+ if (params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]) {
+ for (i = 0; i < uri->len; i++) {
+ if (uri->data[i] == '?') {
+ args.len = uri->len - i - 1;
+ args.data = &uri->data[i + 1];
+ uri->len -= args.len + 1;
+
+ break;
+ }
}
+ }
- uri.len = len;
- uri.data = p;
+ if (ngx_http_subrequest(r, uri, &args) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
+ }
- if (prefix) {
- p = ngx_cpymem(p, r->uri.data, prefix);
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_uint_t i;
+ ngx_buf_t *b;
+ ngx_str_t *var, *value;
+ ngx_chain_t *cl;
+ ngx_http_variable_value_t *vv;
+
+ var = params[NGX_HTTP_SSI_ECHO_VAR];
+
+ value = ngx_http_ssi_get_variable(r, var);
+
+ if (value == NULL) {
+ for (i = 0; i < var->len; i++) {
+ var->data[i] = ngx_tolower(var->data[i]);
}
- for (i = 0; i < values.nelts; i++) {
- p = ngx_cpymem(p, value[i], size[i]);
+ vv = ngx_http_get_variable(r, var);
+
+ if (vv == NULL) {
+ return NGX_HTTP_SSI_ERROR;
}
- } else {
- if (uri.data[0] != '/') {
- for (prefix = r->uri.len; prefix; prefix--) {
- if (r->uri.data[prefix - 1] == '/') {
- break;
- }
- }
+ if (vv != NGX_HTTP_VAR_NOT_FOUND) {
+ value = &vv->text;
+ }
+ }
- if (prefix) {
- len = prefix + uri.len;
+ if (value == NULL) {
+ value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
- data = ngx_palloc(r->pool, len);
- if (data == NULL) {
- return NGX_HTTP_SSI_ERROR;
- }
+ if (value == NULL) {
+ value = &ngx_http_ssi_none;
- p = ngx_cpymem(data, r->uri.data, prefix);
- ngx_memcpy(p, uri.data, uri.len);
+ } else if (value->len == 0) {
+ return NGX_OK;
+ }
- uri.len = len;
- uri.data = data;
- }
+ } else {
+ if (value->len == 0) {
+ return NGX_OK;
}
}
- for (i = 0; i < uri.len; i++) {
- if (uri.data[i] == '?') {
- args.len = uri.len - i - 1;
- args.data = &uri.data[i + 1];
- uri.len -= args.len + 1;
+ b = ngx_calloc_buf(r->pool);
+ if (b == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
- break;
+ cl = ngx_alloc_chain_link(r->pool);
+ if (cl == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
+
+ b->memory = 1;
+ b->pos = value->data;
+ b->last = value->data + value->len;
+
+ cl->buf = b;
+ cl->next = NULL;
+ *ctx->last_out = cl;
+ ctx->last_out = &cl->next;
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_config(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *value;
+
+ value = params[NGX_HTTP_SSI_CONFIG_TIMEFMT];
+
+ if (value) {
+ ctx->timefmt = *value;
+ }
+
+ value = params[NGX_HTTP_SSI_CONFIG_ERRMSG];
+
+ if (value) {
+ ctx->errmsg = *value;
+ }
+
+ return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
+ ngx_str_t **params)
+{
+ ngx_str_t *name, *value, *vv;
+ ngx_http_ssi_var_t *var;
+ ngx_http_ssi_ctx_t *mctx;
+
+ mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+ if (mctx->variables.elts == NULL) {
+ if (ngx_array_init(&mctx->variables, r->pool, 4,
+ sizeof(ngx_http_ssi_var_t)) != NGX_OK)
+ {
+ return NGX_HTTP_SSI_ERROR;
}
}
- if (ngx_http_subrequest(r, &uri, &args) != NGX_OK) {
+ name = params[NGX_HTTP_SSI_SET_VAR];
+ value = params[NGX_HTTP_SSI_SET_VALUE];
+
+ if (ngx_http_ssi_evaluate_string(r, ctx, value, 0) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
- return NGX_OK;
+ vv = ngx_http_ssi_get_variable(r, name);
-invalid_variable:
+ if (vv) {
+ *vv = *value;
+ return NGX_OK;
+ }
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid variable name in \"%V\"", &uri);
+ var = ngx_array_push(&mctx->variables);
+ if (var == NULL) {
+ return NGX_HTTP_SSI_ERROR;
+ }
- return NGX_ERROR;
+ var->name = *name;
+ var->value = *value;
+
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "set: \"%V\"=\"%V\"", name, value);
+
+ return NGX_OK;
}
@@ -1603,55 +1759,55 @@ static ngx_int_t
ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
ngx_str_t **params)
{
- u_char *p, *last;
- ngx_str_t *expr, var, left, right;
- ngx_int_t rc;
- ngx_uint_t negative, noregex;
- ngx_http_variable_value_t *vv;
+ u_char *p, *last;
+ ngx_str_t *expr, left, right;
+ ngx_int_t rc;
+ ngx_uint_t negative, noregex;
#if (NGX_PCRE)
- ngx_str_t err;
- ngx_regex_t *regex;
- u_char errstr[NGX_MAX_CONF_ERRSTR];
+ ngx_str_t err;
+ ngx_regex_t *regex;
+ u_char errstr[NGX_MAX_CONF_ERRSTR];
#endif
expr = params[NGX_HTTP_SSI_IF_EXPR];
- if (expr->data[0] != '$') {
- ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
- "invalid variable name in \"%V\"", expr);
- return NGX_HTTP_SSI_ERROR;
- }
-
- var.data = expr->data + 1;
+ left.data = expr->data;
last = expr->data + expr->len;
- for (p = var.data; p < last; p++) {
+ for (p = left.data; p < last; p++) {
if (*p >= 'A' && *p <= 'Z') {
*p |= 0x20;
continue;
}
- if ((*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_') {
+ if ((*p >= 'a' && *p <= 'z')
+ || (*p >= '0' && *p <= '9')
+ || *p == '$' || *p == '{' || *p == '}' || *p == '_')
+ {
continue;
}
break;
}
- var.len = p - var.data;
+ left.len = p - left.data;
while (p < last && *p == ' ') {
p++;
}
- vv = ngx_http_get_variable(r, &var);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "left: \"%V\"", &left);
- if (vv == NULL) {
+ if (ngx_http_ssi_evaluate_string(r, ctx, &left, 0) != NGX_OK) {
return NGX_HTTP_SSI_ERROR;
}
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "evaluted left: \"%V\"", &left);
+
if (p == last) {
- if (vv != NGX_HTTP_VAR_NOT_FOUND && vv->text.len != 0) {
+ if (left.len) {
ctx->output = 1;
} else {
@@ -1693,16 +1849,15 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
right.len = last - p;
right.data = p;
- if (vv == NGX_HTTP_VAR_NOT_FOUND) {
- left.len = 0;
- left.data = (u_char *) "";
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "right: \"%V\"", &right);
- } else {
- left = vv->text;
+ if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) {
+ return NGX_HTTP_SSI_ERROR;
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
- "left: \"%V\" right: \"%V\"", &left, &right);
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "evaluted right: \"%V\"", &right);
if (noregex) {
if (left.len != right.len) {
diff --git a/src/http/modules/ngx_http_static_module.c b/src/http/modules/ngx_http_static_module.c
index d8884cac8..afdbf7864 100644
--- a/src/http/modules/ngx_http_static_module.c
+++ b/src/http/modules/ngx_http_static_module.c
@@ -339,7 +339,7 @@ ngx_http_static_handler(ngx_http_request_t *r)
b->in_file = 1;
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/modules/ngx_http_userid_filter_module.c b/src/http/modules/ngx_http_userid_filter_module.c
index 1add894be..221d33bf3 100644
--- a/src/http/modules/ngx_http_userid_filter_module.c
+++ b/src/http/modules/ngx_http_userid_filter_module.c
@@ -206,7 +206,7 @@ ngx_http_userid_filter(ngx_http_request_t *r)
ngx_http_userid_ctx_t *ctx;
ngx_http_userid_conf_t *conf;
- if (r->main) {
+ if (r->main != r) {
return ngx_http_next_header_filter(r);
}
diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
index e9f594217..c07e367a0 100644
--- a/src/http/ngx_http_core_module.c
+++ b/src/http/ngx_http_core_module.c
@@ -498,7 +498,7 @@ ngx_http_core_run_phases(ngx_http_request_t *r)
r->phase = NGX_HTTP_FIND_CONFIG_PHASE;
}
- if (r->phase == NGX_HTTP_ACCESS_PHASE && r->main) {
+ if (r->phase == NGX_HTTP_ACCESS_PHASE && r->main != r) {
continue;
}
@@ -1099,7 +1099,7 @@ ngx_http_subrequest(ngx_http_request_t *r,
return NGX_HTTP_INTERNAL_SERVER_ERROR;
}
- sr->main = r->main ? r->main : r;
+ sr->main = r->main;
sr->parent = r;
sr->read_event_handler = ngx_http_request_empty_handler;
sr->write_event_handler = ngx_http_request_empty_handler;
diff --git a/src/http/ngx_http_header_filter_module.c b/src/http/ngx_http_header_filter_module.c
index 5af1cf386..db4179091 100644
--- a/src/http/ngx_http_header_filter_module.c
+++ b/src/http/ngx_http_header_filter_module.c
@@ -159,7 +159,7 @@ ngx_http_header_filter(ngx_http_request_t *r)
ngx_table_elt_t *header;
ngx_http_core_loc_conf_t *clcf;
- if (r->main) {
+ if (r->main != r) {
return NGX_OK;
}
diff --git a/src/http/ngx_http_postpone_filter_module.c b/src/http/ngx_http_postpone_filter_module.c
index 73e31e698..e75e74ffc 100644
--- a/src/http/ngx_http_postpone_filter_module.c
+++ b/src/http/ngx_http_postpone_filter_module.c
@@ -51,7 +51,6 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
{
ngx_int_t rc;
ngx_chain_t *out;
- ngx_http_request_t *mr;
ngx_http_postponed_request_t *pr, **ppr;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
@@ -110,16 +109,14 @@ ngx_http_postpone_filter(ngx_http_request_t *r, ngx_chain_t *in)
out = in;
}
- mr = r->main ? r->main : r;
-
- if (out == NULL && mr->out == NULL && !mr->connection->buffered) {
+ if (out == NULL && r->main->out == NULL && !r->main->connection->buffered) {
return NGX_OK;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"http postpone filter out \"%V\"", &r->uri);
- rc = ngx_http_next_filter(mr, out);
+ rc = ngx_http_next_filter(r->main, out);
if (rc == NGX_ERROR) {
/* NGX_ERROR may be returned by any filter */
diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
index 0e6613b51..704d373b6 100644
--- a/src/http/ngx_http_request.c
+++ b/src/http/ngx_http_request.c
@@ -423,6 +423,8 @@ void ngx_http_init_request(ngx_event_t *rev)
c->single_connection = 1;
r->connection = c;
+ r->main = r;
+
r->start_time = ngx_time();
r->headers_in.content_length_n = -1;
@@ -1666,8 +1668,7 @@ ngx_http_writer(ngx_http_request_t *r)
wev->delayed = 0;
if (!wev->ready) {
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
ngx_add_timer(wev, clcf->send_timeout);
if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
@@ -1683,8 +1684,7 @@ ngx_http_writer(ngx_http_request_t *r)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, wev->log, 0,
"http writer delayed");
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
if (ngx_handle_write_event(wev, clcf->send_lowat) == NGX_ERROR) {
ngx_http_close_request(r, 0);
@@ -1712,8 +1712,7 @@ ngx_http_writer(ngx_http_request_t *r)
"http writer output filter: %d, \"%V\"", rc, &r->uri);
if (rc == NGX_AGAIN) {
- clcf = ngx_http_get_module_loc_conf(r->main ? r->main : r,
- ngx_http_core_module);
+ clcf = ngx_http_get_module_loc_conf(r->main, ngx_http_core_module);
if (!wev->ready && !wev->delayed) {
ngx_add_timer(wev, clcf->send_timeout);
}
@@ -1809,7 +1808,7 @@ ngx_http_discard_body(ngx_http_request_t *r)
ssize_t size;
ngx_event_t *rev;
- if (r->main) {
+ if (r->main != r) {
return NGX_OK;
}
diff --git a/src/http/ngx_http_script.c b/src/http/ngx_http_script.c
index 27c9ce045..a8272ec67 100644
--- a/src/http/ngx_http_script.c
+++ b/src/http/ngx_http_script.c
@@ -361,11 +361,11 @@ ngx_http_script_copy_var_len_code(ngx_http_script_engine_t *e)
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- return 0;
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ return value->text.len;
}
- return value->text.len;
+ return 0;
}
@@ -382,15 +382,14 @@ ngx_http_script_copy_var_code(ngx_http_script_engine_t *e)
if (!e->skip) {
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- return;
- }
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
- e->pos = ngx_cpymem(e->pos, value->text.data, value->text.len);
-
- if (e->log) {
- ngx_log_debug1(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script var: \"%V\"", &e->buf);
+ if (e->log) {
+ ngx_log_debug1(NGX_LOG_DEBUG_HTTP,
+ e->request->connection->log, 0,
+ "http script var: \"%V\"", &e->buf);
+ }
}
}
}
@@ -879,19 +878,18 @@ ngx_http_script_var_code(ngx_http_script_engine_t *e)
value = ngx_http_get_indexed_variable(e->request, code->index);
- if (value == NULL || value == NGX_HTTP_VAR_NOT_FOUND) {
- e->sp->value = 0;
- e->sp->text.len = 0;
- e->sp->text.data = (u_char *) "";
+ if (value && value != NGX_HTTP_VAR_NOT_FOUND) {
+ ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
+ "http script var: %ui, \"%V\"", value->value, &value->text);
+ *e->sp = *value;
e->sp++;
return;
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, e->request->connection->log, 0,
- "http script var: %ui, \"%V\"", value->value, &value->text);
-
- *e->sp = *value;
+ e->sp->value = 0;
+ e->sp->text.len = 0;
+ e->sp->text.data = (u_char *) "";
e->sp++;
}
diff --git a/src/http/ngx_http_special_response.c b/src/http/ngx_http_special_response.c
index 4cf88101e..be23d6d5b 100644
--- a/src/http/ngx_http_special_response.c
+++ b/src/http/ngx_http_special_response.c
@@ -423,7 +423,7 @@ ngx_http_special_response_handler(ngx_http_request_t *r, ngx_int_t error)
cl->buf = b;
}
- if (r->main == NULL) {
+ if (r->main == r) {
b->last_buf = 1;
}
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 834c30244..647d9d20a 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -495,7 +495,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u)
}
if (r->request_body) {
- if (r->request_body->temp_file && r->main == NULL) {
+ if (r->request_body->temp_file && r->main == r) {
/*
* the r->request_body->buf can be reused for one request only,
@@ -560,7 +560,7 @@ ngx_http_upstream_reinit(ngx_http_request_t *r, ngx_http_upstream_t *u)
/* reinit the subrequest's ngx_output_chain() context */
if (r->request_body) {
- if (r->request_body->temp_file && r->main && u->output.buf) {
+ if (r->request_body->temp_file && r->main != r && u->output.buf) {
u->output.free = ngx_alloc_chain_link(r->pool);
if (u->output.free == NULL) {
@@ -1454,7 +1454,7 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
r->connection->log->action = "sending to client";
- if (rc == 0 && r->main == NULL) {
+ if (rc == 0 && r->main == r) {
rc = ngx_http_send_last(r);
}
diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c
index 0247298b1..214015fe9 100644
--- a/src/http/ngx_http_variables.c
+++ b/src/http/ngx_http_variables.c
@@ -229,7 +229,7 @@ ngx_http_get_indexed_variable(ngx_http_request_t *r, ngx_uint_t index)
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
- if (cmcf->variables.elts == NULL || cmcf->variables.nelts <= index) {
+ if (cmcf->variables.nelts <= index) {
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
"unknown variable index: %d", index);
return NULL;