#! /bin/sh /usr/share/dpatch/dpatch-run ## ngx_http_ssi_variable.dpatch by Kirill A. Kroinskiy ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Implement ngx_http_ssi_get_variable, ngx_http_ssi_set_variable and ## DP: $ssi_ variables @DPATCH@ diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c index 61c9592..695f901 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -73,8 +73,6 @@ 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, ngx_uint_t key); 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); @@ -82,7 +80,7 @@ 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_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc); -static ngx_int_t ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, +static ngx_int_t ngx_http_ssi_set_included_variable(ngx_http_request_t *r, void *data, ngx_int_t rc); static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); @@ -1520,22 +1518,27 @@ 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, - ngx_uint_t key) +ngx_str_t * +ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t *key) { ngx_uint_t i; ngx_list_part_t *part; ngx_http_ssi_var_t *var; - ngx_http_ssi_ctx_t *ctx; + ngx_http_ssi_ctx_t *mctx; - ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); + mctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); + + if (mctx == NULL) { + return NULL; + } - if (ctx->variables == NULL) { + if (mctx->variables == NULL) { return NULL; } - part = &ctx->variables->part; + *key = ngx_hash_strlow(name->data, name->data, name->len); + + part = &mctx->variables->part; var = part->elts; for (i = 0; /* void */ ; i++) { @@ -1554,7 +1557,7 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, continue; } - if (key != var[i].key) { + if (*key != var[i].key) { continue; } @@ -1566,6 +1569,50 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, return NULL; } +ngx_str_t * +ngx_http_ssi_set_variable(ngx_http_request_t *r, ngx_str_t *name, + ngx_uint_t *key, ngx_str_t *value) +{ + ngx_str_t *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 == NULL) { + return NULL; + } + + if (mctx->variables == NULL) { + mctx->variables = ngx_list_create(r->main->pool, 4, + sizeof(ngx_http_ssi_var_t)); + if (mctx->variables == NULL) { + return NULL; + } + } + + vv = ngx_http_ssi_get_variable(r, name, key); + if (vv) { + *vv = *value; + return vv; + } + + if (*key == 0) { + *key = ngx_hash_strlow(name->data, name->data, name->len); + } + + var = ngx_list_push(mctx->variables); + if (var == NULL) { + return NULL; + } + + var->name = *name; + var->key = *key; + var->value = *value; + + return &var->value; +} + static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, @@ -1574,8 +1621,7 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, u_char ch, *p, **value, *data, *part_data; size_t *size, len, prefix, part_len; ngx_str_t var, *val; - ngx_int_t key; - ngx_uint_t i, n, bracket, quoted; + ngx_uint_t i, n, bracket, quoted, key; ngx_array_t lengths, values; ngx_http_variable_value_t *vv; @@ -1701,11 +1747,10 @@ ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, goto invalid_variable; } - key = ngx_hash_strlow(var.data, var.data, var.len); - - val = ngx_http_ssi_get_variable(r, &var, key); + val = ngx_http_ssi_get_variable(r, &var, &key); if (val == NULL) { + vv = ngx_http_get_variable(r, &var, key, flags & NGX_HTTP_SSI_EXPR_TEST); if (vv == NULL) { @@ -1826,13 +1871,12 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, { u_char *dst, *src; size_t len; - ngx_int_t rc, key; + ngx_int_t rc; ngx_str_t *uri, *file, *wait, *set, *stub, args; ngx_buf_t *b; - ngx_uint_t flags, i; + ngx_uint_t flags, i, key; ngx_chain_t *cl, *tl, **ll, *out; ngx_http_request_t *sr; - ngx_http_ssi_var_t *var; ngx_http_ssi_ctx_t *mctx; ngx_http_ssi_block_t *bl; ngx_http_post_subrequest_t *psr; @@ -1994,35 +2038,17 @@ ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, } if (set) { - key = ngx_hash_strlow(set->data, set->data, set->len); - psr = ngx_palloc(r->pool, sizeof(ngx_http_post_subrequest_t)); if (psr == NULL) { return NGX_ERROR; } - psr->handler = ngx_http_ssi_set_variable; - psr->data = ngx_http_ssi_get_variable(r, set, key); + psr->handler = ngx_http_ssi_set_included_variable; + psr->data = ngx_http_ssi_get_variable(r, set, &key); if (psr->data == NULL) { - - if (mctx->variables == NULL) { - mctx->variables = ngx_list_create(r->pool, 4, - sizeof(ngx_http_ssi_var_t)); - if (mctx->variables == NULL) { - return NGX_ERROR; - } - } - - var = ngx_list_push(mctx->variables); - if (var == NULL) { - return NGX_ERROR; - } - - var->name = *set; - var->key = key; - var->value = ngx_http_ssi_null_string; - psr->data = &var->value; + psr->data = ngx_http_ssi_set_variable(r, set, &key, + &ngx_http_ssi_null_string); } flags |= NGX_HTTP_SUBREQUEST_IN_MEMORY|NGX_HTTP_SUBREQUEST_WAITED; @@ -2079,7 +2105,7 @@ ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, ngx_int_t rc) static ngx_int_t -ngx_http_ssi_set_variable(ngx_http_request_t *r, void *data, ngx_int_t rc) +ngx_http_ssi_set_included_variable(ngx_http_request_t *r, void *data, ngx_int_t rc) { ngx_str_t *value = data; @@ -2098,9 +2124,9 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, { u_char *p; uintptr_t len; - ngx_int_t key; ngx_buf_t *b; ngx_str_t *var, *value, *enc, text; + ngx_uint_t key = 0; ngx_chain_t *cl; ngx_http_variable_value_t *vv; @@ -2109,9 +2135,7 @@ ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "ssi echo \"%V\"", var); - key = ngx_hash_strlow(var->data, var->data, var->len); - - value = ngx_http_ssi_get_variable(r, var, key); + value = ngx_http_ssi_get_variable(r, var, &key); if (value == NULL) { vv = ngx_http_get_variable(r, var, key, 1); @@ -2261,20 +2285,9 @@ static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { - ngx_int_t key, rc; - 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 == NULL) { - mctx->variables = ngx_list_create(r->pool, 4, - sizeof(ngx_http_ssi_var_t)); - if (mctx->variables == NULL) { - return NGX_ERROR; - } - } + ngx_int_t rc; + ngx_str_t *name, *value; + ngx_uint_t key; name = params[NGX_HTTP_SSI_SET_VAR]; value = params[NGX_HTTP_SSI_SET_VALUE]; @@ -2288,24 +2301,10 @@ ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, return rc; } - key = ngx_hash_strlow(name->data, name->data, name->len); - - vv = ngx_http_ssi_get_variable(r, name, key); - - if (vv) { - *vv = *value; - return NGX_OK; - } - - var = ngx_list_push(mctx->variables); - if (var == NULL) { + if (ngx_http_ssi_set_variable(r, name, &key, value) == NULL) { return NGX_ERROR; } - var->name = *name; - var->key = key; - var->value = *value; - ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "set: \"%V\"=\"%V\"", name, value); diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h index 6ab1884..0b84f0b 100644 --- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -103,5 +103,9 @@ typedef struct { extern ngx_module_t ngx_http_ssi_filter_module; +ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, + ngx_uint_t *key); +ngx_str_t *ngx_http_ssi_set_variable(ngx_http_request_t *r, ngx_str_t *name, + ngx_uint_t *key, ngx_str_t *value); #endif /* _NGX_HTTP_SSI_FILTER_H_INCLUDED_ */ diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c index 998c4ce..2ca7791 100644 --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -27,6 +27,8 @@ static ngx_int_t ngx_http_variable_unknown_header_out(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_ssi(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); @@ -499,6 +501,17 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } +#if (NGX_HTTP_SSI) + if (ngx_strncmp(name->data, "ssi_", 7) == 0) { + + if (ngx_http_variable_ssi(r, vv, (uintptr_t) name) == NGX_OK) { + return vv; + } + + return NULL; + } +#endif + if (ngx_strncmp(name->data, "arg_", 4) == 0) { if (ngx_http_variable_argument(r, vv, (uintptr_t) name) == NGX_OK) { @@ -508,6 +521,8 @@ ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key, return NULL; } + + vv->not_found = 1; if (nowarn == 0) { @@ -767,6 +782,35 @@ ngx_http_variable_cookie(ngx_http_request_t *r, ngx_http_variable_value_t *v, static ngx_int_t +ngx_http_variable_ssi(ngx_http_request_t *r, ngx_http_variable_value_t *v, + uintptr_t data) +{ + ngx_str_t *name = (ngx_str_t *) data; + ngx_str_t *vv; + ngx_str_t s; + ngx_uint_t key; + + s.len = name->len - (sizeof("ssi_") - 1); + s.data = name->data + sizeof("ssi_") - 1; + + vv = ngx_http_ssi_get_variable(r, &s, &key); + + if (vv == NULL) { + v->not_found = 1; + return NGX_OK; + } + + v->len = vv->len; + v->valid = 1; + v->no_cacheable = 1; + v->not_found = 0; + v->data = vv->data; + + return NGX_OK; +} + + +static ngx_int_t ngx_http_variable_argument(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data) { @@ -1590,6 +1634,15 @@ ngx_http_variables_init_vars(ngx_conf_t *cf) continue; } +#if (NGX_HTTP_SSI) + if (ngx_strncmp(v[i].name.data, "ssi_", 7) == 0) { + v[i].get_handler = ngx_http_variable_ssi; + v[i].data = (uintptr_t) &v[i].name; + + continue; + } +#endif + if (ngx_strncmp(v[i].name.data, "arg_", 4) == 0) { v[i].get_handler = ngx_http_variable_argument; v[i].data = (uintptr_t) &v[i].name;