From: Nick Kew Date: Tue, 28 Sep 2010 23:26:44 +0000 (+0000) Subject: Add "IN" operator to expression parser, to evaluate membership of X-Git-Tag: 2.3.9~399 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6ed93282a76d06f40baca75425714d682e70ae24;p=thirdparty%2Fapache%2Fhttpd.git Add "IN" operator to expression parser, to evaluate membership of a list of tokens. Couldn't resist after sf's comment on r1002363! This means expressions like will work as a drop-in substitute for 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 --- diff --git a/include/ap_expr.h b/include/ap_expr.h index bc09f2da23b..99f2d1d8835 100644 --- a/include/ap_expr.h +++ b/include/ap_expr.h @@ -45,7 +45,8 @@ typedef enum { TOKEN_LE, TOKEN_GT, TOKEN_LT, - TOKEN_ACCESS + TOKEN_ACCESS, + TOKEN_IN } token_type_t; typedef struct { diff --git a/server/util_expr.c b/server/util_expr.c index 43e289f210f..f15f4df0837 100644 --- a/server/util_expr.c +++ b/server/util_expr.c @@ -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); }