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)