Mercurial > hg > nginx
comparison src/http/modules/ngx_http_ssi_filter_module.c @ 4438:2840ff6b97bd stable-1.0
Merge of r4375, r4382:
SSI changes:
*) The "if" command did not work inside the "block" command and
produced parsing errors.
*) Added regex captures support in the expression of the "if" command.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 05 Feb 2012 14:09:46 +0000 |
parents | efd515ace6bb |
children | 4919fb357a5d |
comparison
equal
deleted
inserted
replaced
4437:3a1507f48686 | 4438:2840ff6b97bd |
---|---|
76 ngx_http_ssi_ctx_t *ctx); | 76 ngx_http_ssi_ctx_t *ctx); |
77 static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r, | 77 static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r, |
78 ngx_str_t *name, ngx_uint_t key); | 78 ngx_str_t *name, ngx_uint_t key); |
79 static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, | 79 static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, |
80 ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags); | 80 ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags); |
81 static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r, | |
82 ngx_str_t *pattern, ngx_str_t *str); | |
81 | 83 |
82 static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, | 84 static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r, |
83 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); | 85 ngx_http_ssi_ctx_t *ctx, ngx_str_t **params); |
84 static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, | 86 static ngx_int_t ngx_http_ssi_stub_output(ngx_http_request_t *r, void *data, |
85 ngx_int_t rc); | 87 ngx_int_t rc); |
622 } | 624 } |
623 | 625 |
624 continue; | 626 continue; |
625 } | 627 } |
626 | 628 |
627 if (cmd->conditional | |
628 && (ctx->conditional == 0 | |
629 || ctx->conditional > cmd->conditional)) | |
630 { | |
631 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
632 "invalid context of SSI command: \"%V\"", | |
633 &ctx->command); | |
634 goto ssi_error; | |
635 } | |
636 | |
637 if (!ctx->output && !cmd->block) { | 629 if (!ctx->output && !cmd->block) { |
638 | 630 |
639 if (ctx->block) { | 631 if (ctx->block) { |
640 | 632 |
641 /* reconstruct the SSI command text */ | 633 /* reconstruct the SSI command text */ |
707 if (cmd->conditional == 0) { | 699 if (cmd->conditional == 0) { |
708 continue; | 700 continue; |
709 } | 701 } |
710 } | 702 } |
711 | 703 |
704 if (cmd->conditional | |
705 && (ctx->conditional == 0 | |
706 || ctx->conditional > cmd->conditional)) | |
707 { | |
708 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | |
709 "invalid context of SSI command: \"%V\"", | |
710 &ctx->command); | |
711 goto ssi_error; | |
712 } | |
713 | |
712 if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) { | 714 if (ctx->params.nelts > NGX_HTTP_SSI_MAX_PARAMS) { |
713 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 715 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
714 "too many SSI command paramters: \"%V\"", | 716 "too many SSI command paramters: \"%V\"", |
715 &ctx->command); | 717 &ctx->command); |
716 goto ssi_error; | 718 goto ssi_error; |
1528 ngx_list_part_t *part; | 1530 ngx_list_part_t *part; |
1529 ngx_http_ssi_var_t *var; | 1531 ngx_http_ssi_var_t *var; |
1530 ngx_http_ssi_ctx_t *ctx; | 1532 ngx_http_ssi_ctx_t *ctx; |
1531 | 1533 |
1532 ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); | 1534 ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); |
1535 | |
1536 #if (NGX_PCRE) | |
1537 { | |
1538 ngx_str_t *value; | |
1539 | |
1540 if (key >= '0' && key <= '9') { | |
1541 i = key - '0'; | |
1542 | |
1543 if (i < ctx->ncaptures) { | |
1544 value = ngx_palloc(r->pool, sizeof(ngx_str_t)); | |
1545 if (value == NULL) { | |
1546 return NULL; | |
1547 } | |
1548 | |
1549 i *= 2; | |
1550 | |
1551 value->data = ctx->captures_data + ctx->captures[i]; | |
1552 value->len = ctx->captures[i + 1] - ctx->captures[i]; | |
1553 | |
1554 return value; | |
1555 } | |
1556 } | |
1557 } | |
1558 #endif | |
1533 | 1559 |
1534 if (ctx->variables == NULL) { | 1560 if (ctx->variables == NULL) { |
1535 return NULL; | 1561 return NULL; |
1536 } | 1562 } |
1537 | 1563 |
1814 | 1840 |
1815 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, | 1841 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, |
1816 "invalid variable name in \"%V\"", text); | 1842 "invalid variable name in \"%V\"", text); |
1817 | 1843 |
1818 return NGX_HTTP_SSI_ERROR; | 1844 return NGX_HTTP_SSI_ERROR; |
1845 } | |
1846 | |
1847 | |
1848 static ngx_int_t | |
1849 ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern, | |
1850 ngx_str_t *str) | |
1851 { | |
1852 #if (NGX_PCRE) | |
1853 int rc, *captures; | |
1854 u_char *p, errstr[NGX_MAX_CONF_ERRSTR]; | |
1855 size_t size; | |
1856 ngx_int_t key; | |
1857 ngx_str_t *vv, name, value; | |
1858 ngx_uint_t i, n; | |
1859 ngx_http_ssi_ctx_t *ctx; | |
1860 ngx_http_ssi_var_t *var; | |
1861 ngx_regex_compile_t rgc; | |
1862 | |
1863 ngx_memzero(&rgc, sizeof(ngx_regex_compile_t)); | |
1864 | |
1865 rgc.pattern = *pattern; | |
1866 rgc.pool = r->pool; | |
1867 rgc.err.len = NGX_MAX_CONF_ERRSTR; | |
1868 rgc.err.data = errstr; | |
1869 | |
1870 if (ngx_regex_compile(&rgc) != NGX_OK) { | |
1871 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err); | |
1872 return NGX_HTTP_SSI_ERROR; | |
1873 } | |
1874 | |
1875 n = (rgc.captures + 1) * 3; | |
1876 | |
1877 captures = ngx_palloc(r->pool, n * sizeof(int)); | |
1878 if (captures == NULL) { | |
1879 return NGX_ERROR; | |
1880 } | |
1881 | |
1882 rc = ngx_regex_exec(rgc.regex, str, captures, n); | |
1883 | |
1884 if (rc < NGX_REGEX_NO_MATCHED) { | |
1885 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
1886 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", | |
1887 rc, str, pattern); | |
1888 return NGX_HTTP_SSI_ERROR; | |
1889 } | |
1890 | |
1891 if (rc == NGX_REGEX_NO_MATCHED) { | |
1892 return NGX_DECLINED; | |
1893 } | |
1894 | |
1895 ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module); | |
1896 | |
1897 ctx->ncaptures = rc; | |
1898 ctx->captures = captures; | |
1899 ctx->captures_data = str->data; | |
1900 | |
1901 if (rgc.named_captures > 0) { | |
1902 | |
1903 if (ctx->variables == NULL) { | |
1904 ctx->variables = ngx_list_create(r->pool, 4, | |
1905 sizeof(ngx_http_ssi_var_t)); | |
1906 if (ctx->variables == NULL) { | |
1907 return NGX_ERROR; | |
1908 } | |
1909 } | |
1910 | |
1911 size = rgc.name_size; | |
1912 p = rgc.names; | |
1913 | |
1914 for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) { | |
1915 | |
1916 name.data = &p[2]; | |
1917 name.len = ngx_strlen(name.data); | |
1918 | |
1919 n = 2 * ((p[0] << 8) + p[1]); | |
1920 | |
1921 value.data = &str->data[captures[n]]; | |
1922 value.len = captures[n + 1] - captures[n]; | |
1923 | |
1924 key = ngx_hash_strlow(name.data, name.data, name.len); | |
1925 | |
1926 vv = ngx_http_ssi_get_variable(r, &name, key); | |
1927 | |
1928 if (vv) { | |
1929 *vv = value; | |
1930 continue; | |
1931 } | |
1932 | |
1933 var = ngx_list_push(ctx->variables); | |
1934 if (var == NULL) { | |
1935 return NGX_ERROR; | |
1936 } | |
1937 | |
1938 var->name = name; | |
1939 var->key = key; | |
1940 var->value = value; | |
1941 } | |
1942 } | |
1943 | |
1944 return NGX_OK; | |
1945 | |
1946 #else | |
1947 | |
1948 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
1949 "the using of the regex \"%V\" in SSI requires PCRE library", | |
1950 pattern); | |
1951 return NGX_HTTP_SSI_ERROR; | |
1952 | |
1953 #endif | |
1819 } | 1954 } |
1820 | 1955 |
1821 | 1956 |
1822 static ngx_int_t | 1957 static ngx_int_t |
1823 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, | 1958 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, |
2449 } else { | 2584 } else { |
2450 rc = ngx_strncmp(left.data, right.data, right.len); | 2585 rc = ngx_strncmp(left.data, right.data, right.len); |
2451 } | 2586 } |
2452 | 2587 |
2453 } else { | 2588 } else { |
2454 #if (NGX_PCRE) | |
2455 ngx_regex_compile_t rgc; | |
2456 u_char errstr[NGX_MAX_CONF_ERRSTR]; | |
2457 | |
2458 right.data[right.len] = '\0'; | 2589 right.data[right.len] = '\0'; |
2459 | 2590 |
2460 ngx_memzero(&rgc, sizeof(ngx_regex_compile_t)); | 2591 rc = ngx_http_ssi_regex_match(r, &right, &left); |
2461 | 2592 |
2462 rgc.pattern = right; | 2593 if (rc == NGX_OK) { |
2463 rgc.pool = r->pool; | 2594 rc = 0; |
2464 rgc.err.len = NGX_MAX_CONF_ERRSTR; | 2595 } else if (rc == NGX_DECLINED) { |
2465 rgc.err.data = errstr; | 2596 rc = -1; |
2466 | 2597 } else { |
2467 if (ngx_regex_compile(&rgc) != NGX_OK) { | 2598 return rc; |
2468 ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err); | 2599 } |
2469 return NGX_HTTP_SSI_ERROR; | |
2470 } | |
2471 | |
2472 rc = ngx_regex_exec(rgc.regex, &left, NULL, 0); | |
2473 | |
2474 if (rc < NGX_REGEX_NO_MATCHED) { | |
2475 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
2476 ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"", | |
2477 rc, &left, &right); | |
2478 return NGX_HTTP_SSI_ERROR; | |
2479 } | |
2480 #else | |
2481 ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0, | |
2482 "the using of the regex \"%V\" in SSI " | |
2483 "requires PCRE library", &right); | |
2484 | |
2485 return NGX_HTTP_SSI_ERROR; | |
2486 #endif | |
2487 } | 2600 } |
2488 | 2601 |
2489 if ((rc == 0 && !negative) || (rc != 0 && negative)) { | 2602 if ((rc == 0 && !negative) || (rc != 0 && negative)) { |
2490 ctx->output = 1; | 2603 ctx->output = 1; |
2491 ctx->output_chosen = 1; | 2604 ctx->output_chosen = 1; |