From: William A. Rowe Jr Date: Wed, 2 Jan 2002 21:58:43 +0000 (+0000) Subject: Merge a singular path for dir_walk to parse, if we have an r->filename X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=1641c07a9942358754dbe79189f18f578abc1a4c;p=apache Merge a singular path for dir_walk to parse, if we have an r->filename which is an APR_DIR, and path_info contents. Also, al la Mr. Pane, optimize our canonical_filename by simply noting the length of the identity match, and refresh canonical_filename when we are finished. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@92707 13f79535-47bb-0310-9956-ffa450edef68 --- diff --git a/server/request.c b/server/request.c index 712b132259..75735d85dd 100644 --- a/server/request.c +++ b/server/request.c @@ -559,7 +559,9 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) * it goes out of scope, filename_len==strlen(r->filename) */ apr_size_t filename_len; - +#ifdef CASE_BLIND_FILESYSTEM + apr_size_t canonical_len; +#endif /* * We must play our own mimi-merge game here, for the few * running dir_config values we care about within dir_walk. @@ -572,24 +574,94 @@ AP_DECLARE(int) ap_directory_walk(request_rec *r) opts_remove = this_dir->opts_remove; override = this_dir->override; - /* Save path_info to merge back onto path_info later. If this - * isn't really path_info, what would it be doing here? + /* Set aside path_info to merge back onto path_info later. + * If r->filename is a directory, we must remerge the path_info, + * before we continue! [Directories cannot, by defintion, have + * path info. Either the next segment is not-found, or a file.] + * + * r->path_info tracks the unconsumed source path. + * r->filename tracks the path as we process it */ - save_path_info = r->path_info; + if ((r->finfo.filetype == APR_DIR) && r->path_info && *r->path_info) + { + if ((rv = apr_filepath_merge(&r->path_info, r->filename, r->path_info, + APR_FILEPATH_NOTABOVEROOT, r->pool)) + != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "dir_walk error, path_info %s is not relative " + "to the filename path %s for uri %s", + r->path_info, r->filename, r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + save_path_info = NULL; + } + else { + save_path_info = r->path_info; + r->path_info = r->filename; + } - /* Now begin to build r->filename from components, set aside the - * segments we have yet to work with in r->path_info (where they - * will stay when the current element resolves to a regular file.) - * - * r->path_info tracks the remaining source path. - * r->filename tracks the path as we build it. +#ifdef CASE_BLIND_FILESYSTEM + + canonical_len = 0; + while (r->canonical_filename && r->canonical_filename[canonical_len] + && (r->canonical_filename[canonical_len] + == r->path_info[canonical_len])) { + ++canonical_len; + } + while (canonical_len + && ((r->canonical_filename[canonical_len - 1] != '/' + && r->canonical_filename[canonical_len - 1]) + || (r->path_info[canonical_len - 1] != '/' + && r->path_info[canonical_len - 1]))) { + --canonical_len; + } + + /* + * Now build r->filename component by component, starting + * with the root (on Unix, simply "/"). We will make a huge + * assumption here for efficiency, that any canonical path + * already given included a canonical root. + */ + rv = apr_filepath_root((const char **)&r->filename, + (const char **)&r->path_info, + canonical_len + ? 0 : APR_FILEPATH_TRUENAME, + r->pool); + filename_len = strlen(r->filename); + + /* + * Bad assumption above? If the root's length is longer + * than the canonical length, then it cannot be trusted as + * a truename. So try again, this time more seriously. */ - r->path_info = r->filename; + if ((rv == APR_SUCCESS) && canonical_len + && (filename_len > canonical_len)) { + rv = apr_filepath_root((const char **)&r->filename, + (const char **)&r->path_info, + APR_FILEPATH_TRUENAME, r->pool); + filename_len = strlen(r->filename); + canonical_len = 0; + } + +#else /* ndef CASE_BLIND_FILESYSTEM, really this simple for Unix today; */ + rv = apr_filepath_root((const char **)&r->filename, (const char **)&r->path_info, - APR_FILEPATH_TRUENAME, r->pool); + 0, r->pool); filename_len = strlen(r->filename); - /* Space for terminating null and an extra / is required. */ + +#endif + + if (rv != APR_SUCCESS) { + ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r, + "dir_walk error, could not determine the root " + "path of filename %s%s for uri %s", + r->filename, r->path_info, r->uri); + return HTTP_INTERNAL_SERVER_ERROR; + } + + /* Working space for terminating null and an extra / is required. + */ buflen = filename_len + strlen(r->path_info) + 2; buf = apr_palloc(r->pool, buflen); memcpy(buf, r->filename, filename_len + 1); @@ -842,9 +914,7 @@ minimerge2: */ if (r->finfo.filetype #ifdef CASE_BLIND_FILESYSTEM - && (r->canonical_filename - && (strncmp(r->filename, - r->canonical_filename, filename_len) == 0)) + && (filename_len <= canonical_len) #endif && ((opts & (OPT_SYM_OWNER | OPT_SYM_LINKS)) == OPT_SYM_LINKS)) { @@ -1028,6 +1098,12 @@ minimerge2: x } */ + /* Save future sub-requestors much angst in processing + * this subrequest. If dir_walk couldn't canonicalize + * the file path, nothing can. + */ + r->canonical_filename = r->filename; + if (r->finfo.filetype == APR_DIR) { cache->cached = r->filename; }