Author: markt Date: Fri May 9 21:02:10 2014 New Revision: 1593621 URL: http://svn.apache.org/r1593621 Log: Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=56501 HttpServletRequest.getContextPath() should return the undecoded context path used by the user agent.
Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java tomcat/trunk/java/org/apache/catalina/mapper/MappingData.java tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java tomcat/trunk/webapps/docs/changelog.xml Modified: tomcat/trunk/java/org/apache/catalina/connector/Request.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/connector/Request.java?rev=1593621&r1=1593620&r2=1593621&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/connector/Request.java (original) +++ tomcat/trunk/java/org/apache/catalina/connector/Request.java Fri May 9 21:02:10 2014 @@ -1894,7 +1894,17 @@ public class Request */ @Override public String getContextPath() { - return mappingData.contextPath.toString(); + String uri = getRequestURI(); + int lastSlash = mappingData.contextSlashCount; + int pos = 0; + while (lastSlash > 0) { + pos = uri.indexOf('/', pos + 1); + if (pos == -1) { + return uri; + } + lastSlash--; + } + return uri.substring(0, pos); } Modified: tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java?rev=1593621&r1=1593620&r2=1593621&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java (original) +++ tomcat/trunk/java/org/apache/catalina/mapper/Mapper.java Fri May 9 21:02:10 2014 @@ -229,6 +229,7 @@ public final class Mapper { new ContextVersion[contextVersions.length + 1]; ContextVersion newContextVersion = new ContextVersion(); newContextVersion.path = path; + newContextVersion.slashCount = slashCount; newContextVersion.name = version; newContextVersion.object = context; newContextVersion.welcomeResources = welcomeResources; @@ -799,6 +800,7 @@ public final class Mapper { } } mappingData.context = contextVersion.object; + mappingData.contextSlashCount = contextVersion.slashCount; } // Wrapper mapping @@ -1480,6 +1482,7 @@ public final class Mapper { protected static final class ContextVersion extends MapElement<Context> { public String path = null; + public int slashCount; public String[] welcomeResources = new String[0]; public WebResourceRoot resources = null; public MappedWrapper defaultWrapper = null; Modified: tomcat/trunk/java/org/apache/catalina/mapper/MappingData.java URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/mapper/MappingData.java?rev=1593621&r1=1593620&r2=1593621&view=diff ============================================================================== --- tomcat/trunk/java/org/apache/catalina/mapper/MappingData.java (original) +++ tomcat/trunk/java/org/apache/catalina/mapper/MappingData.java Fri May 9 21:02:10 2014 @@ -31,6 +31,7 @@ public class MappingData { public Host host = null; public Context context = null; + public int contextSlashCount = 0; public Context[] contexts = null; public Wrapper wrapper = null; public boolean jspWildCard = false; @@ -45,6 +46,7 @@ public class MappingData { public void recycle() { host = null; context = null; + contextSlashCount = 0; contexts = null; wrapper = null; jspWildCard = false; Modified: tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java?rev=1593621&r1=1593620&r2=1593621&view=diff ============================================================================== --- tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java (original) +++ tomcat/trunk/test/org/apache/catalina/connector/TestRequest.java Fri May 9 21:02:10 2014 @@ -685,4 +685,114 @@ public class TestRequest extends TomcatB fail("OK status was expected: " + status); } } + + @Test + public void testBug56501a() throws Exception { + doBug56501("/path", "/path", "/path"); + } + + @Test + public void testBug56501b() throws Exception { + doBug56501("/path", "/path/", "/path"); + } + + @Test + public void testBug56501c() throws Exception { + doBug56501("/path", "/path/xxx", "/path"); + } + + @Test + public void testBug56501d() throws Exception { + doBug56501("", "", ""); + } + + @Test + public void testBug56501e() throws Exception { + doBug56501("", "/", ""); + } + + @Test + public void testBug56501f() throws Exception { + doBug56501("", "/xxx", ""); + } + + @Test + public void testBug56501g() throws Exception { + doBug56501("/path/abc", "/path/abc", "/path/abc"); + } + + @Test + public void testBug56501h() throws Exception { + doBug56501("/path/abc", "/path/abc/", "/path/abc"); + } + + @Test + public void testBug56501i() throws Exception { + doBug56501("/path/abc", "/path/abc/xxx", "/path/abc"); + } + + @Test + public void testBug56501j() throws Exception { + doBug56501("/pa_th/abc", "/pa%5Fth/abc", "/pa%5Fth/abc"); + } + + @Test + public void testBug56501k() throws Exception { + doBug56501("/pa_th/abc", "/pa%5Fth/abc/", "/pa%5Fth/abc"); + } + + @Test + public void testBug56501l() throws Exception { + doBug56501("/pa_th/abc", "/pa%5Fth/abc/xxx", "/pa%5Fth/abc"); + } + + @Test + public void testBug56501m() throws Exception { + doBug56501("/pa_th/abc", "/pa_th/abc", "/pa_th/abc"); + } + + @Test + public void testBug56501n() throws Exception { + doBug56501("/pa_th/abc", "/pa_th/abc/", "/pa_th/abc"); + } + + @Test + public void testBug56501o() throws Exception { + doBug56501("/pa_th/abc", "/pa_th/abc/xxx", "/pa_th/abc"); + } + + private void doBug56501(String deployPath, String requestPath, String expected) + throws Exception { + + // Setup Tomcat instance + Tomcat tomcat = getTomcatInstance(); + + // Must have a real docBase - just use temp + Context ctx = tomcat.addContext(deployPath, + System.getProperty("java.io.tmpdir")); + + Tomcat.addServlet(ctx, "servlet", new Bug56501Servelet()); + ctx.addServletMapping("/*", "servlet"); + + tomcat.start(); + + ByteChunk res = getUrl("http://localhost:" + getPort() + requestPath); + String resultPath = res.toString(); + if (resultPath == null) { + resultPath = ""; + } + assertEquals(expected, resultPath); + } + + private class Bug56501Servelet extends HttpServlet { + + private static final long serialVersionUID = 1L; + + @Override + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + resp.setContentType("text/plain"); + resp.getWriter().print(req.getContextPath()); + } + } } Modified: tomcat/trunk/webapps/docs/changelog.xml URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1593621&r1=1593620&r2=1593621&view=diff ============================================================================== --- tomcat/trunk/webapps/docs/changelog.xml (original) +++ tomcat/trunk/webapps/docs/changelog.xml Fri May 9 21:02:10 2014 @@ -173,6 +173,10 @@ Make the naming context tokens for containers more robust by using a separate object. (markt/kkolinko) </fix> + <fix> + <bug>56501</bug>: <code>HttpServletRequest.getContextPath()</code> + should return the undecoded context path used by the user agent. (markt) + </fix> </changelog> </subsection> <subsection name="Coyote"> --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org