Changes with Apache 2.3.13
+ *) mod_userdir/mod_alias/mod_vhost_alias: Correctly set DOCUMENT_ROOT,
+ CONTEXT_DOCUMENT_ROOT, CONTEXT_PREFIX. PR 26052. PR 46198.
+ [Stefan Fritsch]
+
+ *) core: Allow to override document_root on a per-request basis. Introduce
+ new context_document_root and context_prefix which provide information
+ about non-global URI-to-directory mappings (from e.g. mod_userdir or
+ mod_alias) to scripts. PR 49705. [Stefan Fritsch]
+
*) core: Add <ElseIf> and <Else> to complement <If> sections.
[Stefan Fritsch]
* ap_expr_exec_ctx()
* 20110604.0 (2.3.13-dev) Make ap_rputs() inline
* 20110605.0 (2.3.13-dev) add core_dir_config->condition_ifelse, change return
- * type of ap_add_if_conf()
+ * type of ap_add_if_conf().
+ * Add members of core_request_config: document_root,
+ * context_document_root, context_prefix.
+ * Add ap_context_*(), ap_set_context_info(), ap_set_document_root()
*/
#define MODULE_MAGIC_COOKIE 0x41503234UL /* "AP24" */
* ErrorDocument
*/
+ /** per-request document root of the server. This allows mass vhosting
+ * modules better compatibility with some scripts. Normally the
+ * context_* info should be used instead */
+ const char *document_root;
+
+ /*
+ * more fine-grained context information which is set by modules like
+ * mod_alias and mod_userdir
+ */
+ /** the context root directory on disk for the current resource,
+ * without trailing slash
+ */
+ const char *context_document_root;
+ /** the URI prefix that corresponds to the context_document_root directory,
+ * without trailing slash
+ */
+ const char *context_prefix;
+
/** There is a script processor installed on the output filter chain,
* so it needs the default_handler to deliver a (script) file into
* the chain so it can process it. Normally, default_handler only
core_ctx_t *in_ctx;
} core_net_rec;
+/**
+ * Get the context_document_root for a request. This is a generalization of
+ * the document root, which is too limited in the presence of mappers like
+ * mod_userdir and mod_alias. The context_document_root is the directory
+ * on disk that maps to the context_prefix URI prefix.
+ * @param r The request
+ * @note For resources that do not map to the file system or for very complex
+ * mappings, this information may still be wrong.
+ */
+AP_DECLARE(const char *) ap_context_document_root(request_rec *r);
+
+/**
+ * Get the context_prefix for a request. The context_prefix URI prefix
+ * maps to the context_document_root on disk.
+ * @param r The request
+ */
+AP_DECLARE(const char *) ap_context_prefix(request_rec *r);
+
+/** Set context_prefix and context_document_root for a request.
+ * @param r The request
+ * @param prefix the URI prefix, without trailing slash
+ * @param document_root the corresponding directory on disk, without trailing
+ * slash
+ * @note If one of prefix of document_root is NULL, the corrsponding
+ * property will not be changed.
+ */
+AP_DECLARE(void) ap_set_context_info(request_rec *r, const char *prefix,
+ const char *document_root);
+
+/** Set per-request document root. This is for mass virtual hosting modules
+ * that want to provide the correct DOCUMENT_ROOT value to scripts.
+ * @param r The request
+ * @param document_root the document root for the request.
+ */
+AP_DECLARE(void) ap_set_document_root(request_rec *r, const char *document_root);
+
/**
* Examine a field value (such as a media-/content-type) string and return
* it sans any parameters; e.g., strip off any ';charset=foo' and the like.
}
static char *try_alias_list(request_rec *r, apr_array_header_t *aliases,
- int doesc, int *status)
+ int is_redir, int *status)
{
alias_entry *entries = (alias_entry *) aliases->elts;
ap_regmatch_t regm[AP_MAX_REG_MATCH];
if (alias->real) {
found = ap_pregsub(r->pool, alias->real, r->uri,
AP_MAX_REG_MATCH, regm);
- if (found && doesc) {
- apr_uri_t uri;
- apr_uri_parse(r->pool, found, &uri);
- /* Do not escape the query string or fragment. */
- found = apr_uri_unparse(r->pool, &uri,
- APR_URI_UNP_OMITQUERY);
- found = ap_escape_uri(r->pool, found);
- if (uri.query) {
- found = apr_pstrcat(r->pool, found, "?",
- uri.query, NULL);
- }
- if (uri.fragment) {
- found = apr_pstrcat(r->pool, found, "#",
- uri.fragment, NULL);
- }
+ if (found) {
+ if (is_redir) {
+ apr_uri_t uri;
+ apr_uri_parse(r->pool, found, &uri);
+ /* Do not escape the query string or fragment. */
+ found = apr_uri_unparse(r->pool, &uri,
+ APR_URI_UNP_OMITQUERY);
+ found = ap_escape_uri(r->pool, found);
+ if (uri.query) {
+ found = apr_pstrcat(r->pool, found, "?",
+ uri.query, NULL);
+ }
+ if (uri.fragment) {
+ found = apr_pstrcat(r->pool, found, "#",
+ uri.fragment, NULL);
+ }
+ }
+ else {
+ int pathlen = strlen(found) -
+ (strlen(r->uri + regm[0].rm_eo));
+ AP_DEBUG_ASSERT(pathlen >= 0);
+ AP_DEBUG_ASSERT(pathlen <= strlen(found));
+ ap_set_context_info(r,
+ apr_pstrmemdup(r->pool, r->uri,
+ regm[0].rm_eo),
+ apr_pstrmemdup(r->pool, found,
+ pathlen));
+ }
}
}
else {
l = alias_matches(r->uri, alias->fake);
if (l > 0) {
- if (doesc) {
+ ap_set_context_info(r, alias->fake, alias->real);
+ if (is_redir) {
char *escurl;
escurl = ap_os_escape_path(r->pool, r->uri + l, 1);
* canonicalized. After I finish eliminating os canonical.
* Better fail test for ap_server_root_relative needed here.
*/
- if (!doesc) {
+ if (!is_redir) {
found = ap_server_root_relative(r->pool, found);
}
if (found) {
if (*var == 'H' && !strcmp(var, "HTTP_FORWARDED")) {
result = lookup_header("Forwarded", ctx);
}
+ else if (*var == 'C' && !strcmp(var, "CONTEXT_PREFIX")) {
+ result = ap_context_prefix(r);
+ }
else if (var[8] == 'M' && !strcmp(var, "REQUEST_METHOD")) {
result = r->method;
}
if (!strcmp(var, "HTTP_PROXY_CONNECTION")) {
result = lookup_header("Proxy-Connection", ctx);
}
+ else if (!strcmp(var, "CONTEXT_DOCUMENT_ROOT")) {
+ result = ap_context_document_root(r);
+ }
break;
}
}
r->pool)) == APR_SUCCESS
|| rv == APR_INCOMPLETE))) {
r->filename = apr_pstrcat(r->pool, filename, dname, NULL);
+ ap_set_context_info(r, apr_pstrmemdup(r->pool, r->uri,
+ dname - r->uri),
+ filename);
/* XXX: Does this walk us around FollowSymLink rules?
* When statbuf contains info on r->filename we can save a syscall
* by copying it to r->finfo
int ndots;
char buf[HUGE_STRING_LEN];
- char *dest, last;
+ char *dest;
+ const char *docroot;
int N, M, Np, Mp, Nd, Md;
const char *start, *end;
r->filename = NULL;
dest = buf;
- last = '\0';
while (*map) {
if (*map != '%') {
/* normal characters */
vhost_alias_checkspace(r, buf, &dest, 1);
- last = *dest++ = *map++;
+ *dest++ = *map++;
continue;
}
/* we are in a format specifier */
++map;
- /* can't be a slash */
- last = '\0';
/* %% -> % */
if (*map == '%') {
++map;
*dest++ = apr_tolower(*p);
}
}
- *dest = '\0';
/* no double slashes */
- if (last == '/') {
- ++uri;
+ if (dest - buf > 0 && dest[-1] == '/') {
+ --dest;
}
+ *dest = '\0';
- if (r->filename) {
- r->filename = apr_pstrcat(r->pool, r->filename, buf, uri, NULL);
- }
- else {
- r->filename = apr_pstrcat(r->pool, buf, uri, NULL);
- }
+ if (r->filename)
+ docroot = apr_pstrcat(r->pool, r->filename, buf, NULL);
+ else
+ docroot = apr_pstrdup(r->pool, buf);
+ r->filename = apr_pstrcat(r->pool, docroot, uri, NULL);
+ ap_set_context_info(r, NULL, docroot);
+ ap_set_document_root(r, docroot);
}
static int mva_translate(request_rec *r)
/* see is_scriptaliased() in mod_cgi */
r->handler = "cgi-script";
apr_table_setn(r->notes, "alias-forced-type", r->handler);
+ ap_set_context_info(r, "/cgi-bin", NULL);
}
return OK;
AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
{
- core_server_config *conf;
+ core_server_config *sconf;
+ core_request_config *rconf = ap_get_module_config(r->request_config,
+ &core_module);
+ if (rconf->document_root)
+ return rconf->document_root;
+ sconf = ap_get_module_config(r->server->module_config, &core_module);
+ return sconf->ap_document_root;
+}
- conf = (core_server_config *)ap_get_module_config(r->server->module_config,
- &core_module);
+AP_DECLARE(const char *) ap_context_prefix(request_rec *r)
+{
+ core_request_config *conf = ap_get_module_config(r->request_config,
+ &core_module);
+ if (conf->context_prefix)
+ return conf->context_prefix;
+ else
+ return "";
+}
- return conf->ap_document_root;
+AP_DECLARE(const char *) ap_context_document_root(request_rec *r)
+{
+ core_request_config *conf = ap_get_module_config(r->request_config,
+ &core_module);
+ if (conf->context_document_root)
+ return conf->context_document_root;
+ else
+ return ap_document_root(r);
+}
+
+AP_DECLARE(void) ap_set_document_root(request_rec *r, const char *document_root)
+{
+ core_request_config *conf = ap_get_module_config(r->request_config,
+ &core_module);
+ conf->document_root = document_root;
+}
+
+AP_DECLARE(void) ap_set_context_info(request_rec *r, const char *context_prefix,
+ const char *context_document_root)
+{
+ core_request_config *conf = ap_get_module_config(r->request_config,
+ &core_module);
+ if (context_prefix)
+ conf->context_prefix = context_prefix;
+ if (context_document_root)
+ conf->context_document_root = context_document_root;
}
/* Should probably just get rid of this... the only code that cares is
"SCRIPT_GROUP", /* 22 */
"DOCUMENT_URI", /* 23 */
"LAST_MODIFIED", /* 24 */
+ "CONTEXT_PREFIX", /* 25 */
+ "CONTEXT_DOCUMENT_ROOT", /* 26 */
NULL
};
tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min,
tm.tm_sec);
}
+ case 25:
+ return ap_context_prefix(r);
+ case 26:
+ return ap_context_document_root(r);
default:
ap_assert(0);
return NULL;
ap_get_remote_host(c, r->per_dir_config, REMOTE_HOST, NULL));
apr_table_addn(e, "REMOTE_ADDR", c->remote_ip);
apr_table_addn(e, "DOCUMENT_ROOT", ap_document_root(r)); /* Apache */
+ apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r));
+ apr_table_addn(e, "CONTEXT_PREFIX", ap_context_prefix(r));
+ apr_table_addn(e, "CONTEXT_DOCUMENT_ROOT", ap_context_document_root(r));
apr_table_addn(e, "SERVER_ADMIN", s->server_admin); /* Apache */
apr_table_addn(e, "SCRIPT_FILENAME", r->filename); /* Apache */
apr_table_setn(e, "GATEWAY_INTERFACE", "CGI/1.1");
apr_table_setn(e, "SERVER_PROTOCOL", r->protocol);
apr_table_setn(e, "REQUEST_METHOD", r->method);
- apr_table_setn(e, "REQUEST_SCHEME", ap_http_scheme(r));
apr_table_setn(e, "QUERY_STRING", r->args ? r->args : "");
apr_table_setn(e, "REQUEST_URI", original_uri(r));