From: William A. Rowe Jr Date: Fri, 24 Aug 2001 18:01:25 +0000 (+0000) Subject: Commit this code before another patch becomes to difficult to follow. X-Git-Tag: 2.0.25~71 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=6be8943643974e1b58fe07b443c736c5ec13323b;p=apache Commit this code before another patch becomes to difficult to follow. This patch does one thing, it changes the root path "/" to reflect an element count of Zero (0). directory_walk will always accept the zero element (which sorts first, thankfully) on it's first go around. So, Unix will accept "/" when it's parsing it's first element "/". Dos/Win32 will accept "/" and "C:/" when they parse their first element, "C:/". The root sorted first, so it behaves as users expect. The syntax "//" or "//machine" will be depreciated for now, the user needs to set up the extact "//machine/share/" that they want served on Win32. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@90644 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/core.c b/server/core.c index 59527b4a80..75d06afdea 100644 --- a/server/core.c +++ b/server/core.c @@ -133,10 +133,19 @@ static void *create_core_dir_config(apr_pool_t *a, char *dir) conf->d = apr_pstrcat(a, dir, "/", NULL); } conf->d_is_fnmatch = conf->d ? (apr_is_fnmatch(conf->d) != 0) : 0; + /* On all platforms, "/" is (at minimum) a faux root */ conf->d_is_absolute = conf->d ? (ap_os_is_path_absolute(a, conf->d) || (strcmp(conf->d, "/") == 0)) : 0; - conf->d_components = conf->d ? ap_count_dirs(conf->d) : 0; + + /* Make this explicit - the "/" root has 0 elements, that is, we + * will always merge it, and it will always sort and merge first. + * All others are sorted and tested by the number of slashes. + */ + if (!conf->d || strcmp(conf->d, "/") == 0) + conf->d_components = 0; + else + conf->d_components = ap_count_dirs(conf->d); conf->opts = dir ? OPT_UNSET : OPT_UNSET|OPT_ALL; conf->opts_add = conf->opts_remove = OPT_NONE; @@ -1552,6 +1561,13 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg) arg=apr_pstrndup(cmd->pool, arg, endp-arg); + if (!arg) { + if (thiscmd->cmd_data) + return " block must specify a path"; + else + return " block must specify a path"; + } + cmd->path = ap_getword_conf(cmd->pool, &arg); cmd->override = OR_ALL|ACCESS_CONF; @@ -1560,27 +1576,22 @@ static const char *dirsection(cmd_parms *cmd, void *mconfig, const char *arg) } else if (!strcmp(cmd->path, "~")) { cmd->path = ap_getword_conf(cmd->pool, &arg); + if (!cmd->path) { + return " block must specify a path"; r = ap_pregcomp(cmd->pool, cmd->path, REG_EXTENDED|USE_ICASE); } -#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE) else if (strcmp(cmd->path, "/") == 0) { - /* Treat 'default' path / as an inalienable root */ + /* Treat 'default' path "/" as the inalienable root */ cmd->path = apr_pstrdup(cmd->pool, cmd->path); } -#endif -#if defined(HAVE_UNC_PATHS) - else if (strcmp(cmd->path, "//") == 0) { - /* Treat UNC path // as an inalienable root */ - cmd->path = apr_pstrdup(cmd->pool, cmd->path); - } -#endif else { char *newpath; /* Ensure that the pathname is canonical */ if (apr_filepath_merge(&newpath, NULL, cmd->path, - APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS) - return apr_pstrcat(cmd->pool, "path, - "\"> is invalid.", NULL); + APR_FILEPATH_TRUENAME, cmd->pool) != APR_SUCCESS) { + return apr_pstrcat(cmd->pool, "path, + "\"> path is invalid.", NULL); + } cmd->path = newpath; } diff --git a/server/request.c b/server/request.c index bc85191132..ceb2b20d87 100644 --- a/server/request.c +++ b/server/request.c @@ -391,9 +391,7 @@ AP_DECLARE(int) directory_walk(request_rec *r) int res; unsigned i, num_dirs; int j, test_filename_len; -#if defined(HAVE_UNC_PATHS) || defined(NETWARE) unsigned iStart = 1; -#endif ap_conf_vector_t *entry_config; ap_conf_vector_t *this_conf; core_dir_config *entry_core; @@ -555,27 +553,11 @@ AP_DECLARE(int) directory_walk(request_rec *r) iStart = 2; #endif -#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE) - /* Should match sections starting from '/', not 'e:/' - * (for example). WIN32/OS2/NETWARE do not have a single root directory, - * they have one for each filesystem. Traditionally, Apache has treated - * permissions as the base for the whole server, and this - * tradition should probably be preserved. - * - * NOTE: MUST SYNC WITH ap_make_dirstr_prefix() CHANGE IN src/main/util.c + /* i keeps track of how many segments we are testing + * j keeps track of which section we're on, see core_reorder_directories */ - if (test_filename[0] == '/') - i = 1; - else - i = 0; -#else - /* Normal File Systems are rooted at / */ - i = 1; -#endif /* def HAVE_DRIVE_LETTERS || NETWARE */ - - /* j keeps track of which section we're on, see core_reorder_directories */ j = 0; - for (; i <= num_dirs; ++i) { + for (i = 1; i <= num_dirs; ++i) { int overrides_here; core_dir_config *core_dir = ap_get_module_config(per_dir_defaults, &core_module); @@ -591,11 +573,8 @@ AP_DECLARE(int) directory_walk(request_rec *r) * permissions appropriate to the *parent* directory... */ -#if defined(HAVE_UNC_PATHS) || defined(NETWARE) - /* Test only legal names against the real filesystem */ - if (i >= iStart) -#endif - if ((res = check_symlinks(test_dirname, core_dir->opts, r->pool))) { + /* Test only real names (after the root) against the real filesystem */ + if ((i > iStart) && (res = check_symlinks(test_dirname, core_dir->opts, r->pool))) { ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r, "Symbolic link not allowed: %s", test_dirname); return res; @@ -613,22 +592,19 @@ AP_DECLARE(int) directory_walk(request_rec *r) entry_core = ap_get_module_config(entry_config, &core_module); entry_dir = entry_core->d; - if (entry_core->r - || !entry_core->d_is_absolute -#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE) - /* To account for the top-level "/" directory when i == 0 - * XXX: The net test may be wrong... may fail ap_os_is_path_absolute - */ - || (entry_core->d_components > 1 - && entry_core->d_components > i) -#else - || entry_core->d_components > i -#endif /* def HAVE_DRIVE_LETTERS || NETWARE */ - ) + if (entry_core->r || !entry_core->d_is_absolute + || entry_core->d_components > i) break; this_conf = NULL; - if (entry_core->d_is_fnmatch) { + /* We will always add in '0' element components, e.g. plain old + * , and is classified as zero + * so that Win32/Netware/OS2 etc all pick that up. + */ + if (!entry_core->d_components) { + this_conf = entry_config; + } + else if (entry_core->d_is_fnmatch) { if (!apr_fnmatch(entry_dir, test_dirname, FNM_PATHNAME)) { this_conf = entry_config; } @@ -643,25 +619,13 @@ AP_DECLARE(int) directory_walk(request_rec *r) core_dir = ap_get_module_config(per_dir_defaults, &core_module); } -#if defined(HAVE_DRIVE_LETTERS) || defined(NETWARE) - /* So that other top-level directory sections (e.g. "e:/") aren't - * skipped when i == 0 - * XXX: I don't get you here, Tim... That's a level 1 section, but - * we are at level 0. Did you mean fast-forward to the next? - */ - else if (!i) - break; -#endif /* def HAVE_DRIVE_LETTERS || NETWARE */ } overrides_here = core_dir->override; /* If .htaccess files are enabled, check for one. */ -#if defined(HAVE_UNC_PATHS) || defined(NETWARE) /* Test only legal names against the real filesystem */ - if (i >= iStart) -#endif - if (overrides_here) { + if ((i >= iStart) && overrides_here) { ap_conf_vector_t *htaccess_conf = NULL; res = ap_parse_htaccess(&htaccess_conf, r, overrides_here, @@ -791,19 +755,18 @@ AP_DECLARE(int) directory_walk(request_rec *r) buf = apr_palloc(r->pool, buflen); strcpy (buf, r->filename); r->filename = buf; + r->finfo.valid = APR_FINFO_TYPE; + r->finfo.filetype = APR_DIR; /* It's the root, of course it's a dir */ } else { - return HTTP_FORBIDDEN; - } - r->finfo.valid = APR_FINFO_TYPE; - r->finfo.filetype = APR_DIR; /* It's the root, of course it's a dir */ - - /* Fake filenames (i.e. proxy:) only match Directory sections. - */ - if (rv == APR_EBADPATH) - { const char *entry_dir; + /* Fake filenames (i.e. proxy:) only match Directory sections. + */ + if (rv != APR_EBADPATH) + return HTTP_FORBIDDEN; + } + for (sec = 0; sec < num_sec; ++sec) { entry_config = sec_ent[sec]; @@ -842,7 +805,7 @@ AP_DECLARE(int) directory_walk(request_rec *r) * sec keeps track of which section we're on, since sections are * ordered by number of segments. See core_reorder_directories */ - seg = 1; + seg = ap_count_dirs(r->filename); sec = 0; do { int overrides_here; @@ -851,40 +814,43 @@ AP_DECLARE(int) directory_walk(request_rec *r) /* We have no trailing slash, but we sure would appreciate one... */ - if (seg > 1) + if (!sec && r->filename[strlen(r->filename)-1] != '/') strcat(r->filename, "/"); /* Begin *this* level by looking for matching sections * from the server config. */ for (; sec < num_sec; ++sec) { - char *entry_dir; + const char *entry_dir; entry_config = sec_ent[sec]; entry_core = ap_get_module_config(entry_config, &core_module); entry_dir = entry_core->d; - /* No more possible matches? */ + /* No more possible matches for this many segments? + * We are done when we find relative/regex/longer components. + */ if (entry_core->r || !entry_core->d_is_absolute || entry_core->d_components > seg) break; - this_conf = NULL; - if (entry_core->d_is_fnmatch) { - if (!apr_fnmatch(entry_dir, r->filename, FNM_PATHNAME)) { - this_conf = entry_config; - } + /* We will never skip '0' element components, e.g. plain old + * , and are classified as zero + * so that Win32/Netware/OS2 etc all pick them up. + * Otherwise, skip over the mismatches. + */ + if (entry_core->d_components + && (entry_core->d_is_fnmatch + ? (apr_fnmatch(entry_dir, r->filename, FNM_PATHNAME) != APR_SUCCESS) + : (strcmp(r->filename, entry_dir) != 0)) { + continue; } - else if (!strcmp(r->filename, entry_dir)) - this_conf = entry_config; - if (this_conf) { - per_dir_defaults = ap_merge_per_dir_configs(r->pool, - per_dir_defaults, - this_conf); - core_dir = ap_get_module_config(per_dir_defaults, + per_dir_defaults = ap_merge_per_dir_configs(r->pool, + per_dir_defaults, + entry_config); + core_dir = ap_get_module_config(per_dir_defaults, &core_module); - } } overrides_here = core_dir->override;