]> granicus.if.org Git - apache/commitdiff
More ap_expr updates:
authorStefan Fritsch <sf@apache.org>
Sun, 21 Nov 2010 19:51:41 +0000 (19:51 +0000)
committerStefan Fritsch <sf@apache.org>
Sun, 21 Nov 2010 19:51:41 +0000 (19:51 +0000)
- minor bump for ap_expr_exec_re() introduced in r1037504
- actually commit the changes to allow using backreferences in SetEnvIfExpr
- automatically add the correct entries to the Vary-header if the result of
  an expression evaluation depends on a request header
  (can be turned off by setting the AP_EXPR_FLAGS_DONT_VARY flag)
- set AP_EXPR_FLAGS_DONT_VARY in mod_log_config's conditional logging
- fix various off-by-one errors in req_table_func

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

include/ap_expr.h
include/ap_mmn.h
modules/loggers/mod_log_config.c
modules/metadata/mod_setenvif.c
server/util_expr_eval.c

index 2a275592320da4ede1f68c1c9ef1e7395b99ad75..f71f8817bb0b102e4bbcbbdba721c17b00344576 100644 (file)
@@ -43,27 +43,37 @@ typedef struct {
     const char *filename;
     /** The line number where the expression has been defined (for logging). */
     unsigned int line_number;
-#define AP_EXPR_FLAGS_SSL_EXPR_COMPAT       1
-    /** Flags relevant for the expression */
+    /** Flags relevant for the expression, see AP_EXPR_FLAGS_* */
     unsigned int flags;
     /** The module that is used for loglevel configuration (XXX put into eval_ctx?) */
     int module_index;
 } ap_expr_info_t;
 
+/** Use ssl_expr compatibility mode (changes the meaning of the comparison
+ * operators)
+ */
+#define AP_EXPR_FLAGS_SSL_EXPR_COMPAT       1
+/** If using the simple ap_expr_exec(), don't add siginificant request headers
+ * to the Vary response header
+ */
+#define AP_EXPR_FLAGS_DONT_VARY             2
+
 
 /**
- * Evaluate a parse tree
+ * Evaluate a parse tree, simple interface
  * @param r The current request
  * @param expr The expression to be evaluated
  * @param err Where an error message should be stored
  * @return > 0 if expression evaluates to true, == 0 if false, < 0 on error
  * @note err will be set to NULL on success, or to an error message on error
+ * @note request headers used during evaluation will be added to the Vary:
+ *       response header, unless AP_EXPR_FLAGS_DONT_VARY is set.
  */
 AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *expr,
                              const char **err);
 
 /**
- * Evaluate a parse tree, with regexp backreferences
+ * Evaluate a parse tree, with access to regexp backreference
  * @param r The current request
  * @param expr The expression to be evaluated
  * @param nmatch size of the regex match vector pmatch
@@ -75,6 +85,8 @@ AP_DECLARE(int) ap_expr_exec(request_rec *r, const ap_expr_info_t *expr,
  * @note nmatch/pmatch/source can be used both to make previous matches
  *       available to ap_expr_exec_re and to use ap_expr_exec_re's matches
  *       later on.
+ * @note request headers used during evaluation will be added to the Vary:
+ *       response header, unless AP_EXPR_FLAGS_DONT_VARY is set.
  */
 AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *expr,
                                 apr_size_t nmatch, ap_regmatch_t *pmatch,
@@ -98,8 +110,13 @@ typedef struct {
     ap_regmatch_t *re_pmatch;
     /** size of the vector pointed to by re_pmatch */
     apr_size_t re_nmatch;
-    /** the string corresponding to the re_pmatch*/
+    /** the string corresponding to the re_pmatch */
     const char **re_source;
+    /** A string where the comma separated names of headers are stored
+     * to be later added to the Vary: header. If NULL, the caller is not
+     * interested in this information.
+     */
+    const char **vary_this;
 } ap_expr_eval_ctx;
 
 
index 3f7d3d566c85263ae858b7729592b0991699b8a7..38d57b2bf08ce5964f39e7dcccd991e15a7ed266 100644 (file)
  * 20101106.2 (2.3.9-dev)  Add suexec_disabled_reason field to ap_unixd_config
  * 20101113.0 (2.3.9-dev)  Add source address to mod_proxy.h
  * 20101113.1 (2.3.9-dev)  Add ap_set_flag_slot_char()
+ * 20101113.2 (2.3.9-dev)  Add ap_expr_exec_re()
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20101113
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 1                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 2                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 12fce8cfeefbfdd1af8300ab6211708e32639370..38efc7bbce2e2e020a24808a15c2aabeefcee20b 100644 (file)
@@ -1257,6 +1257,7 @@ static const char *add_custom_log(cmd_parms *cmd, void *dummy, const char *fn,
             if (err)
                 return err;
             cls->condition_expr->module_index = APLOG_MODULE_INDEX;
+            cls->condition_expr->flags |= AP_EXPR_FLAGS_DONT_VARY;
         }
         else {
             return "error in condition clause";
index 3357963fc9a2fa049bfecd676f34fc8081b79446..aa8db0b40caab64ac952ba9e3410eb6abffa9336 100644 (file)
@@ -651,7 +651,8 @@ static int match_headers(request_rec *r)
 
         if ((b->pattern && apr_strmatch(b->pattern, val, val_len)) ||
             (b->preg && !ap_regexec(b->preg, val, AP_MAX_REG_MATCH, regm, 0)) ||
-            (b->expr && (ap_expr_exec(r, b->expr, &err) > 0))) {
+            (b->expr && ap_expr_exec_re(r, b->expr, AP_MAX_REG_MATCH, regm, &val, &err) > 0))
+        {
             const apr_array_header_t *arr = apr_table_elts(b->features);
             elts = (const apr_table_entry_t *) arr->elts;
 
@@ -660,7 +661,7 @@ static int match_headers(request_rec *r)
                     apr_table_unset(r->subprocess_env, elts[j].key);
                 }
                 else {
-                    if (b->preg) {
+                    if (!b->pattern) {
                         char *replaced = ap_pregsub(r->pool, elts[j].val, val,
                                                     AP_MAX_REG_MATCH, regm);
                         if (replaced) {
index 8e293e0498ba59d7f6151895ccc63918cd654976..9ab4160615ec2aeaf512410efd039c1daf677fac 100644 (file)
@@ -742,6 +742,8 @@ AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
 {
     ap_expr_eval_ctx ctx;
     int rc;
+    int dont_vary = (info->flags & AP_EXPR_FLAGS_DONT_VARY);
+    const char *vary_this = NULL;
     ctx.r = r;
     ctx.c = r->connection;
     ctx.s = r->server;
@@ -751,6 +753,7 @@ AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
     ctx.re_nmatch = nmatch;
     ctx.re_pmatch = pmatch;
     ctx.re_source = source;
+    ctx.vary_this = dont_vary ? NULL : &vary_this;
     ap_regmatch_t tmp_pmatch[10];
     const char *tmp_source;
 
@@ -777,10 +780,28 @@ AP_DECLARE(int) ap_expr_exec_re(request_rec *r, const ap_expr_info_t *info,
         ap_log_rerror(__FILE__, __LINE__, info->module_index, APLOG_TRACE4, 0,
                       r, "Evaluation of expression from %s:%d gave: %d",
                       info->filename, info->line_number, rc);
+
+        if (vary_this)
+            apr_table_merge(r->headers_out, "Vary", vary_this);
+
         return rc;
     }
 }
 
+static void add_vary(ap_expr_eval_ctx *ctx, const char *name)
+{
+    if (!ctx->vary_this)
+        return;
+
+    if (*ctx->vary_this) {
+        *ctx->vary_this = apr_pstrcat(ctx->p, *ctx->vary_this, ", ", name,
+                                      NULL);
+    }
+    else {
+        *ctx->vary_this = name;
+    }
+}
+
 static const char *req_table_func(ap_expr_eval_ctx *ctx, const void *data,
                                   const char *arg)
 {
@@ -789,14 +810,16 @@ static const char *req_table_func(ap_expr_eval_ctx *ctx, const void *data,
     if (!ctx->r)
         return "";
 
-    if (name[3] == 's')             /* resp */
+    if (name[2] == 's')             /* resp */
         t = ctx->r->headers_out;
-    else if (name[4] == 'e')        /* reqenv */
-        t = ctx->r->subprocess_env;
     else if (name[0] == 'n')        /* notes */
         t = ctx->r->notes;
-    else
+    else if (name[3] == 'e')        /* reqenv */
+        t = ctx->r->subprocess_env;
+    else {                          /* req, http */
         t = ctx->r->headers_in;
+        add_vary(ctx, arg);
+    }
     return apr_table_get(t, arg);
 }
 
@@ -1042,8 +1065,8 @@ static const char *request_var_fn(ap_expr_eval_ctx *ctx, const void *data)
 }
 
 static const char *req_header_var_names[] = {
-    "HTTP_USER_AGENT",          /* 0 */
-    "HTTP_PROXY_CONNECTION",    /* 1 */
+    "HTTP_USER_AGENT",
+    "HTTP_PROXY_CONNECTION",
     "HTTP_REFERER",
     "HTTP_COOKIE",
     "HTTP_FORWARDED",
@@ -1052,22 +1075,29 @@ static const char *req_header_var_names[] = {
     NULL
 };
 
+static const char *req_header_header_names[] = {
+    "User-Agent",
+    "Proxy-Connection",
+    "Referer",
+    "Cookie",
+    "Forwarded",
+    "Host",
+    "Accept"
+};
+
 static const char *req_header_var_fn(ap_expr_eval_ctx *ctx, const void *data)
 {
-    const char **name = (const char **)data;
-    int index = (name - req_header_var_names);
+    const char **varname = (const char **)data;
+    int index = (varname - req_header_var_names);
+    const char *name;
+
+    AP_DEBUG_ASSERT(index < 6);
     if (!ctx->r)
         return "";
 
-    switch (index) {
-    case 0:
-        return apr_table_get(ctx->r->headers_in, "User-Agent");
-    case 1:
-        return apr_table_get(ctx->r->headers_in, "Proxy-Connection");
-    default:
-        /* apr_table_get is case insensitive, just skip leading "HTTP_" */
-        return apr_table_get(ctx->r->headers_in, *name + 5);
-    }
+    name = req_header_header_names[index];
+    add_vary(ctx, name);
+    return apr_table_get(ctx->r->headers_in, name);
 }
 
 static const char *misc_var_names[] = {
@@ -1147,6 +1177,7 @@ static const struct expr_provider_single string_func_providers[] = {
     /* 'http' as alias for 'req' for compatibility with ssl_expr */
     { req_table_func, "http" },
     { req_table_func, "note" },
+    { req_table_func, "reqenv" },
     { tolower_func, "tolower" },
     { toupper_func, "toupper" },
     { escape_func, "escape" },