Hi,
I've tried to tackle this issue in STATUS:
* Allow the DocumentRoot directive within <Location > scopes? This
allows the beloved (crusty) Alias /foo/ /somepath/foo/ followed
by a <Directory /somepath/foo> to become simply
<Location /foo/> DocumentRoot /somefile/foo (IMHO a bit more legible
and in-your-face.) DocumentRoot unset would be accepted [and would
not permit content to be served, only virtual resources such as
server-info or server-status.
This proposed change would _not_ depricate Alias.
My patch probably is incomplete (and most likely I broke something), but it
is a first cut I'd like some feedback on. For starters, document_root is
moved for core_server_conf to core_dir_conf. core_dir_conf got an extra
field telling you what type of dir conf it is. Wrowe suggested that we might
want a registration API for this, but I decided to go with an enum for
starters. Registration can come in a later iteration.
Sander
Index: include/http_core.h
===================================================================
RCS file: /home/cvspublic/httpd-2.0/include/http_core.h,v
retrieving revision 1.58
diff -u -r1.58 http_core.h
--- include/http_core.h 2 Jan 2002 07:56:24 -0000 1.58
+++ include/http_core.h 5 Jan 2002 14:14:31 -0000
@@ -390,11 +390,20 @@
} server_signature_e;
typedef struct {
+ enum {
+ DIR_CONF_DIRECTORY = 0,
+ DIR_CONF_LOCATION,
+ DIR_CONF_FILES,
+ DIR_CONF_SERVER
+ } dir_conf_type;
+
/* path of the directory/regex/etc. see also d_is_fnmatch/absolute below */
char *d;
/* the number of slashes in d */
unsigned d_components;
+ const char *document_root;
+
/* If (opts & OPT_UNSET) then no absolute assignment to options has
* been made.
* invariant: (opts_add & opts_remove) == 0
@@ -499,12 +508,6 @@
char *gprof_dir;
#endif
- /* Name translations --- we want the core to be able to do *something*
- * so it's at least a minimally functional web server on its own (and
- * can be tested that way). But let's keep it to the bare minimum:
- */
- const char *ap_document_root;
-
/* Access control */
char *access_name;
Index: server/core.c
===================================================================
RCS file: /home/cvspublic/httpd-2.0/server/core.c,v
retrieving revision 1.126
diff -u -r1.126 core.c
--- server/core.c 2 Jan 2002 07:56:25 -0000 1.126
+++ server/core.c 5 Jan 2002 14:15:28 -0000
@@ -124,6 +124,8 @@
core_dir_config *conf;
conf = (core_dir_config *)apr_pcalloc(a, sizeof(core_dir_config));
+
+ conf->dir_conf_type = DIR_CONF_SERVER;
/* conf->r and conf->d[_*] are initialized by dirsection() or left NULL */
@@ -182,10 +184,15 @@
conf = (core_dir_config *)apr_palloc(a, sizeof(core_dir_config));
memcpy(conf, base, sizeof(core_dir_config));
+ conf->dir_conf_type = new->dir_conf_type;
+
conf->d = new->d;
conf->d_is_fnmatch = new->d_is_fnmatch;
conf->d_components = new->d_components;
conf->r = new->r;
+
+ if (new->document_root)
+ conf->document_root = new->document_root;
if (new->opts & OPT_UNSET) {
/* there was no explicit setting of new->opts, so we merge
@@ -343,7 +350,6 @@
conf->gprof_dir = NULL;
#endif
conf->access_name = is_virtual ? NULL : DEFAULT_ACCESS_FNAME;
- conf->ap_document_root = is_virtual ? NULL : DOCUMENT_LOCATION;
conf->sec_dir = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
conf->sec_url = apr_array_make(a, 40, sizeof(ap_conf_vector_t *));
@@ -361,9 +367,7 @@
if (!conf->access_name) {
conf->access_name = base->access_name;
}
- if (!conf->ap_document_root) {
- conf->ap_document_root = base->ap_document_root;
- }
+
conf->sec_dir = apr_array_append(p, base->sec_dir, virt->sec_dir);
conf->sec_url = apr_array_append(p, base->sec_url, virt->sec_url);
@@ -530,11 +534,11 @@
AP_DECLARE(const char *) ap_document_root(request_rec *r) /* Don't use this! */
{
- core_server_config *conf;
+ core_dir_config *conf;
- conf = (core_server_config *)ap_get_module_config(r->server->module_config,
- &core_module);
- return conf->ap_document_root;
+ conf = (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+ return conf->document_root;
}
AP_DECLARE(const apr_array_header_t *) ap_requires(request_rec *r)
@@ -905,28 +909,29 @@
return NULL;
}
+static const char *unset_document_root = "";
+
static const char *set_document_root(cmd_parms *cmd, void *dummy,
const char *arg)
{
- void *sconf = cmd->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
+ core_dir_config *dconf = dummy;
+
const char *err = ap_check_cmd_context(cmd,
- NOT_IN_DIR_LOC_FILE|NOT_IN_LIMIT);
+ NOT_IN_DIRECTORY | NOT_IN_FILES | NOT_IN_LIMIT);
if (err != NULL) {
return err;
}
/* TODO: ap_configtestonly && ap_docrootcheck && */
/* XXX Shouldn't this be relative to ServerRoot ??? */
- if (apr_filepath_merge((char**)&conf->ap_document_root, NULL, arg,
+ if (apr_filepath_merge((char**)&dconf->document_root, NULL, arg,
APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS
|| !ap_is_directory(cmd->pool, arg)) {
- if (cmd->server->is_virtual) {
+ if (cmd->server->is_virtual || cmd->path != NULL) {
ap_log_perror(APLOG_MARK, APLOG_STARTUP | APLOG_NOERRNO, 0, cmd->pool,
"Warning: DocumentRoot [%s] does not exist",
arg);
- conf->ap_document_root = arg;
+ dconf->document_root = arg;
}
else {
return "DocumentRoot must be a directory";
@@ -1286,6 +1291,8 @@
conf = ap_set_config_vectors(cmd->server, new_dir_conf, cmd->path,
&core_module, cmd->pool);
+ conf->dir_conf_type = DIR_CONF_DIRECTORY;
+
errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_dir_conf);
if (errmsg != NULL)
return errmsg;
@@ -1336,7 +1343,7 @@
return unclosed_directive(cmd);
}
- arg=apr_pstrndup(cmd->pool, arg, endp-arg);
+ arg = apr_pstrndup(cmd->pool, arg, endp-arg);
cmd->path = ap_getword_conf(cmd->pool, &arg);
cmd->override = OR_ALL|ACCESS_CONF;
@@ -1353,6 +1360,9 @@
conf = ap_set_config_vectors(cmd->server, new_url_conf, cmd->path,
&core_module, cmd->pool);
+ conf->document_root = unset_document_root;
+ conf->dir_conf_type = DIR_CONF_LOCATION;
+
errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_url_conf);
if (errmsg != NULL)
return errmsg;
@@ -1425,6 +1435,8 @@
conf = ap_set_config_vectors(cmd->server, new_file_conf, cmd->path,
&core_module, cmd->pool);
+ conf->dir_conf_type = DIR_CONF_FILES;
+
errmsg = ap_walk_config(cmd->directive->first_child, cmd, new_file_conf);
if (errmsg != NULL)
return errmsg;
@@ -2447,7 +2459,7 @@
AP_INIT_RAW_ARGS("AccessFileName", set_access_name, NULL, RSRC_CONF,
"Name(s) of per-directory config files (default: .htaccess)"),
-AP_INIT_TAKE1("DocumentRoot", set_document_root, NULL, RSRC_CONF,
+AP_INIT_TAKE1("DocumentRoot", set_document_root, NULL, RSRC_CONF | ACCESS_CONF,
"Root directory of the document tree"),
AP_INIT_TAKE2("ErrorDocument", set_error_document, NULL, OR_FILEINFO,
"Change responses for HTTP errors"),
@@ -2600,9 +2612,11 @@
AP_DECLARE_NONSTD(int) ap_core_translate(request_rec *r)
{
- void *sconf = r->server->module_config;
- core_server_config *conf = ap_get_module_config(sconf, &core_module);
-
+ core_dir_config *conf =
+ (core_dir_config *)ap_get_module_config(r->per_dir_config,
+ &core_module);
+
+
/* XXX this seems too specific, this should probably become
* some general-case test
*/
@@ -2614,13 +2628,32 @@
"Invalid URI in request %s", r->the_request);
return HTTP_BAD_REQUEST;
}
-
+
+ if (conf->dir_conf_type == DIR_CONF_LOCATION) {
+ char *uri;
+
+ if (conf->document_root == unset_document_root
+ || conf->r != NULL)
+ return DECLINED;
+
+ uri = &r->uri[strlen(conf->d)];
+
+ if (apr_filepath_merge(&r->filename, conf->document_root,
+ uri + ((*(uri) == '/') ? 1 : 0),
+ APR_FILEPATH_TRUENAME
+ | APR_FILEPATH_SECUREROOT, r->pool) != APR_SUCCESS) {
+ return HTTP_FORBIDDEN;
+ }
+
+ return OK;
+ }
+
if (r->server->path
&& !strncmp(r->uri, r->server->path, r->server->pathlen)
&& (r->server->path[r->server->pathlen - 1] == '/'
|| r->uri[r->server->pathlen] == '/'
|| r->uri[r->server->pathlen] == '\0')) {
- if (apr_filepath_merge(&r->filename, conf->ap_document_root,
+ if (apr_filepath_merge(&r->filename, conf->document_root,
r->uri + r->server->pathlen,
APR_FILEPATH_TRUENAME
| APR_FILEPATH_SECUREROOT, r->pool)
@@ -2635,7 +2668,7 @@
* /'s in a row. This happens under windows when the document
* root ends with a /
*/
- if (apr_filepath_merge(&r->filename, conf->ap_document_root,
+ if (apr_filepath_merge(&r->filename, conf->document_root,
r->uri + ((*(r->uri) == '/') ? 1 : 0),
APR_FILEPATH_TRUENAME
| APR_FILEPATH_SECUREROOT, r->pool)