]> granicus.if.org Git - apache/commitdiff
Merge r1661448 from trunk:
authorJim Jagielski <jim@apache.org>
Tue, 31 Mar 2015 12:49:45 +0000 (12:49 +0000)
committerJim Jagielski <jim@apache.org>
Tue, 31 Mar 2015 12:49:45 +0000 (12:49 +0000)
core: Add expression support to ErrorDocument. Switch from a fixed
sized 664 byte array per merge to a hash table.

Submitted by: minfrin
Reviewed/backported by: jim

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1670320 13f79535-47bb-0310-9956-ffa450edef68

CHANGES
STATUS
docs/manual/expr.xml
docs/manual/mod/core.xml
include/ap_mmn.h
include/http_core.h
server/core.c

diff --git a/CHANGES b/CHANGES
index b213ab2b5601827cdda192e61cdcffdc8969d68b..dacac4c54925f24b00b856f229300bf0ac455db9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -46,6 +46,9 @@ Changes with Apache 2.4.13
      a combination of certificate serialNumber and issuer as defined by
      CertificateExactMatch in RFC4523. [Graham Leggett]
 
+  *) core: Add expression support to ErrorDocument. Switch from a fixed
+     sized 664 byte array per merge to a hash table. [Graham Leggett]
+
   *) ab: Add missing longest request (100%) to CSV export.
      [Marcin Fabrykowski <bugzilla fabrykowski.pl>] 
 
diff --git a/STATUS b/STATUS
index 270db57d171aedd3bc7d9f3226ea75130ed94f05..384b32e89697aa556ab7d936567b893a623cdae2 100644 (file)
--- a/STATUS
+++ b/STATUS
@@ -107,11 +107,6 @@ PATCHES ACCEPTED TO BACKPORT FROM TRUNK:
   [ start all new proposals below, under PATCHES PROPOSED. ]
 
 
-  *) core: Add expression support to ErrorDocument. Switch from a fixed
-     sized 664 byte array per merge to a hash table.
-     trunk patch: http://svn.apache.org/r1661448
-     2.4.x patch: http://people.apache.org/~minfrin/httpd-core-errordocument24-3.patch
-     +1: minfrin, jim, covener
 
 PATCHES PROPOSED TO BACKPORT FROM TRUNK:
   [ New proposals should be added at the end of the list ]
index 67b3d04b6a99592127e1f8723b81c7bca8385edf..eed2f0ac4999ee1adfb0168b3a2d8a6cdebe2951 100644 (file)
@@ -40,6 +40,7 @@
 <seealso><directive module="core" type="section">If</directive></seealso>
 <seealso><directive module="core" type="section">ElseIf</directive></seealso>
 <seealso><directive module="core" type="section">Else</directive></seealso>
+<seealso><directive module="core" type="section">ErrorDocument</directive></seealso>
 <seealso><directive module="mod_alias">Alias</directive></seealso>
 <seealso><directive module="mod_alias">ScriptAlias</directive></seealso>
 <seealso><directive module="mod_alias">Redirect</directive></seealso>
index b901850ccdf0afb8c42e8623686de99f9ce1e57c..5612ed69788c23cea9bd739484160d3b6bf57be1 100644 (file)
@@ -1208,10 +1208,15 @@ in case of an error</description>
     or a message. Apache httpd will sometimes offer additional information
     regarding the problem/error.</p>
 
+    <p>From 2.4.13, <a href="../expr.html">expression syntax</a> can be
+    used inside the directive to produce dynamic strings and URLs.</p>
+
     <p>URLs can begin with a slash (/) for local web-paths (relative
     to the <directive module="core">DocumentRoot</directive>), or be a
     full URL which the client can resolve. Alternatively, a message
-    can be provided to be displayed by the browser. Examples:</p>
+    can be provided to be displayed by the browser. Note that deciding
+    whether the parameter is an URL, a path or a message is performed
+    before any expression is parsed. Examples:</p>
 
     <highlight language="config">
 ErrorDocument 500 http://foo.example.com/cgi-bin/tester
@@ -1219,6 +1224,7 @@ ErrorDocument 404 /cgi-bin/bad_urls.pl
 ErrorDocument 401 /subscription_info.html
 ErrorDocument 403 "Sorry can't allow you access today"
 ErrorDocument 403 Forbidden!
+ErrorDocument 403 /cgi-bin/forbidden.pl?referrer=%{escape:%{HTTP_REFERER}}
     </highlight>
 
     <p>Additionally, the special value <code>default</code> can be used
index ca433d6d4b0f212685bf37693e0e90ba3cfd94a7..a992d3cd31ce70df47462a30abc9066afe61a89d 100644 (file)
  * 20120211.39 (2.4.11-dev) Add ap_proxy_connect_uds().
  * 20120211.40 (2.4.11-dev) Add ap_log_data(), ap_log_rdata(), etc.
  * 20120211.41 (2.4.11-dev) Add ap_proxy_de_socketfy to mod_proxy.h
+ * 20120211.42 (2.4.13-dev) Add response_code_exprs to http_core.h
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
 #define MODULE_MAGIC_NUMBER_MAJOR 20120211
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 41                   /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 42                   /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a
index 5cef6224fc6fa530b728621a5c83c5c2db3c2183..23db3cfce0450bd4127b2f2f71c6f42193873cc1 100644 (file)
@@ -497,12 +497,7 @@ typedef struct {
     overrides_t override;
     allow_options_t override_opts;
 
-    /* Custom response config. These can contain text or a URL to redirect to.
-     * if response_code_strings is NULL then there are none in the config,
-     * if it's not null then it's allocated to sizeof(char*)*RESPONSE_CODES.
-     * This lets us do quick merges in merge_core_dir_configs().
-     */
-
+    /* Used to be the custom response config. No longer used. */
     char **response_code_strings; /* from ErrorDocument, not from
                                    * ap_custom_response() */
 
@@ -617,10 +612,15 @@ typedef struct {
     /** Max number of Range reversals (eg: 200-300, 100-125) allowed **/
     int max_reversals;
 
-
     /** Named back references */
     apr_array_header_t *refs;
 
+    /** Custom response config with expression support. The hash table
+     * contains compiled expressions keyed against the custom response
+     * code.
+     */
+    apr_hash_t *response_code_exprs;
+
 } core_dir_config;
 
 /* macro to implement off by default behaviour */
index e307e92bb243ff35474a095fc08c58377796ba73..749cf5c1661a32f0bf66aaf275393b6b5d0c4e96 100644 (file)
@@ -252,23 +252,14 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
         conf->override_list = new->override_list;
     }
 
-    if (conf->response_code_strings == NULL) {
-        conf->response_code_strings = new->response_code_strings;
+    if (conf->response_code_exprs == NULL) {
+        conf->response_code_exprs = new->response_code_exprs;
     }
-    else if (new->response_code_strings != NULL) {
-        /* If we merge, the merge-result must have its own array
-         */
-        conf->response_code_strings = apr_pmemdup(a,
-            base->response_code_strings,
-            sizeof(*conf->response_code_strings) * RESPONSE_CODES);
-
-        for (i = 0; i < RESPONSE_CODES; ++i) {
-            if (new->response_code_strings[i] != NULL) {
-                conf->response_code_strings[i] = new->response_code_strings[i];
-            }
-        }
+    else if (new->response_code_exprs != NULL) {
+        conf->response_code_exprs = apr_hash_overlay(a,
+                new->response_code_exprs, conf->response_code_exprs);
     }
-    /* Otherwise we simply use the base->response_code_strings array
+    /* Otherwise we simply use the base->response_code_exprs array
      */
 
     if (new->hostname_lookups != HOSTNAME_LOOKUP_UNSET) {
@@ -796,25 +787,46 @@ char *ap_response_code_string(request_rec *r, int error_index)
 {
     core_dir_config *dirconf;
     core_request_config *reqconf = ap_get_core_module_config(r->request_config);
+    const char *err;
+    const char *response;
+    void *val;
+    ap_expr_info_t *expr;
 
     /* check for string registered via ap_custom_response() first */
-    if (reqconf->response_code_strings != NULL &&
-        reqconf->response_code_strings[error_index] != NULL) {
+    if (reqconf->response_code_strings != NULL
+            && reqconf->response_code_strings[error_index] != NULL) {
         return reqconf->response_code_strings[error_index];
     }
 
     /* check for string specified via ErrorDocument */
     dirconf = ap_get_core_module_config(r->per_dir_config);
 
-    if (dirconf->response_code_strings == NULL) {
+    if (!dirconf->response_code_exprs) {
+        return NULL;
+    }
+
+    expr = apr_hash_get(dirconf->response_code_exprs, &error_index,
+            sizeof(error_index));
+    if (!expr) {
         return NULL;
     }
 
-    if (dirconf->response_code_strings[error_index] == &errordocument_default) {
+    /* special token to indicate revert back to default */
+    if ((char *) expr == &errordocument_default) {
         return NULL;
     }
 
-    return dirconf->response_code_strings[error_index];
+    err = NULL;
+    response = ap_expr_str_exec(r, expr, &err);
+    if (err) {
+        ap_log_rerror(
+                APLOG_MARK, APLOG_ERR, 0, r, APLOGNO(02830) "core: ErrorDocument: can't "
+                "evaluate require expression: %s", err);
+        return NULL;
+    }
+
+    /* alas, duplication required as we return not-const */
+    return apr_pstrdup(r->pool, response);
 }
 
 
@@ -1499,27 +1511,43 @@ static const char *set_error_document(cmd_parms *cmd, void *conf_,
                      "directive --- ignoring!", cmd->directive->filename, cmd->directive->line_num);
     }
     else { /* Store it... */
-        if (conf->response_code_strings == NULL) {
-            conf->response_code_strings =
-                apr_pcalloc(cmd->pool,
-                            sizeof(*conf->response_code_strings) *
-                            RESPONSE_CODES);
+        if (conf->response_code_exprs == NULL) {
+            conf->response_code_exprs = apr_hash_make(cmd->pool);
         }
 
         if (strcasecmp(msg, "default") == 0) {
             /* special case: ErrorDocument 404 default restores the
              * canned server error response
              */
-            conf->response_code_strings[index_number] = &errordocument_default;
+            apr_hash_set(conf->response_code_exprs,
+                    apr_pmemdup(cmd->pool, &index_number, sizeof(index_number)),
+                    sizeof(index_number), &errordocument_default);
         }
         else {
+            ap_expr_info_t *expr;
+            const char *expr_err = NULL;
+
             /* hack. Prefix a " if it is a msg; as that is what
              * http_protocol.c relies on to distinguish between
              * a msg and a (local) path.
              */
-            conf->response_code_strings[index_number] = (what == MSG) ?
-                    apr_pstrcat(cmd->pool, "\"", msg, NULL) :
-                    apr_pstrdup(cmd->pool, msg);
+            const char *response =
+                    (what == MSG) ? apr_pstrcat(cmd->pool, "\"", msg, NULL) :
+                            apr_pstrdup(cmd->pool, msg);
+
+            expr = ap_expr_parse_cmd(cmd, response, AP_EXPR_FLAG_STRING_RESULT,
+                    &expr_err, NULL);
+
+            if (expr_err) {
+                return apr_pstrcat(cmd->temp_pool,
+                                   "Cannot parse expression in ErrorDocument: ",
+                                   expr_err, NULL);
+            }
+
+            apr_hash_set(conf->response_code_exprs,
+                    apr_pmemdup(cmd->pool, &index_number, sizeof(index_number)),
+                    sizeof(index_number), expr);
+
         }
     }