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
|
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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
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))) {
|
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,17 +1533,9 @@ 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) {
|
|
||||||
/* XXX: error handling */
|
|
||||||
if (ap_expr_exec(r, entry_core->condition, &err) <= 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (entry_core->r
|
if (entry_core->r
|
||||||
? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
|
? ap_regexec(entry_core->r, cache->cached , 0, NULL, 0)
|
||||||
: (entry_core->d_is_fnmatch
|
: (entry_core->d_is_fnmatch
|
||||||
@@ -1545,7 +1543,6 @@ AP_DECLARE(int) ap_file_walk(request_rec *r)
|
|||||||
: strcmp(entry_core->d, cache->cached))) {
|
: strcmp(entry_core->d, cache->cached))) {
|
||||||
continue;
|
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.
|
||||||
|
|||||||
Reference in New Issue
Block a user