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)

Reply via email to