Merge remote-tracking branch 'origin/jetty-9.2.x'
Conflicts: jetty-http-spi/src/main/java/org/eclipse/jetty/http/spi/HttpSpiContextHandler.java jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java jetty-websocket/websocket-server/src/main/java/org/eclipse/jetty/websocket/server/WebSocketServerFactory.java
This commit is contained in:
commit
69bf5ab46c
|
@ -29,7 +29,9 @@ import javax.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.util.Jetty;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
import org.eclipse.jetty.util.log.Log;
|
||||||
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
import com.sun.net.httpserver.Authenticator;
|
import com.sun.net.httpserver.Authenticator;
|
||||||
import com.sun.net.httpserver.Authenticator.Result;
|
import com.sun.net.httpserver.Authenticator.Result;
|
||||||
|
@ -43,6 +45,7 @@ import com.sun.net.httpserver.HttpPrincipal;
|
||||||
*/
|
*/
|
||||||
public class HttpSpiContextHandler extends ContextHandler
|
public class HttpSpiContextHandler extends ContextHandler
|
||||||
{
|
{
|
||||||
|
public static final Logger LOG = Log.getLogger(HttpSpiContextHandler.class);
|
||||||
|
|
||||||
private HttpContext _httpContext;
|
private HttpContext _httpContext;
|
||||||
|
|
||||||
|
@ -88,16 +91,20 @@ public class HttpSpiContextHandler extends ContextHandler
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
LOG.debug(ex);
|
||||||
PrintWriter writer = new PrintWriter(jettyHttpExchange.getResponseBody());
|
PrintWriter writer = new PrintWriter(jettyHttpExchange.getResponseBody());
|
||||||
|
|
||||||
resp.setStatus(500);
|
resp.setStatus(500);
|
||||||
writer.println("<h2>HTTP ERROR: 500</h2>");
|
writer.println("<h2>HTTP ERROR: 500</h2>");
|
||||||
writer.println("<pre>INTERNAL_SERVER_ERROR</pre>");
|
writer.println("<pre>INTERNAL_SERVER_ERROR</pre>");
|
||||||
writer.println("<p>RequestURI=" + req.getRequestURI() + "</p>");
|
writer.println("<p>RequestURI=" + StringUtil.sanitizeXmlString(req.getRequestURI()) + "</p>");
|
||||||
|
|
||||||
|
if (LOG.isDebugEnabled())
|
||||||
|
{
|
||||||
writer.println("<pre>");
|
writer.println("<pre>");
|
||||||
ex.printStackTrace(writer);
|
ex.printStackTrace(writer);
|
||||||
writer.println("</pre>");
|
writer.println("</pre>");
|
||||||
|
}
|
||||||
|
|
||||||
baseRequest.getHttpChannel().getHttpConfiguration().writePoweredBy(writer,"<p>","</p>");
|
baseRequest.getHttpChannel().getHttpConfiguration().writePoweredBy(writer,"<p>","</p>");
|
||||||
|
|
||||||
|
|
|
@ -577,19 +577,9 @@ public class Response implements HttpServletResponse
|
||||||
setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
|
setContentType(MimeTypes.Type.TEXT_HTML_8859_1.toString());
|
||||||
try (ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);)
|
try (ByteArrayISO8859Writer writer= new ByteArrayISO8859Writer(2048);)
|
||||||
{
|
{
|
||||||
if (message != null)
|
message=StringUtil.sanitizeXmlString(message);
|
||||||
{
|
|
||||||
message= StringUtil.replace(message, "&", "&");
|
|
||||||
message= StringUtil.replace(message, "<", "<");
|
|
||||||
message= StringUtil.replace(message, ">", ">");
|
|
||||||
}
|
|
||||||
String uri= request.getRequestURI();
|
String uri= request.getRequestURI();
|
||||||
if (uri!=null)
|
uri=StringUtil.sanitizeXmlString(uri);
|
||||||
{
|
|
||||||
uri= StringUtil.replace(uri, "&", "&");
|
|
||||||
uri= StringUtil.replace(uri, "<", "<");
|
|
||||||
uri= StringUtil.replace(uri, ">", ">");
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
|
writer.write("<html>\n<head>\n<meta http-equiv=\"Content-Type\" content=\"text/html;charset=ISO-8859-1\"/>\n");
|
||||||
writer.write("<title>Error ");
|
writer.write("<title>Error ");
|
||||||
|
|
|
@ -40,6 +40,7 @@ import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.util.BufferUtil;
|
import org.eclipse.jetty.util.BufferUtil;
|
||||||
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
|
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
|
||||||
import org.eclipse.jetty.util.Jetty;
|
import org.eclipse.jetty.util.Jetty;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
|
||||||
|
@ -278,29 +279,7 @@ public class ErrorHandler extends AbstractHandler
|
||||||
if (string==null)
|
if (string==null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (int i=0;i<string.length();i++)
|
writer.write(StringUtil.sanitizeXmlString(string));
|
||||||
{
|
|
||||||
char c=string.charAt(i);
|
|
||||||
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '&' :
|
|
||||||
writer.write("&");
|
|
||||||
break;
|
|
||||||
case '<' :
|
|
||||||
writer.write("<");
|
|
||||||
break;
|
|
||||||
case '>' :
|
|
||||||
writer.write(">");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
|
||||||
writer.write('?');
|
|
||||||
else
|
|
||||||
writer.write(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
|
|
@ -746,6 +746,74 @@ public class StringUtil
|
||||||
return s.substring(1,s.length()-1).split(" *, *");
|
return s.substring(1,s.length()-1).split(" *, *");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String sanitizeXmlString(String html)
|
||||||
|
{
|
||||||
|
if (html==null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
int i=0;
|
||||||
|
|
||||||
|
// Are there any characters that need sanitizing?
|
||||||
|
loop: for (;i<html.length();i++)
|
||||||
|
{
|
||||||
|
char c=html.charAt(i);
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '&' :
|
||||||
|
case '<' :
|
||||||
|
case '>' :
|
||||||
|
case '\'':
|
||||||
|
case '"':
|
||||||
|
break loop;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
||||||
|
break loop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No characters need sanitizing, so return original string
|
||||||
|
if (i==html.length())
|
||||||
|
return html;
|
||||||
|
|
||||||
|
// Create builder with OK content so far
|
||||||
|
StringBuilder out = new StringBuilder(html.length()*4/3);
|
||||||
|
out.append(html,0,i);
|
||||||
|
|
||||||
|
// sanitize remaining content
|
||||||
|
for (;i<html.length();i++)
|
||||||
|
{
|
||||||
|
char c=html.charAt(i);
|
||||||
|
|
||||||
|
switch(c)
|
||||||
|
{
|
||||||
|
case '&' :
|
||||||
|
out.append("&");
|
||||||
|
break;
|
||||||
|
case '<' :
|
||||||
|
out.append("<");
|
||||||
|
break;
|
||||||
|
case '>' :
|
||||||
|
out.append(">");
|
||||||
|
break;
|
||||||
|
case '\'':
|
||||||
|
out.append("'");
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
out.append(""");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (Character.isISOControl(c) && !Character.isWhitespace(c))
|
||||||
|
out.append('?');
|
||||||
|
else
|
||||||
|
out.append(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
/** The String value of an Object
|
/** The String value of an Object
|
||||||
|
|
|
@ -660,7 +660,7 @@ public abstract class Resource implements ResourceFactory, Closeable
|
||||||
|
|
||||||
private static String deTag(String raw)
|
private static String deTag(String raw)
|
||||||
{
|
{
|
||||||
return StringUtil.replace( StringUtil.replace(raw,"<","<"), ">", ">");
|
return StringUtil.sanitizeXmlString(raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------ */
|
/* ------------------------------------------------------------ */
|
||||||
|
|
|
@ -201,7 +201,8 @@ public class StringUtilTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsBlank() {
|
public void testIsBlank()
|
||||||
|
{
|
||||||
Assert.assertTrue(StringUtil.isBlank(null));
|
Assert.assertTrue(StringUtil.isBlank(null));
|
||||||
Assert.assertTrue(StringUtil.isBlank(""));
|
Assert.assertTrue(StringUtil.isBlank(""));
|
||||||
Assert.assertTrue(StringUtil.isBlank("\r\n"));
|
Assert.assertTrue(StringUtil.isBlank("\r\n"));
|
||||||
|
@ -216,7 +217,8 @@ public class StringUtilTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testIsNotBlank() {
|
public void testIsNotBlank()
|
||||||
|
{
|
||||||
Assert.assertFalse(StringUtil.isNotBlank(null));
|
Assert.assertFalse(StringUtil.isNotBlank(null));
|
||||||
Assert.assertFalse(StringUtil.isNotBlank(""));
|
Assert.assertFalse(StringUtil.isNotBlank(""));
|
||||||
Assert.assertFalse(StringUtil.isNotBlank("\r\n"));
|
Assert.assertFalse(StringUtil.isNotBlank("\r\n"));
|
||||||
|
@ -229,4 +231,14 @@ public class StringUtilTest
|
||||||
Assert.assertTrue(StringUtil.isNotBlank("."));
|
Assert.assertTrue(StringUtil.isNotBlank("."));
|
||||||
Assert.assertTrue(StringUtil.isNotBlank(";\n"));
|
Assert.assertTrue(StringUtil.isNotBlank(";\n"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSanitizeHTML()
|
||||||
|
{
|
||||||
|
assertEquals(null,StringUtil.sanitizeXmlString(null));
|
||||||
|
assertEquals("",StringUtil.sanitizeXmlString(""));
|
||||||
|
assertEquals("<&>",StringUtil.sanitizeXmlString("<&>"));
|
||||||
|
assertEquals("Hello <Cruel> World",StringUtil.sanitizeXmlString("Hello <Cruel> World"));
|
||||||
|
assertEquals("Hello ? World",StringUtil.sanitizeXmlString("Hello \u0000 World"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.eclipse.jetty.server.HttpConnection;
|
||||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||||
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
import org.eclipse.jetty.util.DecoratedObjectFactory;
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
import org.eclipse.jetty.util.component.ContainerLifeCycle;
|
||||||
import org.eclipse.jetty.util.log.Log;
|
import org.eclipse.jetty.util.log.Log;
|
||||||
import org.eclipse.jetty.util.log.Logger;
|
import org.eclipse.jetty.util.log.Logger;
|
||||||
|
@ -526,7 +527,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Upgrade the request/response to a WebSocket Connection.
|
* Upgrade the request/response to a WebSocket Connection.
|
||||||
* <p>
|
* <p/>
|
||||||
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
|
* This method will not normally return, but will instead throw a UpgradeConnectionException, to exit HTTP handling and initiate WebSocket handling of the
|
||||||
* connection.
|
* connection.
|
||||||
*
|
*
|
||||||
|
@ -568,7 +569,7 @@ public class WebSocketServerFactory extends ContainerLifeCycle implements WebSoc
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
warn.append('"').append(ua.replaceAll("<", "<")).append("\" ");
|
warn.append('"').append(StringUtil.sanitizeXmlString(ua)).append("\" ");
|
||||||
}
|
}
|
||||||
warn.append("requested WebSocket version [").append(version);
|
warn.append("requested WebSocket version [").append(version);
|
||||||
warn.append("], Jetty supports version");
|
warn.append("], Jetty supports version");
|
||||||
|
|
|
@ -25,6 +25,8 @@ import java.io.OutputStreamWriter;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
|
||||||
public class XmlAppendable
|
public class XmlAppendable
|
||||||
{
|
{
|
||||||
private final String SPACES=" ";
|
private final String SPACES=" ";
|
||||||
|
@ -82,32 +84,7 @@ public class XmlAppendable
|
||||||
public XmlAppendable content(String s) throws IOException
|
public XmlAppendable content(String s) throws IOException
|
||||||
{
|
{
|
||||||
if (s!=null)
|
if (s!=null)
|
||||||
{
|
_out.append(StringUtil.sanitizeXmlString(s));
|
||||||
for (int i=0;i<s.length();i++)
|
|
||||||
{
|
|
||||||
char c = s.charAt(i);
|
|
||||||
switch(c)
|
|
||||||
{
|
|
||||||
case '<':
|
|
||||||
_out.append("<");
|
|
||||||
break;
|
|
||||||
case '>':
|
|
||||||
_out.append(">");
|
|
||||||
break;
|
|
||||||
case '&':
|
|
||||||
_out.append("&");
|
|
||||||
break;
|
|
||||||
case '\'':
|
|
||||||
_out.append("'");
|
|
||||||
break;
|
|
||||||
case '"':
|
|
||||||
_out.append(""");
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
_out.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue