SSI: added regex captures support in the expression of the "if" command.
This commit is contained in:
parent
5fe3db9986
commit
45bf93e9a3
2 changed files with 148 additions and 29 deletions
|
@ -78,6 +78,8 @@ 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);
|
||||
static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
|
||||
ngx_str_t *pattern, ngx_str_t *str);
|
||||
|
||||
static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
|
||||
ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
|
||||
|
@ -1531,6 +1533,30 @@ ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name,
|
|||
|
||||
ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
|
||||
|
||||
#if (NGX_PCRE)
|
||||
{
|
||||
ngx_str_t *value;
|
||||
|
||||
if (key >= '0' && key <= '9') {
|
||||
i = key - '0';
|
||||
|
||||
if (i < ctx->ncaptures) {
|
||||
value = ngx_palloc(r->pool, sizeof(ngx_str_t));
|
||||
if (value == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
i *= 2;
|
||||
|
||||
value->data = ctx->captures_data + ctx->captures[i];
|
||||
value->len = ctx->captures[i + 1] - ctx->captures[i];
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ctx->variables == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1819,6 +1845,115 @@ invalid_variable:
|
|||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
|
||||
ngx_str_t *str)
|
||||
{
|
||||
#if (NGX_PCRE)
|
||||
int rc, *captures;
|
||||
u_char *p, errstr[NGX_MAX_CONF_ERRSTR];
|
||||
size_t size;
|
||||
ngx_int_t key;
|
||||
ngx_str_t *vv, name, value;
|
||||
ngx_uint_t i, n;
|
||||
ngx_http_ssi_ctx_t *ctx;
|
||||
ngx_http_ssi_var_t *var;
|
||||
ngx_regex_compile_t rgc;
|
||||
|
||||
ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
|
||||
|
||||
rgc.pattern = *pattern;
|
||||
rgc.pool = r->pool;
|
||||
rgc.err.len = NGX_MAX_CONF_ERRSTR;
|
||||
rgc.err.data = errstr;
|
||||
|
||||
if (ngx_regex_compile(&rgc) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
}
|
||||
|
||||
n = (rgc.captures + 1) * 3;
|
||||
|
||||
captures = ngx_palloc(r->pool, n * sizeof(int));
|
||||
if (captures == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
rc = ngx_regex_exec(rgc.regex, str, captures, n);
|
||||
|
||||
if (rc < NGX_REGEX_NO_MATCHED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
|
||||
rc, str, pattern);
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
}
|
||||
|
||||
if (rc == NGX_REGEX_NO_MATCHED) {
|
||||
return NGX_DECLINED;
|
||||
}
|
||||
|
||||
ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
|
||||
|
||||
ctx->ncaptures = rc;
|
||||
ctx->captures = captures;
|
||||
ctx->captures_data = str->data;
|
||||
|
||||
if (rgc.named_captures > 0) {
|
||||
|
||||
if (ctx->variables == NULL) {
|
||||
ctx->variables = ngx_list_create(r->pool, 4,
|
||||
sizeof(ngx_http_ssi_var_t));
|
||||
if (ctx->variables == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
size = rgc.name_size;
|
||||
p = rgc.names;
|
||||
|
||||
for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) {
|
||||
|
||||
name.data = &p[2];
|
||||
name.len = ngx_strlen(name.data);
|
||||
|
||||
n = 2 * ((p[0] << 8) + p[1]);
|
||||
|
||||
value.data = &str->data[captures[n]];
|
||||
value.len = captures[n + 1] - captures[n];
|
||||
|
||||
key = ngx_hash_strlow(name.data, name.data, name.len);
|
||||
|
||||
vv = ngx_http_ssi_get_variable(r, &name, key);
|
||||
|
||||
if (vv) {
|
||||
*vv = value;
|
||||
continue;
|
||||
}
|
||||
|
||||
var = ngx_list_push(ctx->variables);
|
||||
if (var == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
var->name = name;
|
||||
var->key = key;
|
||||
var->value = value;
|
||||
}
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
|
||||
#else
|
||||
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"the using of the regex \"%V\" in SSI requires PCRE library",
|
||||
pattern);
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static ngx_int_t
|
||||
ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
|
||||
ngx_str_t **params)
|
||||
|
@ -2451,39 +2586,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
|
|||
}
|
||||
|
||||
} else {
|
||||
#if (NGX_PCRE)
|
||||
ngx_regex_compile_t rgc;
|
||||
u_char errstr[NGX_MAX_CONF_ERRSTR];
|
||||
|
||||
right.data[right.len] = '\0';
|
||||
|
||||
ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
|
||||
rc = ngx_http_ssi_regex_match(r, &right, &left);
|
||||
|
||||
rgc.pattern = right;
|
||||
rgc.pool = r->pool;
|
||||
rgc.err.len = NGX_MAX_CONF_ERRSTR;
|
||||
rgc.err.data = errstr;
|
||||
|
||||
if (ngx_regex_compile(&rgc) != NGX_OK) {
|
||||
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
if (rc == NGX_OK) {
|
||||
rc = 0;
|
||||
} else if (rc == NGX_DECLINED) {
|
||||
rc = -1;
|
||||
} else {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = ngx_regex_exec(rgc.regex, &left, NULL, 0);
|
||||
|
||||
if (rc < NGX_REGEX_NO_MATCHED) {
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
|
||||
rc, &left, &right);
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
}
|
||||
#else
|
||||
ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
|
||||
"the using of the regex \"%V\" in SSI "
|
||||
"requires PCRE library", &right);
|
||||
|
||||
return NGX_HTTP_SSI_ERROR;
|
||||
#endif
|
||||
}
|
||||
|
||||
if ((rc == 0 && !negative) || (rc != 0 && negative)) {
|
||||
|
|
|
@ -64,6 +64,12 @@ typedef struct {
|
|||
ngx_list_t *variables;
|
||||
ngx_array_t *blocks;
|
||||
|
||||
#if (NGX_PCRE)
|
||||
ngx_uint_t ncaptures;
|
||||
int *captures;
|
||||
u_char *captures_data;
|
||||
#endif
|
||||
|
||||
unsigned conditional:2;
|
||||
unsigned encoding:2;
|
||||
unsigned block:1;
|
||||
|
|
Loading…
Reference in a new issue