[nginx] svn commit: r4382 - trunk/src/http/modules

vbart at nginx.com vbart at nginx.com
Sun Dec 25 20:08:37 UTC 2011


Author: vbart
Date: 2011-12-25 20:08:37 +0000 (Sun, 25 Dec 2011)
New Revision: 4382

Log:
SSI: added regex captures support in the expression of the "if" command.


Modified:
   trunk/src/http/modules/ngx_http_ssi_filter_module.c
   trunk/src/http/modules/ngx_http_ssi_filter_module.h

Modified: trunk/src/http/modules/ngx_http_ssi_filter_module.c
===================================================================
--- trunk/src/http/modules/ngx_http_ssi_filter_module.c	2011-12-25 19:32:31 UTC (rev 4381)
+++ trunk/src/http/modules/ngx_http_ssi_filter_module.c	2011-12-25 20:08:37 UTC (rev 4382)
@@ -78,6 +78,8 @@
     ngx_str_t *name, ngx_uint_t key);
 static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags);
+static ngx_int_t ngx_http_ssi_regex_match(ngx_http_request_t *r,
+    ngx_str_t *pattern, ngx_str_t *str);
 
 static ngx_int_t ngx_http_ssi_include(ngx_http_request_t *r,
     ngx_http_ssi_ctx_t *ctx, ngx_str_t **params);
@@ -1531,6 +1533,30 @@
 
     ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
 
+#if (NGX_PCRE)
+    {
+    ngx_str_t  *value;
+
+    if (key >= '0' && key <= '9') {
+        i = key - '0';
+
+        if (i < ctx->ncaptures) {
+            value = ngx_palloc(r->pool, sizeof(ngx_str_t));
+            if (value == NULL) {
+                return NULL;
+            }
+
+            i *= 2;
+
+            value->data = ctx->captures_data + ctx->captures[i];
+            value->len = ctx->captures[i + 1] - ctx->captures[i];
+
+            return value;
+        }
+    }
+    }
+#endif
+
     if (ctx->variables == NULL) {
         return NULL;
     }
@@ -1820,6 +1846,115 @@
 
 
 static ngx_int_t
+ngx_http_ssi_regex_match(ngx_http_request_t *r, ngx_str_t *pattern,
+    ngx_str_t *str)
+{
+#if (NGX_PCRE)
+    int                   rc, *captures;
+    u_char               *p, errstr[NGX_MAX_CONF_ERRSTR];
+    size_t                size;
+    ngx_int_t             key;
+    ngx_str_t            *vv, name, value;
+    ngx_uint_t            i, n;
+    ngx_http_ssi_ctx_t   *ctx;
+    ngx_http_ssi_var_t   *var;
+    ngx_regex_compile_t   rgc;
+
+    ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
+
+    rgc.pattern = *pattern;
+    rgc.pool = r->pool;
+    rgc.err.len = NGX_MAX_CONF_ERRSTR;
+    rgc.err.data = errstr;
+
+    if (ngx_regex_compile(&rgc) != NGX_OK) {
+        ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    n = (rgc.captures + 1) * 3;
+
+    captures = ngx_palloc(r->pool, n * sizeof(int));
+    if (captures == NULL) {
+        return NGX_ERROR;
+    }
+
+    rc = ngx_regex_exec(rgc.regex, str, captures, n);
+
+    if (rc < NGX_REGEX_NO_MATCHED) {
+        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                      ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
+                      rc, str, pattern);
+        return NGX_HTTP_SSI_ERROR;
+    }
+
+    if (rc == NGX_REGEX_NO_MATCHED) {
+        return NGX_DECLINED;
+    }
+
+    ctx = ngx_http_get_module_ctx(r->main, ngx_http_ssi_filter_module);
+
+    ctx->ncaptures = rc;
+    ctx->captures = captures;
+    ctx->captures_data = str->data;
+
+    if (rgc.named_captures > 0) {
+
+        if (ctx->variables == NULL) {
+            ctx->variables = ngx_list_create(r->pool, 4,
+                                             sizeof(ngx_http_ssi_var_t));
+            if (ctx->variables == NULL) {
+                return NGX_ERROR;
+            }
+        }
+
+        size = rgc.name_size;
+        p = rgc.names;
+
+        for (i = 0; i < (ngx_uint_t) rgc.named_captures; i++, p += size) {
+
+            name.data = &p[2];
+            name.len = ngx_strlen(name.data);
+
+            n = 2 * ((p[0] << 8) + p[1]);
+
+            value.data = &str->data[captures[n]];
+            value.len = captures[n + 1] - captures[n];
+
+            key = ngx_hash_strlow(name.data, name.data, name.len);
+
+            vv = ngx_http_ssi_get_variable(r, &name, key);
+
+            if (vv) {
+                *vv = value;
+                continue;
+            }
+
+            var = ngx_list_push(ctx->variables);
+            if (var == NULL) {
+                return NGX_ERROR;
+            }
+
+            var->name = name;
+            var->key = key;
+            var->value = value;
+        }
+    }
+
+    return NGX_OK;
+
+#else
+
+    ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
+                  "the using of the regex \"%V\" in SSI requires PCRE library",
+                  pattern);
+    return NGX_HTTP_SSI_ERROR;
+
+#endif
+}
+
+
+static ngx_int_t
 ngx_http_ssi_include(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx,
     ngx_str_t **params)
 {
@@ -2451,39 +2586,17 @@
         }
 
     } else {
-#if (NGX_PCRE)
-        ngx_regex_compile_t  rgc;
-        u_char               errstr[NGX_MAX_CONF_ERRSTR];
-
         right.data[right.len] = '\0';
 
-        ngx_memzero(&rgc, sizeof(ngx_regex_compile_t));
+        rc = ngx_http_ssi_regex_match(r, &right, &left);
 
-        rgc.pattern = right;
-        rgc.pool = r->pool;
-        rgc.err.len = NGX_MAX_CONF_ERRSTR;
-        rgc.err.data = errstr;
-
-        if (ngx_regex_compile(&rgc) != NGX_OK) {
-            ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "%V", &rgc.err);
-            return NGX_HTTP_SSI_ERROR;
+        if (rc == NGX_OK) {
+            rc = 0;
+        } else if (rc == NGX_DECLINED) {
+            rc = -1;
+        } else {
+            return rc;
         }
-
-        rc = ngx_regex_exec(rgc.regex, &left, NULL, 0);
-
-        if (rc < NGX_REGEX_NO_MATCHED) {
-            ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                          ngx_regex_exec_n " failed: %i on \"%V\" using \"%V\"",
-                          rc, &left, &right);
-            return NGX_HTTP_SSI_ERROR;
-        }
-#else
-        ngx_log_error(NGX_LOG_ALERT, r->connection->log, 0,
-                      "the using of the regex \"%V\" in SSI "
-                      "requires PCRE library", &right);
-
-        return NGX_HTTP_SSI_ERROR;
-#endif
     }
 
     if ((rc == 0 && !negative) || (rc != 0 && negative)) {

Modified: trunk/src/http/modules/ngx_http_ssi_filter_module.h
===================================================================
--- trunk/src/http/modules/ngx_http_ssi_filter_module.h	2011-12-25 19:32:31 UTC (rev 4381)
+++ trunk/src/http/modules/ngx_http_ssi_filter_module.h	2011-12-25 20:08:37 UTC (rev 4382)
@@ -64,6 +64,12 @@
     ngx_list_t               *variables;
     ngx_array_t              *blocks;
 
+#if (NGX_PCRE)
+    ngx_uint_t                ncaptures;
+    int                      *captures;
+    u_char                   *captures_data;
+#endif
+
     unsigned                  conditional:2;
     unsigned                  encoding:2;
     unsigned                  block:1;



More information about the nginx-devel mailing list