1
0
mirror of https://github.com/apache/httpd.git synced 2025-11-09 15:21:02 +03:00

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.


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1059867 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Stefan Fritsch
2011-01-17 11:02:38 +00:00
parent 90e46c5792
commit a38d3c9e23
6 changed files with 162 additions and 21 deletions

View File

@@ -2,6 +2,12 @@
Changes with Apache 2.3.11 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 *) mod_proxy: Refactor usage of shared data by dropping the scoreboard
and using slotmem. Create foundation for dynamic growth/changes of and using slotmem. Create foundation for dynamic growth/changes of
members within a balancer. Remove BalancerNonce in favor of a members within a balancer. Remove BalancerNonce in favor of a

View File

@@ -294,14 +294,16 @@
* info from scoreboard and use slotmem; Allow * info from scoreboard and use slotmem; Allow
* dynamic growth of balancer members; Remove * dynamic growth of balancer members; Remove
* BalancerNonce in favor of 'nonce' parameter. * 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" */ #define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
#ifndef MODULE_MAGIC_NUMBER_MAJOR #ifndef MODULE_MAGIC_NUMBER_MAJOR
#define MODULE_MAGIC_NUMBER_MAJOR 20101223 #define MODULE_MAGIC_NUMBER_MAJOR 20110117
#endif #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 * Determine if the server's current MODULE_MAGIC_NUMBER is at least a

View File

@@ -362,7 +362,8 @@ typedef struct {
#define AP_NOTE_DIRECTORY_WALK 0 #define AP_NOTE_DIRECTORY_WALK 0
#define AP_NOTE_LOCATION_WALK 1 #define AP_NOTE_LOCATION_WALK 1
#define AP_NOTE_FILE_WALK 2 #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 * Reserve an element in the core_request_config->notes array
@@ -499,6 +500,7 @@ typedef struct {
/* Access control */ /* Access control */
apr_array_header_t *sec_file; apr_array_header_t *sec_file;
apr_array_header_t *sec_if;
ap_regex_t *r; ap_regex_t *r;
const char *mime_type; /* forced with ForceType */ const char *mime_type; /* forced with ForceType */
@@ -597,6 +599,7 @@ void ap_core_reorder_directories(apr_pool_t *, server_rec *);
AP_CORE_DECLARE(void) ap_add_per_dir_conf(server_rec *s, void *dir_config); 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_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_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); AP_CORE_DECLARE_NONSTD(const char *) ap_limit_section(cmd_parms *cmd, void *dummy, const char *arg);
/* Core filters; not exported. */ /* Core filters; not exported. */

View File

@@ -531,6 +531,7 @@ AP_DECLARE_HOOK(void,insert_filter,(request_rec *r))
AP_DECLARE(int) ap_location_walk(request_rec *r); AP_DECLARE(int) ap_location_walk(request_rec *r);
AP_DECLARE(int) ap_directory_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_file_walk(request_rec *r);
AP_DECLARE(int) ap_if_walk(request_rec *r);
/** End Of REQUEST (EOR) bucket */ /** End Of REQUEST (EOR) bucket */
AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eor; AP_DECLARE_DATA extern const apr_bucket_type_t ap_bucket_type_eor;

View File

@@ -143,6 +143,7 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir)
conf->limit_req_body = AP_LIMIT_REQ_BODY_UNSET; conf->limit_req_body = AP_LIMIT_REQ_BODY_UNSET;
conf->limit_xml_body = AP_LIMIT_UNSET; conf->limit_xml_body = AP_LIMIT_UNSET;
conf->sec_file = apr_array_make(a, 2, sizeof(ap_conf_vector_t *)); 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; conf->server_signature = srv_sig_unset;
@@ -301,6 +302,17 @@ static void *merge_core_dir_configs(apr_pool_t *a, void *basev, void *newv)
/* Otherwise we simply use the base->sec_file array /* 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) { if (new->server_signature != srv_sig_unset) {
conf->server_signature = new->server_signature; conf->server_signature = new->server_signature;
} }
@@ -510,6 +522,14 @@ AP_CORE_DECLARE(void) ap_add_file_conf(core_dir_config *conf, void *url_config)
*new_space = url_config; *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 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 * 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 * as the minor key during sorting. The major key is the number of
@@ -2035,8 +2055,7 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg)
core_dir_config *conf; core_dir_config *conf;
const command_rec *thiscmd = cmd->cmd; const command_rec *thiscmd = cmd->cmd;
ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool); ap_conf_vector_t *new_file_conf = ap_create_per_dir_config(cmd->pool);
const char *err = ap_check_cmd_context(cmd, const char *err = ap_check_cmd_context(cmd, NOT_IN_LIMIT);
NOT_IN_LOCATION | NOT_IN_LIMIT);
const char *condition; const char *condition;
const char *expr_err; const char *expr_err;
@@ -2078,7 +2097,7 @@ static const char *ifsection(cmd_parms *cmd, void *mconfig, const char *arg)
conf->d_is_fnmatch = 0; conf->d_is_fnmatch = 0;
conf->r = NULL; 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') { if (*arg != '\0') {
return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name, return apr_pstrcat(cmd->pool, "Multiple ", thiscmd->name,

View File

@@ -152,6 +152,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
if ((access_status = ap_location_walk(r))) { if ((access_status = ap_location_walk(r))) {
return access_status; return access_status;
} }
if ((access_status = ap_if_walk(r))) {
return access_status;
}
d = ap_get_module_config(r->per_dir_config, &core_module); d = ap_get_module_config(r->per_dir_config, &core_module);
if (d->log) { if (d->log) {
@@ -177,6 +180,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
if ((access_status = ap_location_walk(r))) { if ((access_status = ap_location_walk(r))) {
return access_status; return access_status;
} }
if ((access_status = ap_if_walk(r))) {
return access_status;
}
d = ap_get_module_config(r->per_dir_config, &core_module); d = ap_get_module_config(r->per_dir_config, &core_module);
if (d->log) { if (d->log) {
@@ -1527,24 +1533,15 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
* really try them with the most general first. * really try them with the most general first.
*/ */
for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) { for (sec_idx = 0; sec_idx < num_sec; ++sec_idx) {
const char *err = NULL;
core_dir_config *entry_core; core_dir_config *entry_core;
entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module); entry_core = ap_get_module_config(sec_ent[sec_idx], &core_module);
if (entry_core->condition) { if (entry_core->r
/* XXX: error handling */ ? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
if (ap_expr_exec(r, entry_core->condition, &err) <= 0) { : (entry_core->d_is_fnmatch
continue; ? apr_fnmatch(entry_core->d, cache->cached, APR_FNM_PATHNAME)
} : strcmp(entry_core->d, cache->cached))) {
} 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 we merged this same section last time, reuse it /* If we merged this same section last time, reuse it
@@ -1614,6 +1611,119 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
return OK; 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. * The sub_request mechanism.