]> granicus.if.org Git - apache/commitdiff
Merge a singular path for dir_walk to parse, if we have an r->filename
authorWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 2 Jan 2002 21:58:43 +0000 (21:58 +0000)
committerWilliam A. Rowe Jr <wrowe@apache.org>
Wed, 2 Jan 2002 21:58:43 +0000 (21:58 +0000)
  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

server/request.c

index 712b132259ea58f4c153788c32c8a5dc4f58db3b..75735d85ddd13db8f1168b6ae5869d11db33c94e 100644 (file)
@@ -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;
     }