# HG changeset patch # User Igor Sysoev # Date 1193670184 0 # Node ID d72f8b48dd87fdcbe3c69f7c4eacc307561dbc1c # Parent d5db0e96bcc620a3186836a09bb99190c6e04cb9 r1545, r1546 merge: ngx_escape_html(), SSI echo encoding diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -1305,6 +1305,67 @@ done: } +uintptr_t +ngx_escape_html(u_char *dst, u_char *src, size_t size) +{ + u_char ch; + ngx_uint_t i, len; + + if (dst == NULL) { + + len = 0; + + for (i = 0; i < size; i++) { + switch (*src++) { + + case '<': + len += sizeof("<") - 2; + break; + + case '>': + len += sizeof(">") - 2; + break; + + case '&': + len += sizeof("&") - 2; + break; + + default: + break; + } + } + + return (uintptr_t) len; + } + + for (i = 0; i < size; i++) { + ch = *src++; + + switch (ch) { + + case '<': + *dst++ = '&'; *dst++ = 'l'; *dst++ = 't'; *dst++ = ';'; + break; + + case '>': + *dst++ = '&'; *dst++ = 'g'; *dst++ = 't'; *dst++ = ';'; + break; + + case '&': + *dst++ = '&'; *dst++ = 'a'; *dst++ = 'm'; *dst++ = 'p'; + *dst++ = ';'; + break; + + default: + *dst++ = ch; + break; + } + } + + return (uintptr_t) dst; +} + + /* ngx_sort() is implemented as insertion sort because we need stable sort */ void diff --git a/src/core/ngx_string.h b/src/core/ngx_string.h --- a/src/core/ngx_string.h +++ b/src/core/ngx_string.h @@ -165,6 +165,8 @@ u_char *ngx_utf_cpystrn(u_char *dst, u_c uintptr_t ngx_escape_uri(u_char *dst, u_char *src, size_t size, ngx_uint_t type); void ngx_unescape_uri(u_char **dst, u_char **src, size_t size, ngx_uint_t type); +uintptr_t ngx_escape_html(u_char *dst, u_char *src, size_t size); + void ngx_sort(void *base, size_t n, size_t size, diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -212,6 +212,7 @@ static ngx_str_t ngx_http_ssi_null_strin #define NGX_HTTP_SSI_ECHO_VAR 0 #define NGX_HTTP_SSI_ECHO_DEFAULT 1 +#define NGX_HTTP_SSI_ECHO_ENCODING 2 #define NGX_HTTP_SSI_CONFIG_ERRMSG 0 #define NGX_HTTP_SSI_CONFIG_TIMEFMT 1 @@ -237,6 +238,7 @@ static ngx_http_ssi_param_t ngx_http_ss static ngx_http_ssi_param_t ngx_http_ssi_echo_params[] = { { ngx_string("var"), NGX_HTTP_SSI_ECHO_VAR, 1, 0 }, { ngx_string("default"), NGX_HTTP_SSI_ECHO_DEFAULT, 0, 0 }, + { ngx_string("encoding"), NGX_HTTP_SSI_ECHO_ENCODING, 0, 0 }, { ngx_null_string, 0, 0, 0 } }; @@ -355,6 +357,7 @@ found: ctx->value_len = slcf->value_len; ctx->last_out = &ctx->out; + ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING; ctx->output = 1; ctx->params.elts = ctx->params_array; @@ -2119,10 +2122,12 @@ static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { + u_char *p; + uintptr_t len; ngx_int_t key; ngx_uint_t i; ngx_buf_t *b; - ngx_str_t *var, *value, text; + ngx_str_t *var, *value, *enc, text; ngx_chain_t *cl; ngx_http_variable_value_t *vv; @@ -2170,6 +2175,69 @@ ngx_http_ssi_echo(ngx_http_request_t *r, } } + enc = params[NGX_HTTP_SSI_ECHO_ENCODING]; + + if (enc) { + if (enc->len == 4 && ngx_strncmp(enc->data, "none", 4) == 0) { + + ctx->encoding = NGX_HTTP_SSI_NO_ENCODING; + + } else if (enc->len == 3 && ngx_strncmp(enc->data, "url", 3) == 0) { + + ctx->encoding = NGX_HTTP_SSI_URL_ENCODING; + + } else if (enc->len == 6 && ngx_strncmp(enc->data, "entity", 6) == 0) { + + ctx->encoding = NGX_HTTP_SSI_ENTITY_ENCODING; + + } else { + ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, + "unknown encoding \"%V\" in the \"echo\" command", + enc); + } + } + + switch (ctx->encoding) { + + case NGX_HTTP_SSI_NO_ENCODING: + break; + + case NGX_HTTP_SSI_URL_ENCODING: + len = 2 * ngx_escape_uri(NULL, value->data, value->len, + NGX_ESCAPE_HTML); + + if (len) { + p = ngx_palloc(r->pool, value->len + len); + if (p == NULL) { + return NGX_HTTP_SSI_ERROR; + } + + (void) ngx_escape_uri(p, value->data, value->len, NGX_ESCAPE_HTML); + + value->len += len; + value->data = p; + } + + break; + + case NGX_HTTP_SSI_ENTITY_ENCODING: + len = ngx_escape_html(NULL, value->data, value->len); + + if (len) { + p = ngx_palloc(r->pool, value->len + len); + if (p == NULL) { + return NGX_HTTP_SSI_ERROR; + } + + (void) ngx_escape_html(p, value->data, value->len); + + value->len += len; + value->data = p; + } + + break; + } + b = ngx_calloc_buf(r->pool); if (b == NULL) { return NGX_HTTP_SSI_ERROR; diff --git a/src/http/modules/ngx_http_ssi_filter_module.h b/src/http/modules/ngx_http_ssi_filter_module.h --- a/src/http/modules/ngx_http_ssi_filter_module.h +++ b/src/http/modules/ngx_http_ssi_filter_module.h @@ -13,15 +13,20 @@ #include -#define NGX_HTTP_SSI_MAX_PARAMS 16 +#define NGX_HTTP_SSI_MAX_PARAMS 16 -#define NGX_HTTP_SSI_COMMAND_LEN 32 -#define NGX_HTTP_SSI_PARAM_LEN 32 -#define NGX_HTTP_SSI_PARAMS_N 4 +#define NGX_HTTP_SSI_COMMAND_LEN 32 +#define NGX_HTTP_SSI_PARAM_LEN 32 +#define NGX_HTTP_SSI_PARAMS_N 4 -#define NGX_HTTP_SSI_COND_IF 1 -#define NGX_HTTP_SSI_COND_ELSE 2 +#define NGX_HTTP_SSI_COND_IF 1 +#define NGX_HTTP_SSI_COND_ELSE 2 + + +#define NGX_HTTP_SSI_NO_ENCODING 0 +#define NGX_HTTP_SSI_URL_ENCODING 1 +#define NGX_HTTP_SSI_ENTITY_ENCODING 2 typedef struct { @@ -60,6 +65,7 @@ typedef struct { ngx_array_t *blocks; unsigned conditional:2; + unsigned encoding:2; unsigned block:1; unsigned output:1; unsigned output_chosen:1;