Refactor WebDAV servlet escaping for XML. Add test case.
diff --git a/java/org/apache/catalina/servlets/WebdavServlet.java b/java/org/apache/catalina/servlets/WebdavServlet.java
index 096ed5a..3844853 100644
--- a/java/org/apache/catalina/servlets/WebdavServlet.java
+++ b/java/org/apache/catalina/servlets/WebdavServlet.java
@@ -52,7 +52,6 @@
import org.apache.catalina.WebResource;
import org.apache.catalina.connector.RequestFacade;
import org.apache.catalina.util.DOMWriter;
-import org.apache.catalina.util.URLEncoder;
import org.apache.catalina.util.XMLWriter;
import org.apache.tomcat.util.buf.HexUtils;
import org.apache.tomcat.util.http.ConcurrentDateFormat;
@@ -140,15 +139,6 @@
// -------------------------------------------------------------- Constants
- private static final URLEncoder URL_ENCODER_XML;
- static {
- URL_ENCODER_XML = (URLEncoder) URLEncoder.DEFAULT.clone();
- // Remove '&' from the safe character set since while it it permitted
- // in a URI path, it is not permitted in XML and encoding it is a simple
- // way to address this.
- URL_ENCODER_XML.removeSafeCharacter('&');
- }
-
private static final String METHOD_PROPFIND = "PROPFIND";
private static final String METHOD_PROPPATCH = "PROPPATCH";
private static final String METHOD_MKCOL = "MKCOL";
@@ -391,18 +381,6 @@
/**
- * URL rewriter.
- *
- * @param path Path which has to be rewritten
- * @return the rewritten path
- */
- @Override
- protected String rewriteUrl(String path) {
- return URL_ENCODER_XML.encode(path, StandardCharsets.UTF_8);
- }
-
-
- /**
* Override the DefaultServlet implementation and only use the PathInfo. If
* the ServletPath is non-null, it will be because the WebDAV servlet has
* been mapped to a url other than /* to configure editing at different url
diff --git a/java/org/apache/catalina/util/XMLWriter.java b/java/org/apache/catalina/util/XMLWriter.java
index 019c4b9..8290b73 100644
--- a/java/org/apache/catalina/util/XMLWriter.java
+++ b/java/org/apache/catalina/util/XMLWriter.java
@@ -19,6 +19,8 @@
import java.io.IOException;
import java.io.Writer;
+import org.apache.tomcat.util.security.Escape;
+
/**
* XMLWriter helper class.
*/
@@ -199,7 +201,7 @@
* @param text Text to append
*/
public void writeText(String text) {
- buffer.append(text);
+ buffer.append(Escape.xml(text));
}
diff --git a/test/org/apache/catalina/servlets/TestWebdavServlet.java b/test/org/apache/catalina/servlets/TestWebdavServlet.java
index fdf61a0..0ce1683 100644
--- a/test/org/apache/catalina/servlets/TestWebdavServlet.java
+++ b/test/org/apache/catalina/servlets/TestWebdavServlet.java
@@ -18,18 +18,25 @@
import java.io.File;
import java.io.IOException;
+import java.io.StringReader;
import java.util.List;
import java.util.Map;
+import javax.xml.parsers.SAXParserFactory;
+
import jakarta.servlet.http.HttpServletResponse;
import org.junit.Assert;
import org.junit.Test;
+import org.apache.catalina.Context;
+import org.apache.catalina.Wrapper;
+import org.apache.catalina.startup.SimpleHttpClient;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;
import org.apache.tomcat.websocket.server.WsContextListener;
+import org.xml.sax.InputSource;
public class TestWebdavServlet extends TomcatBaseTest {
@@ -149,4 +156,45 @@
return TomcatBaseTest.getUrl(path, out, resHead);
}
+ /*
+ * Bug 66609
+ */
+ @Test
+ public void testDirectoryListing() throws Exception {
+ Tomcat tomcat = getTomcatInstance();
+
+ File appDir = new File("test/webapp");
+ Context ctxt = tomcat.addContext("", appDir.getAbsolutePath());
+
+ Wrapper defaultServlet = Tomcat.addServlet(ctxt, "webdav", new WebdavServlet());
+ defaultServlet.addInitParameter("listings", "true");
+
+ ctxt.addServletMappingDecoded("/*", "webdav");
+ ctxt.addMimeMapping("html", "text/html");
+
+ tomcat.start();
+
+ Client client = new Client();
+ client.setPort(getPort());
+ client.setRequest(new String[] { "PROPFIND /bug66609/ HTTP/1.1" + SimpleHttpClient.CRLF +
+ "Host: localhost:" + getPort() + SimpleHttpClient.CRLF +
+ SimpleHttpClient.CRLF});
+ client.connect();
+ client.sendRequest();
+
+ client.setUseContentLength(true);
+ client.readResponse(true);
+
+ // This will throw an exception if the XML is not valid
+ SAXParserFactory.newInstance().newSAXParser().getXMLReader().parse(new InputSource(new StringReader(client.getResponseBody())));
+ }
+
+
+ private static final class Client extends SimpleHttpClient {
+
+ @Override
+ public boolean isResponseBodyOK() {
+ return true;
+ }
+ }
}