diff src/http/modules/ngx_http_ssi_filter_module.c @ 178:87699398f955 NGINX_0_3_36

nginx 0.3.36 *) Feature: the ngx_http_addition_filter_module. *) Feature: the "proxy_pass" and "fastcgi_pass" directives may be used inside the "if" block. *) Feature: the "proxy_ignore_client_abort" and "fastcgi_ignore_client_abort" directives. *) Feature: the "$request_completion" variable. *) Feature: the ngx_http_perl_module supports the $r->request_method and $r->remote_addr. *) Feature: the ngx_http_ssi_module supports the "elif" command. *) Bugfix: the "\/" string in the expression of the "if" command of the ngx_http_ssi_module was treated incorrectly. *) Bugfix: in the regular expressions in the "if" command of the ngx_http_ssi_module. *) Bugfix: if the relative path was specified in the "client_body_temp_path", "proxy_temp_path", "fastcgi_temp_path", and "perl_modules" directives, then the directory was used relatively to a current path but not to a server prefix.
author Igor Sysoev <http://sysoev.ru>
date Wed, 05 Apr 2006 00:00:00 +0400
parents 73e8476f9142
children 71ff1e2b484a
line wrap: on
line diff
--- a/src/http/modules/ngx_http_ssi_filter_module.c
+++ b/src/http/modules/ngx_http_ssi_filter_module.c
@@ -13,6 +13,7 @@
 #define NGX_HTTP_SSI_DATE_LEN       2048
 
 #define NGX_HTTP_SSI_ADD_PREFIX     1
+#define NGX_HTTP_SSI_ADD_ZERO       2
 
 
 typedef struct {
@@ -247,8 +248,12 @@ static ngx_http_ssi_command_t  ngx_http_
     { ngx_string("set"), ngx_http_ssi_set, ngx_http_ssi_set_params, 0, 0 },
 
     { ngx_string("if"), ngx_http_ssi_if, ngx_http_ssi_if_params, 0, 0 },
-    { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params, 1, 0 },
-    { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params, 1, 0 },
+    { ngx_string("elif"), ngx_http_ssi_if, ngx_http_ssi_if_params,
+                       NGX_HTTP_SSI_COND_IF, 0 },
+    { ngx_string("else"), ngx_http_ssi_else, ngx_http_ssi_no_params,
+                       NGX_HTTP_SSI_COND_IF, 0 },
+    { ngx_string("endif"), ngx_http_ssi_endif, ngx_http_ssi_no_params,
+                       NGX_HTTP_SSI_COND_ELSE, 0 },
 
     { ngx_null_string, NULL, NULL, 0, 0 }
 };
@@ -523,7 +528,17 @@ ngx_http_ssi_body_filter(ngx_http_reques
                     continue;
                 }
 
-                if (!ctx->output && !cmd->conditional) {
+                if (cmd->conditional
+                    && (ctx->conditional == 0
+                        || ctx->conditional > cmd->conditional))
+                {
+                    ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                                  "invalid context of SSI command: \"%V\"",
+                                  &ctx->command);
+                    goto ssi_error;
+                }
+
+                if (!ctx->output && cmd->conditional == 0) {
                     continue;
                 }
 
@@ -926,6 +941,7 @@ ngx_http_ssi_parse(ngx_http_request_t *r
                 ctx->key = ngx_hash(ctx->key, ch);
 
                 ctx->params.nelts = 0;
+
                 state = ssi_command_state;
                 break;
             }
@@ -1565,7 +1581,7 @@ ngx_http_ssi_evaluate_string(ngx_http_re
         }
     }
 
-    p = ngx_palloc(r->pool, len);
+    p = ngx_palloc(r->pool, len + ((flags & NGX_HTTP_SSI_ADD_ZERO) ? 1 : 0));
     if (p == NULL) {
         return NGX_ERROR;
     }
@@ -1809,13 +1825,26 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
     u_char       *p, *last;
     ngx_str_t    *expr, left, right;
     ngx_int_t     rc;
-    ngx_uint_t    negative, noregex;
+    ngx_uint_t    negative, noregex, flags;
 #if (NGX_PCRE)
     ngx_str_t     err;
     ngx_regex_t  *regex;
     u_char        errstr[NGX_MAX_CONF_ERRSTR];
 #endif
 
+    if (ctx->command.len == 2) {
+        if (ctx->conditional) {
+            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+                          "the \"if\" command inside the \"if\" command");
+            return NGX_HTTP_SSI_ERROR;
+        }
+    }
+
+    if (ctx->output_chosen) {
+        ctx->output = 0;
+        return NGX_OK;
+    }
+
     expr = params[NGX_HTTP_SSI_IF_EXPR];
 
     left.data = expr->data;
@@ -1857,11 +1886,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
     if (p == last) {
         if (left.len) {
             ctx->output = 1;
+            ctx->output_chosen = 1;
 
         } else {
             ctx->output = 0;
         }
 
+        ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
         return NGX_OK;
     }
 
@@ -1887,11 +1919,17 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
         }
 
         noregex = 0;
+        flags = NGX_HTTP_SSI_ADD_ZERO;
         last--;
 	p++;
 
     } else {
         noregex = 1;
+        flags = 0;
+
+        if (p < last - 1 && p[0] == '\\' && p[1] == '/') {
+	    p++;
+        }
     }
 
     right.len = last - p;
@@ -1900,7 +1938,7 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "right: \"%V\"", &right);
 
-    if (ngx_http_ssi_evaluate_string(r, ctx, &right, 0) != NGX_OK) {
+    if (ngx_http_ssi_evaluate_string(r, ctx, &right, flags) != NGX_OK) {
         return NGX_HTTP_SSI_ERROR;
     }
 
@@ -1948,11 +1986,14 @@ ngx_http_ssi_if(ngx_http_request_t *r, n
 
     if ((rc == 0 && !negative) || (rc != 0 && negative)) {
         ctx->output = 1;
+        ctx->output_chosen = 1;
 
     } else {
         ctx->output = 0;
     }
 
+    ctx->conditional = NGX_HTTP_SSI_COND_IF;
+
     return NGX_OK;
 
 invalid_expression:
@@ -1968,7 +2009,13 @@ static ngx_int_t
 ngx_http_ssi_else(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
-    ctx->output = !ctx->output;
+    if (ctx->output_chosen) {
+        ctx->output = 0;
+    } else {
+        ctx->output = 1;
+    }
+
+    ctx->conditional = NGX_HTTP_SSI_COND_ELSE;
 
     return NGX_OK;
 }
@@ -1979,6 +2026,8 @@ ngx_http_ssi_endif(ngx_http_request_t *r
     ngx_str_t **params)
 {
     ctx->output = 1;
+    ctx->output_chosen = 0;
+    ctx->conditional = 0;
 
     return NGX_OK;
 }