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:
6
CHANGES
6
CHANGES
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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_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_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. */
|
||||
|
||||
@@ -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_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;
|
||||
|
||||
@@ -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_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_pool_t *a, void *basev, void *newv)
|
||||
/* 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(core_dir_config *conf, void *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'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 *cmd, void *mconfig, const char *arg)
|
||||
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 *cmd, void *mconfig, const char *arg)
|
||||
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,
|
||||
|
||||
128
server/request.c
128
server/request.c
@@ -152,6 +152,9 @@ AP_DECLARE(int) ap_process_request_internal(request_rec *r)
|
||||
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_internal(request_rec *r)
|
||||
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,17 +1533,9 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
|
||||
* 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
|
||||
@@ -1545,7 +1543,6 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
|
||||
: 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 *r)
|
||||
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.
|
||||
|
||||
Reference in New Issue
Block a user