util_expr_eval.c revision d95a7ac0fe7a06495c3aab5d684b4174f9ab282c
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke/* Licensed to the Apache Software Foundation (ASF) under one or more
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * contributor license agreements. See the NOTICE file distributed with
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * this work for additional information regarding copyright ownership.
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * The ASF licenses this file to You under the Apache License, Version 2.0
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * (the "License"); you may not use this file except in compliance with
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * the License. You may obtain a copy of the License at
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke * Unless required by applicable law or agreed to in writing, software
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * distributed under the License is distributed on an "AS IS" BASIS,
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke * See the License for the specific language governing permissions and
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke * limitations under the License.
2af38fde95f93562f2124ec615fba0e509c8202eDominik Luecke * ap_expr_eval.c, based on ssl_expr_eval.c from mod_ssl
59917a4f0a6a20f5a20bcab1f2a0a0774db56807Dominik Luecke/* we know core's module_index is 0 */
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke#define APLOG_MODULE_INDEX AP_CORE_MODULE_INDEX
08056875f5f633ef432598d5245ea41c112d2178Dominik LueckeAP_IMPLEMENT_HOOK_RUN_FIRST(int, expr_lookup, (ap_expr_lookup_parms *parms),
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke#define LOG_MARK(info) __FILE__, __LINE__, (info)->module_index
ad270004874ce1d0697fb30d7309f180553bb315Christian Maederstatic const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
08056875f5f633ef432598d5245ea41c112d2178Dominik Lueckestatic const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx, int n);
08056875f5f633ef432598d5245ea41c112d2178Dominik Lueckestatic const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke const void *data);
f90884915ff10ae83f59e709c68824de834e64f5Dominik Luecke/* define AP_EXPR_DEBUG to log the parse tree when parsing an expression */
f90884915ff10ae83f59e709c68824de834e64f5Dominik Lueckestatic void expr_dump_tree(const ap_expr_t *e, const server_rec *s,
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Lueckestatic const char *ap_expr_eval_word(ap_expr_eval_ctx_t *ctx,
b72a390042c19e630cf221494b60c9df2a60d187Dominik Luecke result = ap_expr_eval_var(ctx, node->node_arg1, node->node_arg2);
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke const char *s1 = ap_expr_eval_word(ctx, node->node_arg1);
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke const char *s2 = ap_expr_eval_word(ctx, node->node_arg2);
548f3850942936a8c6021185c8391dfcd3b03018Dominik Luecke result = ap_expr_eval_string_func(ctx, info, args);
08056875f5f633ef432598d5245ea41c112d2178Dominik Luecke *ctx->err = "Internal evaluation error: Unknown word expression node";
548f3850942936a8c6021185c8391dfcd3b03018Dominik Lueckestatic const char *ap_expr_eval_var(ap_expr_eval_ctx_t *ctx,
08056875f5f633ef432598d5245ea41c112d2178Dominik Lueckestatic const char *ap_expr_eval_re_backref(ap_expr_eval_ctx_t *ctx, int n)
fcac596b16bb10f475066c323b9b1ca44db2b755Dominik Luecke if (!ctx->re_pmatch || !ctx->re_source || *ctx->re_source == '\0' ||
4df63f7187b1ba16cbe5c781db187a42f2f49579Dominik Luecke len = ctx->re_pmatch[n].rm_eo - ctx->re_pmatch[n].rm_so;
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke return apr_pstrndup(ctx->p, *ctx->re_source + ctx->re_pmatch[n].rm_so, len);
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Lueckestatic const char *ap_expr_eval_string_func(ap_expr_eval_ctx_t *ctx,
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke ap_expr_string_func_t *func = (ap_expr_string_func_t *)info->node_arg1;
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke AP_DEBUG_ASSERT(info->node_op == op_StringFuncInfo);
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Luecke return (*func)(ctx, data, ap_expr_eval_word(ctx, arg));
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Lueckestatic int intstrcmp(const char *s1, const char *s2)
5b9f5c1b3592b99fc74d3438740ebcf9eb4c94beDominik Lueckestatic int ap_expr_eval_comp(ap_expr_eval_ctx_t *ctx, const ap_expr_t *node)
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) < 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) > 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (intstrcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) == 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) != 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) < 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) <= 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) > 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke return (strcmp(ap_expr_eval_word(ctx, e1), ap_expr_eval_word(ctx, e2)) >= 0);
2ea0ce749d2525f96d5d2f285f519ab07b005b8dDominik Luecke const char *needle = ap_expr_eval_word(ctx, e1);
case op_REG:
case op_NRE: {
int result;
return result;
return !result;
for (i = 0; i < n1; i++) {
case op_EQ:
case op_STR_EQ:
case op_NE:
case op_STR_NE:
case op_LT:
case op_STR_LT:
case op_LE:
case op_STR_LE:
case op_GT:
case op_STR_GT:
case op_GE:
case op_STR_GE:
int rc;
#ifdef AP_EXPR_DEBUG
return NULL;
const char *expr,
unsigned int flags,
const char **err,
int module_index)
if (*err)
return NULL;
return info;
return node;
return NULL;
return info;
if (!info)
return NULL;
if (!info)
return NULL;
if (!info)
return NULL;
arg2);
if (!info)
return NULL;
if (!node)
return NULL;
return node;
#ifdef AP_EXPR_DEBUG
switch (e->node_op) {
case op_NOP:
case op_True:
case op_False:
char *name;
switch (e->node_op) {
ap_assert(0);
case op_UnaryOpCall:
case op_BinaryOpCall:
case op_BinaryOpArgs:
char *name;
switch (e->node_op) {
ap_assert(0);
case op_Comp:
case op_Not:
case op_Or:
case op_And:
case op_EQ:
case op_NE:
case op_LT:
case op_LE:
case op_GT:
case op_GE:
case op_STR_EQ:
case op_STR_NE:
case op_STR_LT:
case op_STR_LE:
case op_STR_GT:
case op_STR_GE:
case op_IN:
case op_REG:
case op_NRE:
case op_Concat:
case op_StringFuncCall:
case op_ListFuncCall:
case op_ListElement:
char *name;
switch (e->node_op) {
ap_assert(0);
case op_Digit:
case op_String:
char *name;
switch (e->node_op) {
ap_assert(0);
case op_Var:
case op_StringFuncInfo:
case op_UnaryOpInfo:
case op_BinaryOpInfo:
case op_ListFuncInfo:
char *name;
switch (e->node_op) {
ap_assert(0);
case op_Regex:
case op_RegexBackref:
case op_True:
case op_False:
case op_Not:
case op_Or:
case op_And:
case op_UnaryOpCall:
case op_BinaryOpCall:
case op_Comp:
return FALSE;
const char **err)
int rc;
return rc;
ctx.r = r;
if (!pmatch) {
const char **source,
const char **err)
const char *result;
ctx.r = r;
if (!pmatch) {
if (rc > 0)
return result;
else if (rc < 0)
return NULL;
ap_assert(0);
const char **err)
NULL);
const char *arg)
apr_table_t *t;
if (!ctx->r)
const char *arg)
const char *res;
if (ctx->r) {
return res;
return res;
const char *arg)
const char *arg)
return result;
const char *arg)
return result;
const char *arg)
char *arg)
char *buf;
if (len == 0) {
offset = 0;
return buf;
char *arg)
const char *arg)
return result;
return FALSE;
switch (name[0]) {
return TRUE;
ap_assert(0);
return FALSE;
#if !defined(OS2)
return TRUE;
return FALSE;
return TRUE;
return FALSE;
return FALSE;
return FALSE;
return rc;
return FALSE;
return rc;
static const char *conn_var_names[] = {
switch (index) {
return c->remote_ip;
#if APR_HAVE_IPV6
return c->log_id;
ap_assert(0);
return NULL;
static const char *request_var_names[] = {
switch (index) {
return r->method;
return ap_http_scheme(r);
return r->uri;
return r->filename;
return ap_get_remote_logname(r);
return r->user;
return ap_get_server_name(r);
return r->protocol;
return r->filename;
return r->path_info;
return r->args;
return ap_document_root(r);
return r->ap_auth_type;
return r->the_request;
return r->content_type;
return r->handler;
return r->log_id;
return result;
return result;
return r->uri;
return ap_context_prefix(r);
return ap_context_document_root(r);
ap_assert(0);
return NULL;
static const char *req_header_var_names[] = {
static const char *req_header_header_names[] = {
const char *name;
if (!ctx->r)
static const char *misc_var_names[] = {
switch (index) {
return ap_get_server_banner();
ap_assert(0);
return NULL;
const char *mask;
return !OK;
if (mask) {
mask++;
return !OK;
return OK;
const char *arg2)
return FALSE;
if (!ctx->c)
return FALSE;
switch (arg[0]) {
return FALSE;
return TRUE;
struct expr_provider_single {
const void *func;
const char *name;
int restricted;
struct expr_provider_multi {
const void *func;
const char **names;
case AP_EXPR_FUNC_VAR: {
while (*name) {
return OK;
name++;
prov++;
case AP_EXPR_FUNC_STRING:
case AP_EXPR_FUNC_OP_UNARY:
case AP_EXPR_FUNC_OP_BINARY: {
case AP_EXPR_FUNC_STRING:
case AP_EXPR_FUNC_OP_UNARY:
case AP_EXPR_FUNC_OP_BINARY:
ap_assert(0);
return !OK;
return OK;
prov++;
return DECLINED;
const char *type;
case AP_EXPR_FUNC_VAR:
case AP_EXPR_FUNC_STRING:
case AP_EXPR_FUNC_LIST:
case AP_EXPR_FUNC_OP_UNARY:
case AP_EXPR_FUNC_OP_BINARY:
return !OK;
return !OK;
return OK;