12 #define NGX_HTTP_SSI_ERROR 1
14 #define NGX_HTTP_SSI_DATE_LEN 2048
16 #define NGX_HTTP_SSI_ADD_PREFIX 1
17 #define NGX_HTTP_SSI_ADD_ZERO 2
112 static void *ngx_http_ssi_create_main_conf(
ngx_conf_t *cf);
113 static char *ngx_http_ssi_init_main_conf(
ngx_conf_t *cf,
void *conf);
114 static void *ngx_http_ssi_create_loc_conf(
ngx_conf_t *cf);
115 static char *ngx_http_ssi_merge_loc_conf(
ngx_conf_t *cf,
116 void *parent,
void *child);
171 ngx_http_ssi_preconfiguration,
172 ngx_http_ssi_filter_init,
174 ngx_http_ssi_create_main_conf,
175 ngx_http_ssi_init_main_conf,
180 ngx_http_ssi_create_loc_conf,
181 ngx_http_ssi_merge_loc_conf
187 &ngx_http_ssi_filter_module_ctx,
188 ngx_http_ssi_filter_commands,
205 static u_char ngx_http_ssi_string[] =
"<!--";
211 #define NGX_HTTP_SSI_INCLUDE_VIRTUAL 0
212 #define NGX_HTTP_SSI_INCLUDE_FILE 1
213 #define NGX_HTTP_SSI_INCLUDE_WAIT 2
214 #define NGX_HTTP_SSI_INCLUDE_SET 3
215 #define NGX_HTTP_SSI_INCLUDE_STUB 4
217 #define NGX_HTTP_SSI_ECHO_VAR 0
218 #define NGX_HTTP_SSI_ECHO_DEFAULT 1
219 #define NGX_HTTP_SSI_ECHO_ENCODING 2
221 #define NGX_HTTP_SSI_CONFIG_ERRMSG 0
222 #define NGX_HTTP_SSI_CONFIG_TIMEFMT 1
224 #define NGX_HTTP_SSI_SET_VAR 0
225 #define NGX_HTTP_SSI_SET_VALUE 1
227 #define NGX_HTTP_SSI_IF_EXPR 0
229 #define NGX_HTTP_SSI_BLOCK_NAME 0
282 {
ngx_string(
"include"), ngx_http_ssi_include,
283 ngx_http_ssi_include_params, 0, 0, 1 },
285 ngx_http_ssi_echo_params, 0, 0, 0 },
287 ngx_http_ssi_config_params, 0, 0, 0 },
288 {
ngx_string(
"set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0, 0 },
290 {
ngx_string(
"if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0, 0 },
291 {
ngx_string(
"elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
293 {
ngx_string(
"else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
295 {
ngx_string(
"endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
299 ngx_http_ssi_block_params, 0, 0, 0 },
300 {
ngx_string(
"endblock"), ngx_http_ssi_endblock,
301 ngx_http_ssi_no_params, 0, 1, 0 },
309 {
ngx_string(
"date_local"), NULL, ngx_http_ssi_date_gmt_local_variable, 0,
312 {
ngx_string(
"date_gmt"), NULL, ngx_http_ssi_date_gmt_local_variable, 1,
332 return ngx_http_next_header_filter(r);
356 "[an error occurred while processing the directive]");
367 return ngx_http_next_header_filter(r);
394 && ctx->
busy == NULL))
396 return ngx_http_next_body_filter(r, in);
408 "http ssi filter \"%V?%V\"", &r->
uri, &r->
args);
414 "http ssi filter wait \"%V?%V\" non-active",
422 "http ssi filter wait \"%V?%V\" done",
429 "http ssi filter wait \"%V?%V\"",
432 return ngx_http_next_body_filter(r, NULL);
438 while (ctx->
in || ctx->
buf) {
440 if (ctx->
buf == NULL) {
456 "saved: %d state: %d", ctx->
saved, ctx->
state);
458 rc = ngx_http_ssi_parse(r, ctx);
461 "parse: %d, looked: %d %p-%p",
473 "saved: %d", ctx->
saved);
498 b->
pos = ngx_http_ssi_string;
499 b->
last = ngx_http_ssi_string + ctx->
saved;
580 ngx_http_ssi_filter_module);
615 ngx_http_ssi_filter_module);
623 "invalid SSI command: \"%V\"",
641 len += 1 + param[
i].
key.
len + 2
685 ngx_http_ssi_filter_module);
711 "invalid context of SSI command: \"%V\"",
718 "too many SSI command parameters: \"%V\"",
732 if (param[i].key.len != prm->
name.
len
740 if (params[prm->
index]) {
743 "duplicate \"%V\" parameter "
744 "in \"%V\" SSI command",
755 for (index = prm->
index; params[index]; index++) {
766 "invalid parameter name: \"%V\" "
767 "in \"%V\" SSI command",
777 "mandatory \"%V\" parameter is absent "
778 "in \"%V\" SSI command",
790 if (ngx_http_ssi_output(r, ctx) ==
NGX_ERROR) {
795 rc = cmd->
handler(r, ctx, params);
802 ngx_http_ssi_buffered(r, ctx);
889 if (ctx->
out == NULL && ctx->
busy == NULL) {
893 return ngx_http_ssi_output(r, ctx);
906 for (cl = ctx->
out; cl; cl = cl->
next) {
908 "ssi out: %p %p", cl->
buf, cl->
buf->
pos);
911 "the same buf was used in ssi");
919 rc = ngx_http_next_body_filter(r, ctx->
out);
921 if (ctx->
busy == NULL) {
955 ngx_http_ssi_buffered(r, ctx);
964 if (ctx->
in || ctx->
buf) {
976 u_char *p, *value, *last, *copy_end, ch;
985 for (p = ctx->
pos; p < last; p++) {
1098 if (p - ctx->
pos < 4) {
1165 "the \"%V%c...\" SSI command is too long",
1192 if (ctx->
param == NULL) {
1242 "invalid \"%V\" parameter in \"%V\" SSI command",
1250 "too long \"%V%c...\" parameter in "
1251 "\"%V\" SSI command",
1281 "unexpected \"%c\" symbol after \"%V\" "
1282 "parameter in \"%V\" SSI command",
1313 "unexpected \"%c\" symbol before value of "
1314 "\"%V\" parameter in \"%V\" SSI command",
1336 "too long \"%V%c...\" value of \"%V\" "
1337 "parameter in \"%V\" SSI command",
1364 "too long \"%V%c...\" value of \"%V\" "
1365 "parameter in \"%V\" SSI command",
1382 "too long \"%V%c...\" value of \"%V\" "
1383 "parameter in \"%V\" SSI command",
1398 if (value == NULL) {
1426 "unexpected \"%c\" symbol after \"%V\" value "
1427 "of \"%V\" parameter in \"%V\" SSI command",
1444 "unexpected \"%c\" symbol in \"%V\" SSI command",
1468 "unexpected \"%c\" symbol in \"%V\" SSI command",
1553 if (key >=
'0' && key <=
'9') {
1556 if (i < ctx->ncaptures) {
1558 if (value == NULL) {
1564 value->
data = ctx->captures_data + ctx->captures[
i];
1565 value->
len = ctx->captures[i + 1] - ctx->captures[
i];
1580 for (i = 0; ; i++) {
1582 if (i >= part->
nelts) {
1583 if (part->
next == NULL) {
1596 if (key != var[i].key) {
1613 u_char ch, *p, **value, *data, *part_data;
1614 size_t *size, len, prefix, part_len;
1630 for (prefix = r->
uri.
len; prefix; prefix--) {
1631 if (r->
uri.
data[prefix - 1] ==
'/') {
1637 len = prefix + text->
len;
1650 for (i = 0; i < text->
len; i++) {
1663 if (ch !=
'\\' && ch !=
'\'' && ch !=
'"' && ch !=
'$') {
1671 text->
len = p - data;
1677 if (ngx_array_init(&lengths, r->
pool, 8,
sizeof(
size_t *)) !=
NGX_OK) {
1681 if (ngx_array_init(&values, r->
pool, 8,
sizeof(u_char *)) !=
NGX_OK) {
1688 while (i < text->len) {
1690 if (text->
data[i] ==
'$') {
1694 if (++i == text->
len) {
1695 goto invalid_variable;
1698 if (text->
data[i] ==
'{') {
1701 if (++i == text->
len) {
1702 goto invalid_variable;
1712 for ( ; i < text->
len; i++, var.
len++) {
1715 if (ch ==
'}' && bracket) {
1721 if ((ch >=
'A' && ch <=
'Z')
1722 || (ch >=
'a' && ch <=
'z')
1723 || (ch >=
'0' && ch <=
'9')
1734 "the closing bracket in \"%V\" "
1735 "variable is missing", &var);
1740 goto invalid_variable;
1745 val = ngx_http_ssi_get_variable(r, &var, key);
1757 part_data = vv->
data;
1761 part_data = val->
data;
1762 part_len = val->
len;
1766 part_data = &text->
data[
i];
1769 for (p = part_data; i < text->
len; i++) {
1786 if (ch !=
'\\' && ch !=
'\'' && ch !=
'"' && ch !=
'$') {
1794 part_len = p - part_data;
1807 if (value == NULL) {
1816 size = lengths.
elts;
1817 value = values.
elts;
1819 if (flags & NGX_HTTP_SSI_ADD_PREFIX) {
1820 for (i = 0; i < values.
nelts; i++) {
1822 if (*value[i] !=
'/') {
1823 for (prefix = r->
uri.
len; prefix; prefix--) {
1824 if (r->
uri.
data[prefix - 1] ==
'/') {
1846 for (i = 0; i < values.
nelts; i++) {
1847 p =
ngx_copy(p, value[i], size[i]);
1855 "invalid variable name in \"%V\"", text);
1891 if (captures == NULL) {
1910 ctx->ncaptures = rc;
1911 ctx->captures = captures;
1912 ctx->captures_data = str->
data;
1932 n = 2 * ((p[0] << 8) + p[1]);
1934 value.
data = &str->
data[captures[n]];
1935 value.
len = captures[n + 1] - captures[n];
1939 vv = ngx_http_ssi_get_variable(r, &name, key);
1962 "the using of the regex \"%V\" in SSI requires PCRE library",
1977 ngx_str_t *uri, *file, *wait, *
set, *stub, args;
1995 "inlcusion may be either virtual=\"%V\" or file=\"%V\"",
2000 if (uri == NULL && file == NULL) {
2002 "no parameter in \"include\" SSI command");
2008 "\"set\" and \"stub\" cannot be used together "
2009 "in \"include\" SSI command");
2016 "\"wait\" cannot be used with file=\"%V\"", file);
2025 }
else if (wait->
len != 3
2029 "invalid value \"%V\" in the \"wait\" parameter",
2040 rc = ngx_http_ssi_evaluate_string(r, ctx, uri, NGX_HTTP_SSI_ADD_PREFIX);
2051 len = (uri->
data + uri->
len) - src;
2059 "ssi include: \"%V\"", uri);
2085 "\"stub\"=\"%V\" for \"include\" not found", stub);
2095 psr->
handler = ngx_http_ssi_stub_output;
2097 if (bl[i].count++) {
2102 for (tl = bl[i].bufs; tl; tl = tl->
next) {
2151 psr->
handler = ngx_http_ssi_set_variable;
2152 psr->
data = ngx_http_ssi_get_variable(r,
set, key);
2154 if (psr->
data == NULL) {
2171 var->
value = ngx_http_ssi_null_string;
2182 if (wait == NULL &&
set == NULL) {
2186 if (ctx->
wait == NULL) {
2193 "can only wait for one subrequest at a time");
2210 "ssi stub output: \"%V?%V\"", &r->
uri, &r->
args);
2257 "ssi echo \"%V\"", var);
2261 value = ngx_http_ssi_get_variable(r, var, key);
2263 if (value == NULL) {
2277 if (value == NULL) {
2280 if (value == NULL) {
2281 value = &ngx_http_ssi_none;
2283 }
else if (value->
len == 0) {
2288 if (value->
len == 0) {
2310 "unknown encoding \"%V\" in the \"echo\" command",
2429 "ssi set \"%V\" \"%V\"", name, value);
2431 rc = ngx_http_ssi_evaluate_string(r, ctx, value, 0);
2439 vv = ngx_http_ssi_get_variable(r, name, key);
2453 var->
value = *value;
2456 "set: \"%V\"=\"%V\"", name, value);
2474 "the \"if\" command inside the \"if\" command");
2487 "ssi if expr=\"%V\"", expr);
2490 last = expr->
data + expr->
len;
2492 for (p = left.
data; p < last; p++) {
2493 if (*p >=
'A' && *p <=
'Z') {
2498 if ((*p >=
'a' && *p <=
'z')
2499 || (*p >=
'0' && *p <=
'9')
2500 || *p ==
'$' || *p ==
'{' || *p ==
'}' || *p ==
'_'
2501 || *p ==
'"' || *p ==
'\'')
2511 while (p < last && *p ==
' ') {
2518 "left: \"%V\"", &left);
2520 rc = ngx_http_ssi_evaluate_string(r, ctx, &left, flags);
2527 "evaluted left: \"%V\"", &left);
2543 if (p < last && *p ==
'=') {
2547 }
else if (p + 1 < last && *p ==
'!' && *(p + 1) ==
'=') {
2552 goto invalid_expression;
2555 while (p < last && *p ==
' ') {
2559 if (p < last - 1 && *p ==
'/') {
2560 if (*(last - 1) !=
'/') {
2561 goto invalid_expression;
2573 if (p < last - 1 && p[0] ==
'\\' && p[1] ==
'/') {
2578 right.
len = last - p;
2582 "right: \"%V\"", &right);
2584 rc = ngx_http_ssi_evaluate_string(r, ctx, &right, flags);
2591 "evaluted right: \"%V\"", &right);
2594 if (left.
len != right.
len) {
2604 rc = ngx_http_ssi_regex_match(r, &right, &left);
2615 if ((rc == 0 && !negative) || (rc != 0 && negative)) {
2630 "invalid expression in \"%V\"", expr);
2682 if (mctx->
blocks == NULL) {
2685 if (mctx->
blocks == NULL) {
2742 if (v->
data == NULL) {
2764 if (v->
data == NULL) {
2775 ngx_http_ssi_preconfiguration(
ngx_conf_t *cf)
2782 for (v = ngx_http_ssi_vars; v->
name.
len; v++) {
2794 for (cmd = ngx_http_ssi_commands; cmd->
name.
len; cmd++) {
2804 "conflicting SSI command \"%V\"", &cmd->
name);
2815 ngx_http_ssi_create_main_conf(
ngx_conf_t *cf)
2836 ngx_http_ssi_init_main_conf(
ngx_conf_t *cf,
void *conf)
2846 hash.
name =
"ssi_command_hash";
2890 ngx_http_ssi_merge_loc_conf(
ngx_conf_t *cf,
void *parent,
void *child)