From: Stefan Fritsch Date: Mon, 17 Jan 2011 11:02:38 +0000 (+0000) Subject: Merge the sections in a separate step ap_if_walk, after ap_location_walk. X-Git-Tag: 2.3.11~178 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a38d3c9e232f9b28d7136e032b6972fcaf4545d7;p=thirdparty%2Fapache%2Fhttpd.git Merge the sections in a separate step ap_if_walk, after ap_location_walk. This makes apply to all requests, not only to file base requests and it allows to use inside , , and sections. The merging of sections always happens after the merging of sections, even if the section is embedded inside a or section. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1059867 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/CHANGES b/CHANGES index 76464b5fb3d..ed95c6a55ab 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,12 @@ Changes with Apache 2.3.11 + *) core: Apply sections to all requests, not only to file base requests. + Allow to use inside , , and sections. + The merging of sections now happens after the merging of + sections, even if an section is embedded inside a or + 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 diff --git a/include/ap_mmn.h b/include/ap_mmn.h index 193d203d2a2..097e7c0c1a1 100644 --- a/include/ap_mmn.h +++ b/include/ap_mmn.h @@ -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 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 diff --git a/include/http_core.h b/include/http_core.h index f3b7f5b9100..613148b346b 100644 --- a/include/http_core.h +++ b/include/http_core.h @@ -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. */ diff --git a/include/http_request.h b/include/http_request.h index 5f14ceb776d..5c607f7f7c0 100644 --- a/include/http_request.h +++ b/include/http_request.h @@ -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; diff --git a/server/core.c b/server/core.c index 9fa3d947840..7e06e5c961c 100644 --- a/server/core.c +++ b/server/core.c @@ -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, diff --git a/server/request.c b/server/request.c index 9eaee15e4a2..6b7e8918026 100644 --- a/server/request.c +++ b/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,24 +1533,15 @@ 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 - ? 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 *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 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 (!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 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.