X-Git-Url: https://code.wpia.club/?p=gigi.git;a=blobdiff_plain;f=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Fhttp%2FHttpParser.java;fp=lib%2Fjetty%2Forg%2Feclipse%2Fjetty%2Fhttp%2FHttpParser.java;h=e1ddee838c22aac3a90d4fb195986c294b135bca;hp=79f1c28d90d407a0d9469e9dd26b27270442a362;hb=aa5723dbb64ec8efa63909d39ff72364f0a5ee96;hpb=e443f19911df6a30ab07ef70d23970bda671b194
diff --git a/lib/jetty/org/eclipse/jetty/http/HttpParser.java b/lib/jetty/org/eclipse/jetty/http/HttpParser.java
index 79f1c28d..e1ddee83 100644
--- a/lib/jetty/org/eclipse/jetty/http/HttpParser.java
+++ b/lib/jetty/org/eclipse/jetty/http/HttpParser.java
@@ -1,6 +1,6 @@
//
// ========================================================================
-// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
+// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
@@ -18,6 +18,8 @@
package org.eclipse.jetty.http;
+import static org.eclipse.jetty.http.HttpTokens.*;
+
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@@ -35,7 +37,7 @@ import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** A Parser for HTTP 0.9, 1.0 and 1.1
*
- * The is parser parses HTTP client and server messages from buffers
+ * This parser parses HTTP client and server messages from buffers
* passed in the {@link #parseNext(ByteBuffer)} method. The parsed
* elements of the HTTP message are passed as event calls to the
* {@link HttpHandler} instance the parser is constructed with.
@@ -115,6 +117,7 @@ public class HttpParser
CHUNK_SIZE,
CHUNK_PARAMS,
CHUNK,
+ CHUNK_END,
END,
CLOSED
}
@@ -329,33 +332,31 @@ public class HttpParser
}
/* ------------------------------------------------------------------------------- */
- private static class BadMessage extends Error
+ @SuppressWarnings("serial")
+ private static class BadMessageException extends RuntimeException
{
- private static final long serialVersionUID = 1L;
private final int _code;
- private final String _message;
- BadMessage()
+ private BadMessageException()
{
this(400,null);
}
- BadMessage(int code)
+ private BadMessageException(int code)
{
this(code,null);
}
- BadMessage(String message)
+ private BadMessageException(String message)
{
this(400,message);
}
- BadMessage(int code,String message)
+ private BadMessageException(int code,String message)
{
+ super(message);
_code=code;
- _message=message;
}
-
}
/* ------------------------------------------------------------------------------- */
@@ -365,23 +366,23 @@ public class HttpParser
if (_cr)
{
- if (ch!=HttpTokens.LINE_FEED)
- throw new BadMessage("Bad EOL");
+ if (ch!=LINE_FEED)
+ throw new BadMessageException("Bad EOL");
_cr=false;
return ch;
}
- if (ch>=0 && ch=0 && ch0 && _state.ordinal() HttpTokens.SPACE)
+ if (ch > SPACE)
{
_string.setLength(0);
_string.append((char)ch);
@@ -443,13 +444,13 @@ public class HttpParser
else if (ch==0)
break;
else if (ch<0)
- throw new BadMessage();
+ throw new BadMessageException();
// count this white space as a header byte to avoid DOS
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
{
LOG.warn("padding is too large >"+_maxHeaderBytes);
- throw new BadMessage(HttpStatus.BAD_REQUEST_400);
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400);
}
}
return false;
@@ -493,7 +494,7 @@ public class HttpParser
if (_state==State.URI)
{
LOG.warn("URI is too large >"+_maxHeaderBytes);
- throw new BadMessage(HttpStatus.REQUEST_URI_TOO_LONG_414);
+ throw new BadMessageException(HttpStatus.REQUEST_URI_TOO_LONG_414);
}
else
{
@@ -501,14 +502,14 @@ public class HttpParser
LOG.warn("request is too large >"+_maxHeaderBytes);
else
LOG.warn("response is too large >"+_maxHeaderBytes);
- throw new BadMessage(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
+ throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
}
}
switch (_state)
{
case METHOD:
- if (ch == HttpTokens.SPACE)
+ if (ch == SPACE)
{
_length=_string.length();
_methodString=takeString();
@@ -517,8 +518,13 @@ public class HttpParser
_methodString=method.asString();
setState(State.SPACE1);
}
- else if (ch < HttpTokens.SPACE)
- throw new BadMessage(ch<0?"Illegal character":"No URI");
+ else if (ch < SPACE)
+ {
+ if (ch==LINE_FEED)
+ throw new BadMessageException("No URI");
+ else
+ throw new IllegalCharacterException(_state,ch,buffer);
+ }
else
_string.append((char)ch);
break;
@@ -530,11 +536,11 @@ public class HttpParser
String version=takeString();
_version=HttpVersion.CACHE.get(version);
if (_version==null)
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Unknown Version");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Unknown Version");
setState(State.SPACE1);
}
else if (ch < HttpTokens.SPACE)
- throw new BadMessage(ch<0?"Illegal character":"No Status");
+ throw new IllegalCharacterException(_state,ch,buffer);
else
_string.append((char)ch);
break;
@@ -567,7 +573,7 @@ public class HttpParser
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
{
LOG.warn("URI is too large >"+_maxHeaderBytes);
- throw new BadMessage(HttpStatus.REQUEST_URI_TOO_LONG_414);
+ throw new BadMessageException(HttpStatus.REQUEST_URI_TOO_LONG_414);
}
if (_uri.remaining()<=len)
{
@@ -585,7 +591,7 @@ public class HttpParser
}
else if (ch < HttpTokens.SPACE)
{
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,_requestHandler!=null?"No URI":"No Status");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,_requestHandler!=null?"No URI":"No Status");
}
break;
@@ -605,7 +611,7 @@ public class HttpParser
}
else
{
- throw new BadMessage();
+ throw new BadMessageException();
}
break;
@@ -623,6 +629,7 @@ public class HttpParser
BufferUtil.clear(buffer);
handle=_handler.headerComplete()||handle;
handle=_handler.messageComplete()||handle;
+ return handle;
}
else
{
@@ -662,7 +669,7 @@ public class HttpParser
if (_method==HttpMethod.PROXY)
{
if (!(_requestHandler instanceof ProxyHandler))
- throw new BadMessage();
+ throw new BadMessageException();
_uri.flip();
String protocol=BufferUtil.toString(_uri);
@@ -718,10 +725,11 @@ public class HttpParser
BufferUtil.clear(buffer);
handle=_handler.headerComplete()||handle;
handle=_handler.messageComplete()||handle;
+ return handle;
}
}
else if (ch<0)
- throw new BadMessage();
+ throw new BadMessageException();
break;
case REQUEST_VERSION:
@@ -733,7 +741,7 @@ public class HttpParser
_version=HttpVersion.CACHE.get(takeString());
}
if (_version==null)
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Unknown Version");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Unknown Version");
// Should we try to cache header fields?
if (_connectionFields==null && _version.getVersion()>=HttpVersion.HTTP_1_1.getVersion())
@@ -750,7 +758,7 @@ public class HttpParser
else if (ch>=HttpTokens.SPACE)
_string.append((char)ch);
else
- throw new BadMessage();
+ throw new BadMessageException();
break;
@@ -770,7 +778,7 @@ public class HttpParser
_length=_string.length();
}
else
- throw new BadMessage();
+ throw new BadMessageException();
break;
default:
@@ -797,7 +805,7 @@ public class HttpParser
catch(NumberFormatException e)
{
LOG.ignore(e);
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Content-Length");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Content-Length");
}
if (_contentLength <= 0)
_endOfContent=EndOfContent.NO_CONTENT;
@@ -815,7 +823,7 @@ public class HttpParser
_endOfContent=EndOfContent.CHUNKED_CONTENT;
else if (_valueString.contains(HttpHeaderValue.CHUNKED.toString()))
{
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad chunking");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad chunking");
}
}
break;
@@ -827,7 +835,7 @@ public class HttpParser
int port=0;
if (host==null || host.length()==0)
{
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Host header");
}
int len=host.length();
@@ -849,7 +857,7 @@ public class HttpParser
{
if (DEBUG)
LOG.debug(e);
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad Host header");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad Host header");
}
break loop;
}
@@ -858,9 +866,9 @@ public class HttpParser
{
if (host.charAt(len-1)!=']')
{
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"Bad IPv6 Host header");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Bad IPv6 Host header");
}
- host = host.substring(1,len-1);
+ host = host.substring(0,len);
}
else if (len!=host.length())
host = host.substring(0,len);
@@ -922,7 +930,7 @@ public class HttpParser
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
{
LOG.warn("Header is too large >"+_maxHeaderBytes);
- throw new BadMessage(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
+ throw new BadMessageException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413);
}
switch (_state)
@@ -980,9 +988,9 @@ public class HttpParser
// End of headers!
// Was there a required host header?
- if (!_host && _version!=HttpVersion.HTTP_1_0 && _requestHandler!=null)
+ if (!_host && _version==HttpVersion.HTTP_1_1 && _requestHandler!=null)
{
- throw new BadMessage(HttpStatus.BAD_REQUEST_400,"No Host");
+ throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"No Host");
}
// is it a response that cannot have a body?
@@ -1010,27 +1018,27 @@ public class HttpParser
case EOF_CONTENT:
setState(State.EOF_CONTENT);
handle=_handler.headerComplete()||handle;
- break;
+ return handle;
case CHUNKED_CONTENT:
setState(State.CHUNKED_CONTENT);
handle=_handler.headerComplete()||handle;
- break;
+ return handle;
case NO_CONTENT:
handle=_handler.headerComplete()||handle;
setState(State.END);
handle=_handler.messageComplete()||handle;
- break;
+ return handle;
default:
setState(State.CONTENT);
handle=_handler.headerComplete()||handle;
- break;
+ return handle;
}
}
else if (ch<=HttpTokens.SPACE)
- throw new BadMessage();
+ throw new BadMessageException();
else
{
if (buffer.hasRemaining())
@@ -1147,8 +1155,8 @@ public class HttpParser
_length=_string.length();
break;
}
-
- throw new BadMessage("Illegal character");
+
+ throw new IllegalCharacterException(_state,ch,buffer);
case HEADER_VALUE:
if (ch>HttpTokens.SPACE || ch<0)
@@ -1172,8 +1180,8 @@ public class HttpParser
setState(State.HEADER);
break;
}
-
- throw new BadMessage("Illegal character");
+
+ throw new IllegalCharacterException(_state,ch,buffer);
case HEADER_IN_VALUE:
if (ch>=HttpTokens.SPACE || ch<0 || ch==HttpTokens.TAB)
@@ -1201,7 +1209,8 @@ public class HttpParser
setState(State.HEADER);
break;
}
- throw new BadMessage("Illegal character");
+
+ throw new IllegalCharacterException(_state,ch,buffer);
default:
throw new IllegalStateException(_state.toString());
@@ -1256,8 +1265,7 @@ public class HttpParser
if (_responseStatus>0 && _headResponse)
{
setState(State.END);
- if (_handler.messageComplete())
- return true;
+ return _handler.messageComplete();
}
else
{
@@ -1280,7 +1288,7 @@ public class HttpParser
// Just ignore data when closed
_headerBytes+=buffer.remaining();
BufferUtil.clear(buffer);
- if (_headerBytes>_maxHeaderBytes)
+ if (_maxHeaderBytes>0 && _headerBytes>_maxHeaderBytes)
{
// Don't want to waste time reading data of a closed request
throw new IllegalStateException("too much data after closed");
@@ -1329,15 +1337,15 @@ public class HttpParser
return false;
}
- catch(BadMessage e)
+ catch(BadMessageException e)
{
BufferUtil.clear(buffer);
- LOG.warn("badMessage: "+e._code+(e._message!=null?" "+e._message:"")+" for "+_handler);
+ LOG.warn("badMessage: "+e._code+(e.getMessage()!=null?" "+e.getMessage():"")+" for "+_handler);
if (DEBUG)
LOG.debug(e);
setState(State.CLOSED);
- _handler.badMessage(e._code, e._message);
+ _handler.badMessage(e._code, e.getMessage());
return false;
}
catch(Exception e)
@@ -1372,8 +1380,7 @@ public class HttpParser
if (content == 0)
{
setState(State.END);
- if (_handler.messageComplete())
- return true;
+ return _handler.messageComplete();
}
}
@@ -1397,8 +1404,7 @@ public class HttpParser
if (content == 0)
{
setState(State.END);
- if (_handler.messageComplete())
- return true;
+ return _handler.messageComplete();
}
else
{
@@ -1421,8 +1427,7 @@ public class HttpParser
if(_contentPosition == _contentLength)
{
setState(State.END);
- if (_handler.messageComplete())
- return true;
+ return _handler.messageComplete();
}
}
break;
@@ -1449,11 +1454,7 @@ public class HttpParser
if (ch == HttpTokens.LINE_FEED)
{
if (_chunkLength == 0)
- {
- setState(State.END);
- if (_handler.messageComplete())
- return true;
- }
+ setState(State.CHUNK_END);
else
setState(State.CHUNK);
}
@@ -1470,11 +1471,7 @@ public class HttpParser
if (ch == HttpTokens.LINE_FEED)
{
if (_chunkLength == 0)
- {
- setState(State.END);
- if (_handler.messageComplete())
- return true;
- }
+ setState(State.CHUNK_END);
else
setState(State.CHUNK);
}
@@ -1505,6 +1502,20 @@ public class HttpParser
break;
}
+ case CHUNK_END:
+ {
+ // TODO handle chunk trailer
+ ch=next(buffer);
+ if (ch==0)
+ break;
+ if (ch == HttpTokens.LINE_FEED)
+ {
+ setState(State.END);
+ return _handler.messageComplete();
+ }
+ throw new IllegalCharacterException(_state,ch,buffer);
+ }
+
case CLOSED:
{
BufferUtil.clear(buffer);
@@ -1577,6 +1588,29 @@ public class HttpParser
_state=state;
}
+ /* ------------------------------------------------------------------------------- */
+ public Trie getFieldCache()
+ {
+ return _connectionFields;
+ }
+
+ /* ------------------------------------------------------------------------------- */
+ private String getProxyField(ByteBuffer buffer)
+ {
+ _string.setLength(0);
+ _length=0;
+
+ while (buffer.hasRemaining())
+ {
+ // process each character
+ byte ch=next(buffer);
+ if (ch<=' ')
+ return _string.toString();
+ _string.append((char)ch);
+ }
+ throw new BadMessageException();
+ }
+
/* ------------------------------------------------------------------------------- */
@Override
public String toString()
@@ -1632,11 +1666,17 @@ public class HttpParser
public int getHeaderCacheSize();
}
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
public interface ProxyHandler
{
void proxied(String protocol, String sAddr, String dAddr, int sPort, int dPort);
}
-
+
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
public interface RequestHandler extends HttpHandler
{
/**
@@ -1657,6 +1697,9 @@ public class HttpParser
public abstract boolean parsedHostHeader(String host,int port);
}
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
+ /* ------------------------------------------------------------------------------- */
public interface ResponseHandler extends HttpHandler
{
/**
@@ -1665,24 +1708,15 @@ public class HttpParser
public abstract boolean startResponse(HttpVersion version, int status, String reason);
}
- public Trie getFieldCache()
- {
- return _connectionFields;
- }
-
- private String getProxyField(ByteBuffer buffer)
+ /* ------------------------------------------------------------------------------- */
+ @SuppressWarnings("serial")
+ private static class IllegalCharacterException extends BadMessageException
{
- _string.setLength(0);
- _length=0;
-
- while (buffer.hasRemaining())
+ private IllegalCharacterException(State state,byte ch,ByteBuffer buffer)
{
- // process each character
- byte ch=next(buffer);
- if (ch<=' ')
- return _string.toString();
- _string.append((char)ch);
+ super(400,String.format("Illegal character 0x%X",ch));
+ // Bug #460642 - don't reveal buffers to end user
+ LOG.warn(String.format("Illegal character 0x%X in state=%s for buffer %s",ch,state,BufferUtil.toDetailString(buffer)));
}
- throw new BadMessage();
}
}