]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Add "IN" operator to expression parser, to evaluate membership of
authorNick Kew <niq@apache.org>
Tue, 28 Sep 2010 23:26:44 +0000 (23:26 +0000)
committerNick Kew <niq@apache.org>
Tue, 28 Sep 2010 23:26:44 +0000 (23:26 +0000)
a list of tokens.  Couldn't resist after sf's comment on r1002363!

This means expressions like
<If %{REQUEST_METHOD} IN GET,HEAD,OPTIONS,...>
will work as a drop-in substitute for <Limit>

Also fix off-by-one bug in variable evaluation

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1002415 13f79535-47bb-0310-9956-ffa450edef68

include/ap_expr.h
server/util_expr.c

index bc09f2da23be1d7e333f5196bccc9e7b2171f830..99f2d1d883530b0ae6e377a1f79fde95d12bc276 100644 (file)
@@ -45,7 +45,8 @@ typedef enum {
     TOKEN_LE,
     TOKEN_GT,
     TOKEN_LT,
-    TOKEN_ACCESS
+    TOKEN_ACCESS,
+    TOKEN_IN
 } token_type_t;
 
 typedef struct {
index 43e289f210f8f03e64a46d8a19749e35400d6cab..f15f4df08379c876dea2009fbc91bc2dbc40bcbf 100644 (file)
@@ -389,6 +389,13 @@ static int get_ptoken(apr_pool_t *pool, const char **parse, token_t *token,
             return 0;
         }
         break;
+    case 'I':
+        if (**parse == 'N') {
+            TYPE_TOKEN(token, TOKEN_IN);
+            ++*parse;
+            return 0;
+        }
+        break;
     }
 
     /* It's a string or regex token
@@ -604,6 +611,7 @@ AP_DECLARE(ap_parse_node_t*) ap_expr_parse(apr_pool_t* pool, const char *expr,
         case TOKEN_GT:
         case TOKEN_LE:
         case TOKEN_LT:
+        case TOKEN_IN:
             if (current->token.type == TOKEN_STRING) {
                 current = current->parent;
 
@@ -819,6 +827,27 @@ static int expr_eval(request_rec *r, ap_parse_node_t *root,
             default: current->value = 0; break; /* should not happen */
             }
             break;
+        case TOKEN_IN:
+            if (!current->left || !current->right ||
+                current->left->token.type != TOKEN_STRING ||
+                current->right->token.type != TOKEN_STRING) {
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "Invalid expression in file %s", r->filename);
+                *was_error = 1;
+                return 0;
+            }
+
+            lval = PARSE_STRING(r, current->left->token.value);
+            rval = PARSE_STRING(r, current->right->token.value);
+            val = strstr(rval, lval);
+            /* should be included as a complete word, not a subword
+             * as in regexp /\bLVAL\b/
+             */
+            current->value = (val != NULL
+                              && (val == rval || !isalnum(val[-1]))
+                              && !isalnum(val[strlen(val)]))
+                ? 1 : 0;
+            break;
 
         case TOKEN_NOT:
         case TOKEN_GROUP:
@@ -941,7 +970,7 @@ AP_DECLARE_NONSTD(const char*) ap_expr_string(request_rec *r,
         char *ch, *var;
         apr_time_exp_t tm;
 
-        var = apr_pstrndup(r->pool, str+2, p-str-3);
+        var = apr_pstrndup(r->pool, str+2, p-str-2);
         for (ch = var; *ch; ++ch) {
             *ch = apr_toupper(*ch);
         }