summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Fritsch <sf@apache.org>2010-12-29 22:48:35 +0100
committerStefan Fritsch <sf@apache.org>2010-12-29 22:48:35 +0100
commit95216d39186a3de764c740a7b2069d363f96f0e1 (patch)
tree3a966017d69b845093002c7dd9b1b103f0324ca5
parentin struct backrefinfo: remove nsub member which is never read, (diff)
downloadapache2-95216d39186a3de764c740a7b2069d363f96f0e1.tar.xz
apache2-95216d39186a3de764c740a7b2069d363f96f0e1.zip
Allow to use arbitrary boolean expressions (ap_expr) in RewriteCond.
git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1053750 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--CHANGES3
-rw-r--r--docs/manual/mod/mod_rewrite.xml10
-rw-r--r--modules/mappers/mod_rewrite.c54
3 files changed, 58 insertions, 9 deletions
diff --git a/CHANGES b/CHANGES
index 9f1e631b43..e6099e76f9 100644
--- 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]
diff --git a/docs/manual/mod/mod_rewrite.xml b/docs/manual/mod/mod_rewrite.xml
index d219cda527..ba0060a4c6 100644
--- a/docs/manual/mod/mod_rewrite.xml
+++ b/docs/manual/mod/mod_rewrite.xml
@@ -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>
diff --git a/modules/mappers/mod_rewrite.c b/modules/mappers/mod_rewrite.c
index 9a784e1cef..1b38a6c148 100644
--- a/modules/mappers/mod_rewrite.c
+++ b/modules/mappers/mod_rewrite.c
@@ -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);