]> granicus.if.org Git - apache/commitdiff
Allow to use arbitrary boolean expressions (ap_expr) in RewriteCond.
authorStefan Fritsch <sf@apache.org>
Wed, 29 Dec 2010 21:48:35 +0000 (21:48 +0000)
committerStefan Fritsch <sf@apache.org>
Wed, 29 Dec 2010 21:48:35 +0000 (21:48 +0000)
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1053750 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
docs/manual/mod/mod_rewrite.xml
modules/mappers/mod_rewrite.c

diff --git a/CHANGES b/CHANGES
index 9f1e631b430c90d7a68351b0c6a86adfd4bf7939..e6099e76f97bc2adb21efac59c889855ae26dc50 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -2,6 +2,9 @@
 
 Changes with Apache 2.3.11
 
+  *) mod_rewrite: Allow to use arbitrary boolean expressions (ap_expr) in
+     RewriteCond. [Stefan Fritsch]
+
   *) mod_rewrite: Allow to unset environment variables using E=!VAR.
      PR 49512. [Mark Drayton <mark markdrayton info>, Stefan Fritsch]
 
index d219cda527f664597ca369c1d0b24e5f0e01647a..ba0060a4c615935a4e3a31ee12465c43961f1de6 100644 (file)
@@ -503,6 +503,10 @@ RewriteRule ^index\.html$  newsite.html
         </li>
       </ul>
 
+      <p>If the <em>TestString</em> has the special value <code>expr</code>, the
+      <em>CondPattern</em> will be treated as a
+      <a href="../expr.html">ap_expr</a>.</p>
+
       <p>Other things you should be aware of:</p>
 
       <ol>
@@ -756,6 +760,12 @@ RewriteRule ^index\.html$  newsite.html
 </note>
         </li>
 
+       <li>
+           <p>If the <em>TestString</em> has the special value <code>expr</code>, the
+           <em>CondPattern</em> will be treated as a
+           <a href="../expr.html">ap_expr</a>.</p>
+        </li>
+
         <li>You can also set special flags for
       <em>CondPattern</em> by appending
         <strong><code>[</code><em>flags</em><code>]</code></strong>
index 9a784e1ceff5dccd089ee1ba9b87a3afd4124267..1b38a6c1487bde5d9dd930f6e5e1dd915b4d92a0 100644 (file)
@@ -99,6 +99,7 @@
 #include "mod_ssl.h"
 
 #include "mod_rewrite.h"
+#include "ap_expr.h"
 
 static ap_dbd_t *(*dbd_acquire)(request_rec*) = NULL;
 static void (*dbd_prepare)(server_rec*, const char*, const char*) = NULL;
@@ -272,16 +273,18 @@ typedef enum {
     CONDPAT_INT_LE,
     CONDPAT_INT_EQ,
     CONDPAT_INT_GT,
-    CONDPAT_INT_GE
+    CONDPAT_INT_GE,
+    CONDPAT_AP_EXPR
 } pattern_type;
 
 typedef struct {
-    char        *input;   /* Input string of RewriteCond   */
-    char        *pattern; /* the RegExp pattern string     */
-    ap_regex_t  *regexp;  /* the precompiled regexp        */
-    int          flags;   /* Flags which control the match */
-    pattern_type ptype;   /* pattern type                  */
-    int          pskip;   /* back-index to display pattern */
+    char           *input;   /* Input string of RewriteCond   */
+    char           *pattern; /* the RegExp pattern string     */
+    ap_regex_t     *regexp;  /* the precompiled regexp        */
+    ap_expr_info_t *expr;    /* the compiled ap_expr          */
+    int             flags;   /* Flags which control the match */
+    pattern_type    ptype;   /* pattern type                  */
+    int             pskip;   /* back-index to display pattern */
 } rewritecond_entry;
 
 /* single linked list for env vars and cookies */
@@ -3234,7 +3237,10 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
 
     /* determine the pattern type */
     newcond->ptype = CONDPAT_REGEX;
-    if (*a2 && a2[1]) {
+    if (strcasecmp(a1, "expr") == 0) {
+        newcond->ptype = CONDPAT_AP_EXPR;
+    }
+    else if (*a2 && a2[1]) {
         if (!a2[2] && *a2 == '-') {
             switch (a2[1]) {
             case 'f': newcond->ptype = CONDPAT_FILE_EXISTS; break;
@@ -3313,6 +3319,15 @@ static const char *cmd_rewritecond(cmd_parms *cmd, void *in_dconf,
 
         newcond->regexp  = regexp;
     }
+    else if (newcond->ptype == CONDPAT_AP_EXPR) {
+        newcond->expr = ap_expr_parse_cmd(cmd, a2, &err, NULL);
+        if (err)
+            return apr_psprintf(cmd->pool, "RewriteCond: cannot compile "
+                                "expression \"%s\": %s", a2, err);
+        newcond->expr->module_index = rewrite_module.module_index;
+        if (newcond->flags & CONDFLAG_NOVARY)
+            newcond->expr->flags |= AP_EXPR_FLAGS_DONT_VARY;
+    }
 
     return NULL;
 }
@@ -3679,13 +3694,16 @@ static APR_INLINE int compare_lexicography(char *a, char *b)
  */
 static int apply_rewrite_cond(rewritecond_entry *p, rewrite_ctx *ctx)
 {
-    char *input = do_expand(p->input, ctx, NULL);
+    char *input;
     apr_finfo_t sb;
     request_rec *rsub, *r = ctx->r;
     ap_regmatch_t regmatch[AP_MAX_REG_MATCH];
     int rc = 0;
     int basis;
 
+    if (p->ptype != CONDPAT_AP_EXPR)
+        input = do_expand(p->input, ctx, NULL);
+
     switch (p->ptype) {
     case CONDPAT_FILE_EXISTS:
         if (   apr_stat(&sb, input, APR_FINFO_MIN, r->pool) == APR_SUCCESS
@@ -3799,6 +3817,24 @@ test_str_l:
 
     case CONDPAT_INT_EQ: rc = (atoi(input) == atoi(p->pattern)); break;
 
+    case CONDPAT_AP_EXPR:
+        {
+            const char *err, *source;
+            rc = ap_expr_exec_re(r, p->expr, AP_MAX_REG_MATCH, regmatch,
+                                 &source, &err);
+            if (rc < 0 || err) {
+                rewritelog((r, 1, ctx->perdir,
+                            "RewriteCond: expr='%s' evaluation failed: %s",
+                            p->pattern - p->pskip, err));
+                rc = 0;
+            }
+            /* update briRC backref info */
+            if (rc && !(p->flags & CONDFLAG_NOTMATCH)) {
+                ctx->briRC.source = source;
+                memcpy(ctx->briRC.regmatch, regmatch, sizeof(regmatch));
+            }
+        }
+        break;
     default:
         /* it is really a regexp pattern, so apply it */
         rc = !ap_regexec(p->regexp, input, AP_MAX_REG_MATCH, regmatch, 0);