Welcome! Log In Create A New Profile

Advanced

Экранирующие шрифты в SSI модуле

Posted by alt13 
Экранирующие шрифты в SSI модуле
January 26, 2012 04:44AM
Уважаемые разработчики пожалуйста поправьте работу экранирующих слешов в модуле ngx_http_ssi_filter_module.c в зависимости от того какие внешние кавычки используются в выражении (двойные или одинарные) они должны работать по разному, сейчас это не учитывается.

Ниже привожу код процедуры ngx_http_ssi_evaluate_string корректно работающей с таким выражением
<!--#set var="test1" value='Ic$t1\$hi12fsfs\\312 \go \' \"'-->
в которой удаляются только те слеши которые экранируют знак доллара (в этом случае
\$hi не считается переменной) и те слэши, которые стоят перед кавычкой,
совпадающей с внешними, в данном случае с одинарной, также двойной слеш заменяется на одинарный.


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, *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_array_t lengths, values;
ngx_http_variable_value_t *vv;

n = ngx_http_script_variables_count(text);

if (n == 0) {

data = text->data;
p = data;

if ((flags & NGX_HTTP_SSI_ADD_PREFIX) && text->data[0] != '/') {

for (prefix = r->uri.len; prefix; prefix--) {
if (r->uri.data[prefix - 1] == '/') {
break;
}
}

if (prefix) {
len = prefix + text->len;

data = ngx_pnalloc(r->pool, len);
if (data == NULL) {
return NGX_ERROR;
}

p = ngx_copy(data, r->uri.data, prefix);
}
}

quoted = 0;

for (i = 0; i < text->len; i++) {
ch = text->data[i];

if (!quoted) {

if (ch == '\\') {
if ( (i + 1 < text->len) &&
( ( (text->data[i + 1] == '\'') && (ctx->saved_state == ssi_quoted_value_state) ) ||
( (text->data[i + 1] == '"') && (ctx->saved_state == ssi_double_quoted_value_state) ) ) ) {
quoted = 1;
continue;
}
}
} else {
quoted = 0;

if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
*p++ = '\\';
}
}

*p++ = ch;
}

text->len = p - data;
text->data = data;

return NGX_OK;
}

if (ngx_array_init(&lengths, r->pool, 8, sizeof(size_t *)) != NGX_OK) {
return NGX_ERROR;
}

if (ngx_array_init(&values, r->pool, 8, sizeof(u_char *)) != NGX_OK) {
return NGX_ERROR;
}

len = 0;
i = 0;

while (i < text->len) {

if ( (text->data[i] == '$') && ( (i == 0) || ((i > 0) && (text->data[i - 1] != '\\')) ) ) {

var.len = 0;

if (++i == text->len) {
goto invalid_variable;
}

if (text->data[i] == '{') {
bracket = 1;

if (++i == text->len) {
goto invalid_variable;
}

var.data = &text->data[i];

} else {
bracket = 0;
var.data = &text->data[i];
}

for ( /* void */ ; i < text->len; i++, var.len++) {
ch = text->data[i];

if (ch == '}' && bracket) {
i++;
bracket = 0;
break;
}

if ((ch >= 'A' && ch <= 'Z')
|| (ch >= 'a' && ch <= 'z')
|| (ch >= '0' && ch <= '9')
|| ch == '_')
{
continue;
}

break;
}

if (bracket) {
ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
"the closing bracket in \"%V\" "
"variable is missing", &var);
return NGX_HTTP_SSI_ERROR;
}

if (var.len == 0) {
goto invalid_variable;
}

key = ngx_hash_strlow(var.data, var.data, var.len);

val = ngx_http_ssi_get_variable(r, &var, key);

if (val == NULL) {
vv = ngx_http_get_variable(r, &var, key);
if (vv == NULL) {
return NGX_ERROR;
}

if (vv->not_found) {
continue;
}

part_data = vv->data;
part_len = vv->len;

} else {
part_data = val->data;
part_len = val->len;
}

} else {
part_data = &text->data[i];
quoted = 0;

for (p = part_data; i < text->len; i++) {
ch = text->data[i];

if (!quoted) {

if (ch == '\\') {
if ( (i + 1 < text->len) &&
( ( (text->data[i + 1] == '\'') && (ctx->saved_state == ssi_quoted_value_state) ) ||
( (text->data[i + 1] == '"') && (ctx->saved_state == ssi_double_quoted_value_state) ) ||
(text->data[i + 1] == '$') ) ) {
quoted = 1;
continue;
}
}

if ( (ch == '$') && ((i == 0) || ((i > 0) && (text->data[i - 1] != '\\')) ) ) {
break;
}

} else {
quoted = 0;

if (ch != '\\' && ch != '\'' && ch != '"' && ch != '$') {
*p++ = '\\';
}
}

*p++ = ch;
}

part_len = p - part_data;
}

len += part_len;

size = ngx_array_push(&lengths);
if (size == NULL) {
return NGX_ERROR;
}

*size = part_len;

value = ngx_array_push(&values);
if (value == NULL) {
return NGX_ERROR;
}

*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] != '/') {
for (prefix = r->uri.len; prefix; prefix--) {
if (r->uri.data[prefix - 1] == '/') {
len += prefix;
break;
}
}
}

break;
}
}
}

p = ngx_pnalloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0));
if (p == NULL) {
return NGX_ERROR;
}

text->len = len;
text->data = p;

p = ngx_copy(p, r->uri.data, prefix);

for (i = 0; i < values.nelts; i++) {
p = ngx_copy(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_HTTP_SSI_ERROR;
}

Заранее благодарен
Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 186
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready