Author: bdelacretaz
Date: Mon Jan 5 08:15:27 2009
New Revision: 731608
URL: http://svn.apache.org/viewvc?rev=731608&view=rev
Log:
SLING-760 - move escaping code to DefaultErrorHandlerServlet (and
SlingMainServlet, but that's only used as a last resort IIUC) and add tests
Added:
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
(with props)
incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/
incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
Modified:
incubator/sling/trunk/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/HttpTestBase.java
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/ResponseUtil.java
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
incubator/sling/trunk/engine/src/test/java/org/apache/sling/engine/ResponseUtilTest.java
incubator/sling/trunk/servlets/resolver/pom.xml
incubator/sling/trunk/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/defaults/DefaultErrorHandlerServlet.java
Modified:
incubator/sling/trunk/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/HttpTestBase.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/HttpTestBase.java?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
---
incubator/sling/trunk/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/HttpTestBase.java
(original)
+++
incubator/sling/trunk/commons/testing/src/main/java/org/apache/sling/commons/testing/integration/HttpTestBase.java
Mon Jan 5 08:15:27 2009
@@ -27,6 +27,8 @@
import java.util.List;
import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+
import junit.framework.TestCase;
import org.apache.commons.httpclient.Credentials;
@@ -282,11 +284,15 @@
return getContent(url, expectedContentType, null);
}
+ protected String getContent(String url, String expectedContentType,
List<NameValuePair> params) throws IOException {
+ return getContent(url, expectedContentType, params,
HttpServletResponse.SC_OK);
+ }
+
/** retrieve the contents of given URL and assert its content type
* @param expectedContentType use CONTENT_TYPE_DONTCARE if must not be
checked
* @throws IOException
* @throws HttpException */
- protected String getContent(String url, String expectedContentType,
List<NameValuePair> params) throws IOException {
+ protected String getContent(String url, String expectedContentType,
List<NameValuePair> params, int expectedStatusCode) throws IOException {
final GetMethod get = new GetMethod(url);
if(params != null) {
final NameValuePair [] nvp = new NameValuePair[0];
@@ -301,7 +307,8 @@
while( (n = is.read(buffer, 0, buffer.length)) > 0) {
content.append(new String(buffer, 0, n, charset));
}
- assertEquals("Expected status 200 for " + url + " (content=" + content
+ ")",200,status);
+ assertEquals("Expected status " + expectedStatusCode + " for " + url +
" (content=" + content + ")",
+ expectedStatusCode,status);
final Header h = get.getResponseHeader("Content-Type");
if(expectedContentType == null) {
if(h!=null) {
Modified:
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/ResponseUtil.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/ResponseUtil.java?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
---
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/ResponseUtil.java
(original)
+++
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/ResponseUtil.java
Mon Jan 5 08:15:27 2009
@@ -18,9 +18,65 @@
*/
package org.apache.sling.engine;
+import java.io.IOException;
+import java.io.Writer;
+
/** Response-related utilities */
public class ResponseUtil {
+ private static class XmlEscapingWriter extends Writer {
+ private final Writer target;
+
+ XmlEscapingWriter(Writer target) {
+ this.target = target;
+ }
+
+ @Override
+ public void close() throws IOException {
+ target.close();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ target.flush();
+ }
+
+ @Override
+ public void write(char[] buffer, int offset, int length) throws
IOException {
+ for(int i = offset; i < offset + length; i++) {
+ write(buffer[i]);
+ }
+ }
+
+ @Override
+ public void write(char[] cbuf) throws IOException {
+ write(cbuf, 0, cbuf.length);
+ }
+
+ @Override
+ public void write(int c) throws IOException {
+ if(c == '&') {
+ target.write("&");
+ } else if(c == '<') {
+ target.write("<");
+ } else if(c == '>') {
+ target.write(">");
+ } else {
+ target.write(c);
+ }
+ }
+
+ @Override
+ public void write(String str, int off, int len) throws IOException {
+ write(str.toCharArray(), off, len);
+ }
+
+ @Override
+ public void write(String str) throws IOException {
+ write(str.toCharArray());
+ }
+ }
+
/** Escape xml text */
public static String escapeXml(String input) {
if(input == null) {
@@ -42,4 +98,10 @@
}
return b.toString();
}
+
+ /** Return a Writer that writes escaped XML text to target
+ */
+ public static Writer getXmlEscapingWriter(Writer target) {
+ return new XmlEscapingWriter(target);
+ }
}
Modified:
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
---
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
(original)
+++
incubator/sling/trunk/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
Mon Jan 5 08:15:27 2009
@@ -58,6 +58,7 @@
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.commons.mime.MimeTypeService;
+import org.apache.sling.engine.ResponseUtil;
import org.apache.sling.engine.impl.auth.MissingRepositoryException;
import org.apache.sling.engine.impl.auth.SlingAuthenticator;
import org.apache.sling.engine.impl.filter.RequestSlingFilterChain;
@@ -516,17 +517,17 @@
PrintWriter pw = response.getWriter();
pw.println("<html><head><title>");
- pw.println(message);
+ pw.println(ResponseUtil.escapeXml(message));
pw.println("</title></head><body><h1>");
if (throwable != null) {
- pw.println(throwable.toString());
+ pw.println(ResponseUtil.escapeXml(throwable.toString()));
} else if (message != null) {
- pw.println(message);
+ pw.println(ResponseUtil.escapeXml(message));
} else {
pw.println("Internal error (no Exception to report)");
}
pw.println("</h1><p>");
- pw.println("RequestURI=" + request.getRequestURI());
+ pw.println("RequestURI=" +
ResponseUtil.escapeXml(request.getRequestURI()));
if (servletName != null) {
pw.println("</p>Servlet=" + servletName + "<p>");
}
Modified:
incubator/sling/trunk/engine/src/test/java/org/apache/sling/engine/ResponseUtilTest.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/engine/src/test/java/org/apache/sling/engine/ResponseUtilTest.java?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
---
incubator/sling/trunk/engine/src/test/java/org/apache/sling/engine/ResponseUtilTest.java
(original)
+++
incubator/sling/trunk/engine/src/test/java/org/apache/sling/engine/ResponseUtilTest.java
Mon Jan 5 08:15:27 2009
@@ -16,6 +16,10 @@
*/
package org.apache.sling.engine;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+
import junit.framework.TestCase;
public class ResponseUtilTest extends TestCase {
@@ -31,4 +35,12 @@
assertEquals("<bonnie> & </clyde> && others",
ResponseUtil.escapeXml("<bonnie> & </clyde> && others"));
}
+
+ public void testXmlEscapingWriter() throws IOException {
+ final StringWriter sw = new StringWriter();
+ final Writer w = ResponseUtil.getXmlEscapingWriter(sw);
+ w.write("<bonnie> & </clyde> && others");
+ w.flush();
+ assertEquals("<bonnie> & </clyde> && others",
sw.toString());
+ }
}
Added:
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java?rev=731608&view=auto
==============================================================================
---
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
(added)
+++
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
Mon Jan 5 08:15:27 2009
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.launchpad.webapp.integrationtest.issues;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.sling.commons.testing.integration.HttpTestBase;
+
+public class SLING760Test extends HttpTestBase {
+ public static final String TEST_PATH = "/" +
SLING760Test.class.getSimpleName();
+
+ /** Verify that all instances of our error message are escaped in
response, which
+ * is generated by the default Sling error handler */
+ public void testEscapedErrorMessages() throws Exception {
+ final String [] mustContain = { "<characters/>", "filtered &
escaped" };
+ final String [] mustNotContain = { "<characters/>", "filtered &
escaped" };
+
+ final TestNode tn = new TestNode(HTTP_BASE_URL + TEST_PATH, null);
+
+ try {
+ uploadTestScript(tn.scriptPath,
"issues/sling760/throw-with-markup.esp", "html.esp");
+ final String content = getContent(tn.nodeUrl + ".html",
CONTENT_TYPE_HTML,
+ null, HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+
+ for(String str : mustContain) {
+ assertTrue("Content must contain " + str + " (" + content +
")", content.contains(str));
+ }
+
+ for(String str : mustNotContain) {
+ assertFalse("Content must NOT contain " + str + " (" + content
+ ")", content.contains(str));
+ }
+ } finally {
+ tn.delete();
+ }
+ }
+}
Propchange:
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
------------------------------------------------------------------------------
svn:eol-style = native
Propchange:
incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/issues/SLING760Test.java
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision Rev URL
Added:
incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp?rev=731608&view=auto
==============================================================================
---
incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
(added)
+++
incubator/sling/trunk/launchpad/testing/src/test/resources/integration-test/issues/sling760/throw-with-markup.esp
Mon Jan 5 08:15:27 2009
@@ -0,0 +1,5 @@
+<%
+// SLING-760: test an error message with characters that must
+// be escaped
+throw("This string contains <characters/> that must be filtered & escaped");
+%>
\ No newline at end of file
Modified: incubator/sling/trunk/servlets/resolver/pom.xml
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/servlets/resolver/pom.xml?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
--- incubator/sling/trunk/servlets/resolver/pom.xml (original)
+++ incubator/sling/trunk/servlets/resolver/pom.xml Mon Jan 5 08:15:27 2009
@@ -89,7 +89,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.engine</artifactId>
- <version>2.0.2-incubator</version>
+ <version>2.0.3-incubator-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
Modified:
incubator/sling/trunk/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/defaults/DefaultErrorHandlerServlet.java
URL:
http://svn.apache.org/viewvc/incubator/sling/trunk/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/defaults/DefaultErrorHandlerServlet.java?rev=731608&r1=731607&r2=731608&view=diff
==============================================================================
---
incubator/sling/trunk/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/defaults/DefaultErrorHandlerServlet.java
(original)
+++
incubator/sling/trunk/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/defaults/DefaultErrorHandlerServlet.java
Mon Jan 5 08:15:27 2009
@@ -30,6 +30,7 @@
import org.apache.sling.api.SlingConstants;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.request.RequestProgressTracker;
+import org.apache.sling.engine.ResponseUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -66,17 +67,22 @@
// write the exception message
if (req.getAttribute(SlingConstants.ERROR_EXCEPTION) instanceof
Throwable) {
+ final PrintWriter escapingWriter = new
PrintWriter(ResponseUtil.getXmlEscapingWriter(pw));
Throwable throwable = (Throwable)
req.getAttribute(SlingConstants.ERROR_EXCEPTION);
pw.println("<h3>Exception:</h3>");
pw.println("<pre>");
- printStackTrace(pw, throwable);
+ pw.flush();
+ printStackTrace(escapingWriter, throwable);
+ escapingWriter.flush();
pw.println("</pre>");
if (req instanceof SlingHttpServletRequest) {
RequestProgressTracker tracker = ((SlingHttpServletRequest)
req).getRequestProgressTracker();
pw.println("<h3>Request Progress:</h3>");
pw.println("<pre>");
- tracker.dump(pw);
+ pw.flush();
+ tracker.dump(escapingWriter);
+ escapingWriter.flush();
pw.println("</pre>");
}
}
@@ -118,9 +124,11 @@
* response HTML text with the header, and an introductory phrase.
*/
private PrintWriter sendIntro(HttpServletResponse response, int statusCode,
- String statusMessage, String requestUri, String servletName)
+ String statusMessageIn, String requestUri, String servletName)
throws IOException {
+ final String statusMessage = ResponseUtil.escapeXml(statusMessageIn);
+
// set the status code and content type in the response
final PrintWriter pw = response.getWriter();
if(!response.isCommitted()) {
@@ -139,7 +147,7 @@
log.warn("Response already committed, unable to change status,
output might not be well formed");
}
pw.println("<h1>" + statusMessage + " (" + statusCode + ")</h1>");
- pw.print("<p>The requested URL " + requestUri
+ pw.print("<p>The requested URL " + ResponseUtil.escapeXml(requestUri)
+ " resulted in an error");
if (servletName != null) {