All static resources such as index.html will not be found when application
is added with <Context path="/" docBase="../../../"/>, for example tomcat
is put inside the application's META-INF.

I've drilled down that the AbstractFileResourceSet class is responsible for
this behaviour, inside the protected final File file(String name, boolean
mustExist) method. There absoluteBase and canonicalBase (absolute, unique
with resolved symlinks) are used to determine if the file should be
accessed based on a case sensitivity check.

Everything works fine if the docBase is not just path like ../../.././../
but has an actual directory at the end, like ../../../web-app. However in
this edgy case the difference appears since the behaviour of
the org.apache.tomcat.util.http.RequestUtil.normalize method has slightly
different behavior than the File.getCanonicalPath.

System.out.println(RequestUtil.normalize("/base/1/2/3/../../../"));
/base/

System.out.println(RequestUtil.normalize("/base/1/2/3/../../.."));
/base/1/..
System.out.println(new File("/base/1/2/3/../../../").getCanonicalPath());
/base

The added /from RequestUtil breakes the logic inside the file method, since
when doing the substring operation inside AbstractFileResourceSet.file
method it may or may not have a trailing /. In such situation <whatever
path>/index.html substring with the absoluteBase becomes ndex.html. At the
end the file method returns from here:

        if (!canPath.equals(absPath)) // !"index.html".equals("ndex.html")
=> true
                    return null;

The RequestUtil comes from the http packages and follows their conventions
when normalizing the path, so an obvious way to fix this is to add and if
statement after the normalization
inside AbstractFileResourceSet.initInternal.

        this.absoluteBase = normalize(absolutePath);
        if (this.absoluteBase.endsWith("/")) {
        this.absoluteBase = this.absoluteBase.substring(0,
this.absoluteBase.length() - 1);
        }

With Java 7 instead of using the RequestUtil for normalization, Path
java.nio.file.Path.normalize() can accomplish the correct thing.

Do you think that is something that can be fixed? Maybe the above is not
the best approach, however it's the least invasive.

Best Regards
Dimitar Valov

Reply via email to