comparison src/http/modules/ngx_http_ssi_filter_module.c @ 122:d25a1d6034f1 NGINX_0_3_8

nginx 0.3.8 *) Security: nginx now checks URI got from a backend in "X-Accel-Redirect" header line or in SSI file for the "/../" paths and zeroes. *) Change: nginx now does not treat the empty user name in the "Authorization" header line as valid one. *) Feature: the "ssl_session_timeout" directives of the ngx_http_ssl_module and ngx_imap_ssl_module. *) Feature: the "auth_http_header" directive of the ngx_imap_auth_http_module. *) Feature: the "add_header" directive. *) Feature: the ngx_http_realip_module. *) Feature: the new variables to use in the "log_format" directive: $bytes_sent, $apache_bytes_sent, $status, $time_gmt, $uri, $request_time, $request_length, $upstream_status, $upstream_response_time, $gzip_ratio, $uid_got, $uid_set, $connection, $pipe, and $msec. The parameters in the "%name" form will be canceled soon. *) Change: now the false variable values in the "if" directive are the empty string "" and string starting with "0". *) Bugfix: while using proxied or FastCGI-server nginx may leave connections and temporary files with client requests in open state. *) Bugfix: the worker processes did not flush the buffered logs on graceful exit. *) Bugfix: if the request URI was changes by the "rewrite" directive and the request was proxied in location given by regular expression, then the incorrect request was transferred to backend; bug appeared in 0.2.6. *) Bugfix: the "expires" directive did not remove the previous "Expires" header. *) Bugfix: nginx may stop to accept requests if the "rtsig" method and several worker processes were used. *) Bugfix: the "\"" and "\'" escape symbols were incorrectly handled in SSI commands. *) Bugfix: if the response was ended just after the SSI command and gzipping was used, then the response did not transferred complete or did not transferred at all.
author Igor Sysoev <http://sysoev.ru>
date Wed, 09 Nov 2005 00:00:00 +0300
parents 644a7935144b
children df17fbafec8f
comparison
equal deleted inserted replaced
121:737953b238a4 122:d25a1d6034f1
142 static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r, 142 static ngx_int_t ngx_http_ssi_else(ngx_http_request_t *r,
143 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); 143 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
144 static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r, 144 static ngx_int_t ngx_http_ssi_endif(ngx_http_request_t *r,
145 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); 145 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
146 146
147 static ngx_http_variable_value_t * 147 static ngx_int_t ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
148 ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt); 148 ngx_http_variable_value_t *v, uintptr_t gmt);
149 149
150 static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 150 static char *ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf);
151 151
152 static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf); 152 static ngx_int_t ngx_http_ssi_add_variables(ngx_conf_t *cf);
153 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf); 153 static void *ngx_http_ssi_create_conf(ngx_conf_t *cf);
560 if (rc == NGX_AGAIN) { 560 if (rc == NGX_AGAIN) {
561 continue; 561 continue;
562 } 562 }
563 563
564 564
565 b = NULL;
566
565 if (rc == NGX_OK) { 567 if (rc == NGX_OK) {
566 568
567 for (cmd = ngx_http_ssi_commands; cmd->handler; cmd++) { 569 for (cmd = ngx_http_ssi_commands; cmd->handler; cmd++) {
568 if (cmd->name.len == 0) { 570 if (cmd->name.len == 0) {
569 cmd = (ngx_http_ssi_command_t *) cmd->handler; 571 cmd = (ngx_http_ssi_command_t *) cmd->handler;
1198 if (ch == '\\') { 1200 if (ch == '\\') {
1199 break; 1201 break;
1200 } 1202 }
1201 1203
1202 if (ch == '"' && state == ssi_double_quoted_value_state) { 1204 if (ch == '"' && state == ssi_double_quoted_value_state) {
1205 ctx->param->value.data[ctx->param->value.len - 1] = ch;
1203 break; 1206 break;
1204 } 1207 }
1205 1208
1206 if (ch == '\'' && state == ssi_quoted_value_state) { 1209 if (ch == '\'' && state == ssi_quoted_value_state) {
1210 ctx->param->value.data[ctx->param->value.len - 1] = ch;
1207 break; 1211 break;
1208 } 1212 }
1209 1213
1210 ctx->param->value.data[ctx->param->value.len++] = ch; 1214 ctx->param->value.data[ctx->param->value.len++] = ch;
1211 1215
1376 1380
1377 static ngx_int_t 1381 static ngx_int_t
1378 ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, 1382 ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
1379 ngx_str_t *text, ngx_uint_t flags) 1383 ngx_str_t *text, ngx_uint_t flags)
1380 { 1384 {
1381 u_char ch, *p, **value, *data; 1385 u_char ch, *p, **value, *data, *part_data;
1382 size_t *size, len, prefix; 1386 size_t *size, len, prefix, part_len;
1383 ngx_str_t var, part, *val; 1387 ngx_str_t var, *val;
1384 ngx_uint_t i, j, n, bracket; 1388 ngx_uint_t i, j, n, bracket;
1385 ngx_array_t lengths, values; 1389 ngx_array_t lengths, values;
1386 ngx_http_variable_value_t *vv; 1390 ngx_http_variable_value_t *vv;
1387 1391
1388 n = ngx_http_script_variables_count(text); 1392 n = ngx_http_script_variables_count(text);
1406 data = ngx_palloc(r->pool, len); 1410 data = ngx_palloc(r->pool, len);
1407 if (data == NULL) { 1411 if (data == NULL) {
1408 return NGX_ERROR; 1412 return NGX_ERROR;
1409 } 1413 }
1410 1414
1411 p = ngx_cpymem(data, r->uri.data, prefix); 1415 p = ngx_copy(data, r->uri.data, prefix);
1412 ngx_memcpy(p, text->data, text->len); 1416 ngx_memcpy(p, text->data, text->len);
1413 1417
1414 text->len = len; 1418 text->len = len;
1415 text->data = data; 1419 text->data = data;
1416 } 1420 }
1496 1500
1497 if (vv == NULL) { 1501 if (vv == NULL) {
1498 return NGX_ERROR; 1502 return NGX_ERROR;
1499 } 1503 }
1500 1504
1501 if (vv == NGX_HTTP_VAR_NOT_FOUND) { 1505 if (vv->not_found) {
1502 continue; 1506 continue;
1503 } 1507 }
1504 1508
1505 part = vv->text; 1509 part_data = vv->data;
1510 part_len = vv->len;
1506 1511
1507 } else { 1512 } else {
1508 part = *val; 1513 part_data = val->data;
1514 part_len = val->len;
1509 } 1515 }
1510 1516
1511 } else { 1517 } else {
1512 part.data = &text->data[i]; 1518 part_data = &text->data[i];
1513 1519
1514 for (p = part.data; i < text->len; i++) { 1520 for (p = part_data; i < text->len; i++) {
1515 ch = text->data[i]; 1521 ch = text->data[i];
1516 1522
1517 if (ch == '$') { 1523 if (ch == '$') {
1518 if (text->data[i - 1] != '\\') { 1524 if (text->data[i - 1] != '\\') {
1519 break; 1525 break;
1525 } 1531 }
1526 1532
1527 *p++ = ch; 1533 *p++ = ch;
1528 } 1534 }
1529 1535
1530 part.len = p - part.data; 1536 part_len = p - part_data;
1531 } 1537 }
1532 1538
1533 len += part.len; 1539 len += part_len;
1534 1540
1535 size = ngx_array_push(&lengths); 1541 size = ngx_array_push(&lengths);
1536 if (size == NULL) { 1542 if (size == NULL) {
1537 return NGX_ERROR; 1543 return NGX_ERROR;
1538 } 1544 }
1539 1545
1540 *size = part.len; 1546 *size = part_len;
1541 1547
1542 value = ngx_array_push(&values); 1548 value = ngx_array_push(&values);
1543 if (value == NULL) { 1549 if (value == NULL) {
1544 return NGX_ERROR; 1550 return NGX_ERROR;
1545 } 1551 }
1546 1552
1547 *value = part.data; 1553 *value = part_data;
1548 } 1554 }
1549 1555
1550 prefix = 0; 1556 prefix = 0;
1551 1557
1552 size = lengths.elts; 1558 size = lengths.elts;
1575 } 1581 }
1576 1582
1577 text->len = len; 1583 text->len = len;
1578 text->data = p; 1584 text->data = p;
1579 1585
1580 if (prefix) { 1586 p = ngx_copy(p, r->uri.data, prefix);
1581 p = ngx_cpymem(p, r->uri.data, prefix);
1582 }
1583 1587
1584 for (i = 0; i < values.nelts; i++) { 1588 for (i = 0; i < values.nelts; i++) {
1585 p = ngx_cpymem(p, value[i], size[i]); 1589 p = ngx_copy(p, value[i], size[i]);
1586 } 1590 }
1587 1591
1588 return NGX_OK; 1592 return NGX_OK;
1589 1593
1590 invalid_variable: 1594 invalid_variable:
1599 static ngx_int_t 1603 static ngx_int_t
1600 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, 1604 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
1601 ngx_str_t **params) 1605 ngx_str_t **params)
1602 { 1606 {
1603 ngx_str_t *uri, *file, args; 1607 ngx_str_t *uri, *file, args;
1604 ngx_uint_t i; 1608 ngx_uint_t flags;
1605 1609
1606 uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]; 1610 uri = params[NGX_HTTP_SSI_INCLUDE_VIRTUAL];
1607 file = params[NGX_HTTP_SSI_INCLUDE_FILE]; 1611 file = params[NGX_HTTP_SSI_INCLUDE_FILE];
1608 1612
1609 if (uri && file) { 1613 if (uri && file) {
1629 return NGX_HTTP_SSI_ERROR; 1633 return NGX_HTTP_SSI_ERROR;
1630 } 1634 }
1631 1635
1632 args.len = 0; 1636 args.len = 0;
1633 args.data = NULL; 1637 args.data = NULL;
1634 1638 flags = 0;
1635 if (params[NGX_HTTP_SSI_INCLUDE_VIRTUAL]) { 1639
1636 for (i = 0; i < uri->len; i++) { 1640 ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
1637 if (uri->data[i] == '?') { 1641 "ssi include: \"%V\"", uri);
1638 args.len = uri->len - i - 1; 1642
1639 args.data = &uri->data[i + 1]; 1643 if (ngx_http_parse_unsafe_uri(r, uri, &args, &flags) != NGX_OK) {
1640 uri->len -= args.len + 1; 1644 return NGX_HTTP_SSI_ERROR;
1641 1645 }
1642 break; 1646
1643 } 1647 if (ngx_http_subrequest(r, uri, &args, flags) != NGX_OK) {
1644 }
1645 }
1646
1647 if (ngx_http_subrequest(r, uri, &args) != NGX_OK) {
1648 return NGX_HTTP_SSI_ERROR; 1648 return NGX_HTTP_SSI_ERROR;
1649 } 1649 }
1650 1650
1651 return NGX_OK; 1651 return NGX_OK;
1652 } 1652 }
1656 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, 1656 ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
1657 ngx_str_t **params) 1657 ngx_str_t **params)
1658 { 1658 {
1659 ngx_uint_t i; 1659 ngx_uint_t i;
1660 ngx_buf_t *b; 1660 ngx_buf_t *b;
1661 ngx_str_t *var, *value; 1661 ngx_str_t *var, *value, text;
1662 ngx_chain_t *cl; 1662 ngx_chain_t *cl;
1663 ngx_http_variable_value_t *vv; 1663 ngx_http_variable_value_t *vv;
1664 1664
1665 var = params[NGX_HTTP_SSI_ECHO_VAR]; 1665 var = params[NGX_HTTP_SSI_ECHO_VAR];
1666 1666
1675 1675
1676 if (vv == NULL) { 1676 if (vv == NULL) {
1677 return NGX_HTTP_SSI_ERROR; 1677 return NGX_HTTP_SSI_ERROR;
1678 } 1678 }
1679 1679
1680 if (vv != NGX_HTTP_VAR_NOT_FOUND) { 1680 if (!vv->not_found) {
1681 value = &vv->text; 1681 text.data = vv->data;
1682 text.len = vv->len;
1683 value = &text;
1682 } 1684 }
1683 } 1685 }
1684 1686
1685 if (value == NULL) { 1687 if (value == NULL) {
1686 value = params[NGX_HTTP_SSI_ECHO_DEFAULT]; 1688 value = params[NGX_HTTP_SSI_ECHO_DEFAULT];
1815 continue; 1817 continue;
1816 } 1818 }
1817 1819
1818 if ((*p >= 'a' && *p <= 'z') 1820 if ((*p >= 'a' && *p <= 'z')
1819 || (*p >= '0' && *p <= '9') 1821 || (*p >= '0' && *p <= '9')
1820 || *p == '$' || *p == '{' || *p == '}' || *p == '_') 1822 || *p == '$' || *p == '{' || *p == '}' || *p == '_'
1823 || *p == '"' || *p == '\'')
1821 { 1824 {
1822 continue; 1825 continue;
1823 } 1826 }
1824 1827
1825 break; 1828 break;
1969 1972
1970 return NGX_OK; 1973 return NGX_OK;
1971 } 1974 }
1972 1975
1973 1976
1974 static ngx_http_variable_value_t * 1977 static ngx_int_t
1975 ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r, uintptr_t gmt) 1978 ngx_http_ssi_date_gmt_local_variable(ngx_http_request_t *r,
1979 ngx_http_variable_value_t *v, uintptr_t gmt)
1976 { 1980 {
1977 ngx_http_ssi_ctx_t *ctx; 1981 ngx_http_ssi_ctx_t *ctx;
1978 ngx_http_variable_value_t *vv; 1982 ngx_time_t *tp;
1979 ngx_time_t *tp; 1983 struct tm tm;
1980 struct tm tm; 1984 char buf[NGX_HTTP_SSI_DATE_LEN];
1981 char buf[NGX_HTTP_SSI_DATE_LEN]; 1985
1982 1986 v->valid = 1;
1983 vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); 1987 v->no_cachable = 0;
1984 if (vv == NULL) { 1988 v->not_found = 0;
1985 return NULL;
1986 }
1987 1989
1988 tp = ngx_timeofday(); 1990 tp = ngx_timeofday();
1989 1991
1990 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module); 1992 ctx = ngx_http_get_module_ctx(r, ngx_http_ssi_filter_module);
1991 1993
1992 if (ctx->timefmt.len == sizeof("%s") - 1 1994 if (ctx->timefmt.len == sizeof("%s") - 1
1993 && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's') 1995 && ctx->timefmt.data[0] == '%' && ctx->timefmt.data[1] == 's')
1994 { 1996 {
1995 vv->value = tp->sec + (gmt ? 0 : tp->gmtoff); 1997 v->data = ngx_palloc(r->pool, NGX_TIME_T_LEN);
1996 1998 if (v->data == NULL) {
1997 vv->text.data = ngx_palloc(r->pool, NGX_TIME_T_LEN); 1999 return NGX_ERROR;
1998 if (vv->text.data == NULL) { 2000 }
1999 return NULL; 2001
2000 } 2002 v->len = ngx_sprintf(v->data, "%T", tp->sec + (gmt ? 0 : tp->gmtoff))
2001 2003 - v->data;
2002 vv->text.len = ngx_sprintf(vv->text.data, "%T", vv->value) 2004 return NGX_OK;
2003 - vv->text.data;
2004 return vv;
2005 } 2005 }
2006 2006
2007 if (gmt) { 2007 if (gmt) {
2008 ngx_libc_gmtime(tp->sec, &tm); 2008 ngx_libc_gmtime(tp->sec, &tm);
2009 } else { 2009 } else {
2010 ngx_libc_localtime(tp->sec, &tm); 2010 ngx_libc_localtime(tp->sec, &tm);
2011 } 2011 }
2012 2012
2013 vv->value = tp->sec + (gmt ? 0 : tp->gmtoff); 2013 v->len = strftime(buf, NGX_HTTP_SSI_DATE_LEN,
2014 2014 (char *) ctx->timefmt.data, &tm);
2015 vv->text.len = strftime(buf, NGX_HTTP_SSI_DATE_LEN, 2015 if (v->len == 0) {
2016 (char *) ctx->timefmt.data, &tm); 2016 return NGX_ERROR;
2017 if (vv->text.len == 0) { 2017 }
2018 return NULL; 2018
2019 } 2019 v->data = ngx_palloc(r->pool, v->len);
2020 2020 if (v->data == NULL) {
2021 vv->text.data = ngx_palloc(r->pool, vv->text.len); 2021 return NGX_ERROR;
2022 if (vv->text.data == NULL) { 2022 }
2023 return NULL; 2023
2024 } 2024 ngx_memcpy(v->data, buf, v->len);
2025 2025
2026 ngx_memcpy(vv->text.data, buf, vv->text.len); 2026 return NGX_OK;
2027
2028 return vv;
2029 } 2027 }
2030 2028
2031 2029
2032 static char * 2030 static char *
2033 ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 2031 ngx_http_ssi_types(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)