Hello,

org.apache.tomcat.util.FileUtil.safePath() had a bug (at least from my point of 
view) that was preventing use of "\\machine\share" paths in context docBases, 
yielding a 404 on those contexts.

The patch was obtained with a "diff -u <old> <new>", I don't know if that's ok. 
  I've made some testing, and the reasons that lead to safePath implementation 
in TC32 are still held, I believe (no paths fall outside docBase, case 
sensitiveness enforced, Win oddities like "*.jsp." prevented).  I haven't 
tested on *nix or netware, but the scope of the changes doesn't seem that big 
(but feel free to ignore them or apply only on the next bug fix release ;-)

Regards,

-- 
Rogério Meneguelli Gatto     |  ICQ# 25775025
Analista de Sistemas Pleno   |  +55 19 3254-6518 ext 223
Software Design Informática  |  http://www.softwaredesign.com.br
God is a comic playing to an audience that's afraid to laugh
--- /usr/tomcat32b8/src/org/apache/tomcat/util/FileUtil.java    Tue Nov 21 00:59:54 
2000
+++ FileUtil.java       Tue Nov 28 18:02:53 2000
@@ -67,6 +67,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.util.Locale;
+import java.util.StringTokenizer;
 
 /*
  * FileUtil contains utils for dealing with Files. Some of these are 
@@ -83,6 +84,7 @@
  */
 
 public class FileUtil {
+    public static final String PATH_SEPARATORS = "/" + File.separatorChar;
 
     public static File[] listFiles(File dir) {
 
@@ -134,47 +136,32 @@
        // Hack for Jsp ( and other servlets ) that use rel. paths 
        // if( ! path.startsWith("/") ) path="/"+ path;
 
-       String normP=path;
-       if( path.indexOf('\\') >=0 )
-           normP= path.replace('\\', '/');
-
-       if ( !normP.startsWith("/"))
-           normP = "/" + normP;
-
-       int index = normP.indexOf("/../");
-       if (index >= 0) {
-
-           // Clean out "//" and "/./" so they will not be confused
-           // with real parent directories
-           int index2 = 0;
-           while ((index2 = normP.indexOf("//", index2)) >= 0) {
-               normP = normP.substring(0, index2) +
-                   normP.substring(index2 + 1);
-               if (index2 < index)
-                   index--;
-           }
-           index2 = 0;
-           while ((index2 = normP.indexOf("/./", index2)) >= 0) {
-               normP = normP.substring(0, index2) +
-                   normP.substring(index2 + 2);
-               if (index2 < index)
-                   index -= 2;
-           }
-
-           // Remove cases of "/{directory}/../"
-           while (index >= 0) {
-               // If no parent directory to remove, return null
-               if (index == 0)
-                   return (null);      // Trying to leave our context
-               index2 = normP.lastIndexOf('/', index-1);
-               normP = normP.substring(0, index2) +
-                   normP.substring(index + 3);
-               index = normP.indexOf("/../", index2);
-           }
-
-       }
+        // Splits path into its componentes and normalize it
+        StringTokenizer tk = new StringTokenizer(path, PATH_SEPARATORS, false);
+        String[] comp = new String[tk.countTokens()];
+        int length = 0;
+        while (tk.hasMoreTokens()) {
+            String component = tk.nextToken();
+            if (component.length() == 0 || component.equals(".")) {
+                // Empty path component, ignore
+                continue;
+            } else if (component.equals("..")) {
+                // Remove last component.
+                if (--length < 0) {
+                    // No last component to remove, trying to leave our context
+                    return null;
+                };
+            } else {
+                // Normal component, append
+                comp[length++] = component;
+            }
+        }
+        StringBuffer buf = new StringBuffer(base);
+        for (int i = 0; i < length; i++) {
+            buf.append(File.separatorChar).append(comp[i]);
+        }
 
-       String realPath= base + normP;
+       String realPath = buf.toString();
 
        // Probably not needed - it will be used on the local FS
        realPath = FileUtil.patch(realPath);

Reply via email to