You are viewing a plain text version of this content. The canonical link for it is here.
Posted to cvs@httpd.apache.org by sf...@apache.org on 2011/01/17 12:02:38 UTC

svn commit: r1059867 - in /httpd/httpd/trunk: CHANGES include/ap_mmn.h include/http_core.h include/http_request.h server/core.c server/request.c

Author: sf
Date: Mon Jan 17 11:02:38 2011
New Revision: 1059867

URL: http://svn.apache.org/viewvc?rev=1059867&view=rev
Log:
Merge the <If> sections in a separate step ap_if_walk, after ap_location_walk.

This makes <If> apply to all requests, not only to file base requests and
it allows to use <If> inside <Directory>, <Location>, and <Files> sections.

The merging of <If> sections always happens after the merging of <Location>
sections, even if the <If> section is embedded inside a <Directory> or
<Files> section.

Modified:
    httpd/httpd/trunk/CHANGES
    httpd/httpd/trunk/include/ap_mmn.h
    httpd/httpd/trunk/include/http_core.h
    httpd/httpd/trunk/include/http_request.h
    httpd/httpd/trunk/server/core.c
    httpd/httpd/trunk/server/request.c

Modified: httpd/httpd/trunk/CHANGES
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/CHANGES?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/CHANGES [utf-8] (original)
+++ httpd/httpd/trunk/CHANGES [utf-8] Mon Jan 17 11:02:38 2011
@@ -2,6 +2,12 @@
 
 Changes with Apache 2.3.11
 
+  *) core: Apply <If> sections to all requests, not only to file base requests.
+     Allow to use <If> inside <Directory>, <Location>, and <Files> sections.
+     The merging of <If> sections now happens after the merging of <Location>
+     sections, even if an <If> section is embedded inside a <Directory> or
+     <Files> section.  [Stefan Fritsch]
+
   *) mod_proxy: Refactor usage of shared data by dropping the scoreboard
      and using slotmem. Create foundation for dynamic growth/changes of
      members within a balancer. Remove BalancerNonce in favor of a

Modified: httpd/httpd/trunk/include/ap_mmn.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_mmn.h?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/include/ap_mmn.h (original)
+++ httpd/httpd/trunk/include/ap_mmn.h Mon Jan 17 11:02:38 2011
@@ -294,14 +294,16 @@
  *                         info from scoreboard and use slotmem; Allow
  *                         dynamic growth of balancer members; Remove
  *                         BalancerNonce in favor of 'nonce' parameter.
+ * 20110117.0 (2.3.11-dev) Merge <If> sections in separate step (ap_if_walk).
+ *                         Add core_dir_config->sec_if.
  */
 
 #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
 
 #ifndef MODULE_MAGIC_NUMBER_MAJOR
-#define MODULE_MAGIC_NUMBER_MAJOR 20101223
+#define MODULE_MAGIC_NUMBER_MAJOR 20110117
 #endif
-#define MODULE_MAGIC_NUMBER_MINOR 1                     /* 0...n */
+#define MODULE_MAGIC_NUMBER_MINOR 0                     /* 0...n */
 
 /**
  * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

Modified: httpd/httpd/trunk/include/http_core.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/http_core.h?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/include/http_core.h (original)
+++ httpd/httpd/trunk/include/http_core.h Mon Jan 17 11:02:38 2011
@@ -362,7 +362,8 @@ typedef struct {
 #define AP_NOTE_DIRECTORY_WALK 0
 #define AP_NOTE_LOCATION_WALK  1
 #define AP_NOTE_FILE_WALK      2
-#define AP_NUM_STD_NOTES       3
+#define AP_NOTE_IF_WALK        3
+#define AP_NUM_STD_NOTES       4
 
 /**
  * Reserve an element in the core_request_config->notes array
@@ -499,6 +500,7 @@ typedef struct {
 
     /* Access control */
     apr_array_header_t *sec_file;
+    apr_array_header_t *sec_if;
     ap_regex_t *r;
 
     const char *mime_type;       /* forced with ForceType  */
@@ -597,6 +599,7 @@ void ap_core_reorder_directories(apr_poo
 AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config);
 AP_CORE_DECLARE(void) ap_add_per_url_conf(server_rec *s, void *url_config);
 AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config);
+AP_CORE_DECLARE(void) ap_add_if_conf(core_dir_config *conf, void *url_config);
 AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy, const char *arg);
 
 /* Core filters; not exported. */

Modified: httpd/httpd/trunk/include/http_request.h
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/include/http_request.h?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/include/http_request.h (original)
+++ httpd/httpd/trunk/include/http_request.h Mon Jan 17 11:02:38 2011
@@ -531,6 +531,7 @@ AP_DECLARE_HOOK(void,insert_filter,(requ
 AP_DECLARE(int) ap_location_walk(request_rec *r);
 AP_DECLARE(int) ap_directory_walk(request_rec *r);
 AP_DECLARE(int) ap_file_walk(request_rec *r);
+AP_DECLARE(int) ap_if_walk(request_rec *r);
 
 /** End Of REQUEST (EOR) bucket */
 AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eor;

Modified: httpd/httpd/trunk/server/core.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/core.c?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/server/core.c (original)
+++ httpd/httpd/trunk/server/core.c Mon Jan 17 11:02:38 2011
@@ -143,6 +143,7 @@ static void *create_core_dir_config(apr_
     conf->limit_req_body = AP_LIMIT_REQ_BODY_UNSET;
     conf->limit_xml_body = AP_LIMIT_UNSET;
     conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
+    conf->sec_if   = apr_array_make(a, 2, sizeof(ap_conf_vector_t *));
 
     conf->server_signature = srv_sig_unset;
 
@@ -301,6 +302,17 @@ static void *merge_core_dir_configs(apr_
     /* Otherwise we simply use the base->sec_file array
      */
 
+    if (!conf->sec_if) {
+        conf->sec_if = new->sec_if;
+    }
+    else if (new->sec_if) {
+        /* If we merge, the merge-result must have it's own array
+         */
+        conf->sec_if = apr_array_append(a, base->sec_if, new->sec_if);
+    }
+    /* Otherwise we simply use the base->sec_if array
+     */
+
     if (new->server_signature != srv_sig_unset) {
         conf->server_signature = new->server_signature;
     }
@@ -510,6 +522,14 @@ AP_CORE_DECLARE(void) ap_add_file_conf(c
     *new_space = url_config;
 }
 
+AP_CORE_DECLARE(void) ap_add_if_conf(core_dir_config *conf, void *url_config)
+{
+    void **new_space = (void **)apr_array_push(conf->sec_if);
+
+    *new_space = url_config;
+}
+
+
 /* We need to do a stable sort, qsort isn't stable.  So to make it stable
  * we'll be maintaining the original index into the list, and using it
  * as the minor key during sorting.  The major key is the number of
@@ -2035,8 +2055,7 @@ static const char *ifsection(cmd_parms *
     core_dir_config *conf;
     const command_rec *thiscmd = cmd->cmd;
     ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
-    const char *err = ap_check_cmd_context(cmd,
-                                           NOT_IN_LOCATION | NOT_IN_LIMIT);
+    const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
     const char *condition;
     const char *expr_err;
 
@@ -2078,7 +2097,7 @@ static const char *ifsection(cmd_parms *
     conf->d_is_fnmatch = 0;
     conf->r = NULL;
 
-    ap_add_file_conf((core_dir_config *)mconfig, new_file_conf);
+    ap_add_if_conf((core_dir_config *)mconfig, new_file_conf);
 
     if (*arg != '\0') {
         return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,

Modified: httpd/httpd/trunk/server/request.c
URL: http://svn.apache.org/viewvc/httpd/httpd/trunk/server/request.c?rev=1059867&r1=1059866&r2=1059867&view=diff
==============================================================================
--- httpd/httpd/trunk/server/request.c (original)
+++ httpd/httpd/trunk/server/request.c Mon Jan 17 11:02:38 2011
@@ -152,6 +152,9 @@ AP_DECLARE(int) ap_process_request_inter
         if ((access_status = ap_location_walk(r))) {
             return access_status;
         }
+        if ((access_status = ap_if_walk(r))) {
+            return access_status;
+        }
 
         d = ap_get_module_config(r->per_dir_config, &core_module);
         if (d->log) {
@@ -177,6 +180,9 @@ AP_DECLARE(int) ap_process_request_inter
     if ((access_status = ap_location_walk(r))) {
         return access_status;
     }
+    if ((access_status = ap_if_walk(r))) {
+        return access_status;
+    }
 
     d = ap_get_module_config(r->per_dir_config, &core_module);
     if (d->log) {
@@ -1527,24 +1533,15 @@ AP_DECLARE(int) ap_file_walk(request_rec
          * really try them with the most general first.
          */
         for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
-            const char *err = NULL;
             core_dir_config *entry_core;
             entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module);
 
-            if (entry_core->condition) {
-                /* XXX: error handling */
-                if (ap_expr_exec(r, entry_core->condition, &err) <= 0) {
-                    continue;
-                }
-            }
-            else {
-                if (entry_core->r
-                    ? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
-                    : (entry_core->d_is_fnmatch
-                       ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
-                       : strcmp(entry_core->d, cache->cached))) {
-                    continue;
-                }
+            if (entry_core->r
+                ? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
+                : (entry_core->d_is_fnmatch
+                   ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
+                   : strcmp(entry_core->d, cache->cached))) {
+                continue;
             }
 
             /* If we merged this same section last time, reuse it
@@ -1614,6 +1611,119 @@ AP_DECLARE(int) ap_file_walk(request_rec
     return OK;
 }
 
+AP_DECLARE(int) ap_if_walk(request_rec *r)
+{
+    ap_conf_vector_t *now_merged = NULL;
+    core_dir_config *dconf = ap_get_module_config(r->per_dir_config,
+                                                  &core_module);
+    ap_conf_vector_t **sec_ent = (ap_conf_vector_t **)dconf->sec_if->elts;
+    int num_sec = dconf->sec_if->nelts;
+    walk_cache_t *cache;
+    int cached;
+    int sec_idx;
+    int matches;
+    int cached_matches;
+    walk_walked_t *last_walk;
+
+    /* No tricks here, there are just no <If > to parse in this context.
+     * We won't destroy the cache, just in case _this_ redirect is later
+     * redirected again to a context containing the same or similar <If >.
+     */
+    if (!num_sec) {
+        return OK;
+    }
+
+    cache = prep_walk_cache(AP_NOTE_IF_WALK, r);
+    cached = (cache->cached != NULL);
+    cache->cached = (void *)1;
+    matches = cache->walked->nelts;
+    cached_matches = matches;
+    last_walk = (walk_walked_t*)cache->walked->elts;
+
+    cached &= auth_internal_per_conf;
+
+    /* Go through the if entries, and check for matches  */
+    for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
+        const char *err = NULL;
+        core_dir_config *entry_core;
+        int rc;
+        entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module);
+
+        rc = ap_expr_exec(r, entry_core->condition, &err);
+        if (rc <= 0) {
+            if (rc < 0)
+                ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
+                              "Failed to evaluate <If > condition: %s",
+                              err);
+            continue;
+        }
+
+        /* If we merged this same section last time, reuse it
+         */
+        if (matches) {
+            if (last_walk->matched == sec_ent[sec_idx]) {
+                now_merged = last_walk->merged;
+                ++last_walk;
+                --matches;
+                continue;
+            }
+
+            /* We fell out of sync.  This is our own copy of walked,
+             * so truncate the remaining matches and reset remaining.
+             */
+            cache->walked->nelts -= matches;
+            matches = 0;
+            cached = 0;
+        }
+
+        if (now_merged) {
+            now_merged = ap_merge_per_dir_configs(r->pool,
+                                                  now_merged,
+                                                  sec_ent[sec_idx]);
+        }
+        else {
+            now_merged = sec_ent[sec_idx];
+        }
+
+        last_walk = (walk_walked_t*)apr_array_push(cache->walked);
+        last_walk->matched = sec_ent[sec_idx];
+        last_walk->merged = now_merged;
+    }
+
+    /* Everything matched in sequence, but it may be that the original
+     * walk found some additional matches (which we need to truncate), or
+     * this walk found some additional matches.
+     */
+    if (matches) {
+        cache->walked->nelts -= matches;
+        cached = 0;
+    }
+    else if (cache->walked->nelts > cached_matches) {
+        cached = 0;
+    }
+
+    if (cached
+        && r->per_dir_config == cache->dir_conf_merged) {
+        r->per_dir_config = cache->per_dir_result;
+        return OK;
+    }
+
+    cache->dir_conf_tested = sec_ent;
+    cache->dir_conf_merged = r->per_dir_config;
+
+    /* Merge our cache->dir_conf_merged construct with the r->per_dir_configs,
+     * and note the end result to (potentially) skip this step next time.
+     */
+    if (now_merged) {
+        r->per_dir_config = ap_merge_per_dir_configs(r->pool,
+                                                     r->per_dir_config,
+                                                     now_merged);
+    }
+    cache->per_dir_result = r->per_dir_config;
+
+    return OK;
+}
+
 /*****************************************************************
  *
  * The sub_request mechanism.