#1792 Accept ISO-8859-1 in Response reason

This commit is contained in:
Greg Wilkins 2017-09-05 17:29:49 +10:00
parent 7be350370c
commit ca750cf582
4 changed files with 82 additions and 62 deletions

View File

@ -28,6 +28,7 @@ import org.eclipse.jetty.http.HttpTokens.EndOfContent;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.ArrayTrie;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.Trie;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
@ -618,8 +619,8 @@ public class HttpParser
while (_state.ordinal()<State.HEADER.ordinal() && buffer.hasRemaining() && !handle)
{
// process each character
byte ch=next(buffer);
if (ch==0)
byte b=next(buffer);
if (b==0)
break;
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
@ -642,7 +643,7 @@ public class HttpParser
switch (_state)
{
case METHOD:
if (ch == SPACE)
if (b == SPACE)
{
_length=_string.length();
_methodString=takeString();
@ -651,19 +652,19 @@ public class HttpParser
_methodString=legacyString(_methodString,method.asString());
setState(State.SPACE1);
}
else if (ch < SPACE)
else if (b < SPACE)
{
if (ch==LINE_FEED)
if (b==LINE_FEED)
throw new BadMessageException("No URI");
else
throw new IllegalCharacterException(_state,ch,buffer);
throw new IllegalCharacterException(_state,b,buffer);
}
else
_string.append((char)ch);
_string.append((char)b);
break;
case RESPONSE_VERSION:
if (ch == HttpTokens.SPACE)
if (b == HttpTokens.SPACE)
{
_length=_string.length();
String version=takeString();
@ -672,19 +673,19 @@ public class HttpParser
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,"Unknown Version");
setState(State.SPACE1);
}
else if (ch < HttpTokens.SPACE)
throw new IllegalCharacterException(_state,ch,buffer);
else if (b < HttpTokens.SPACE)
throw new IllegalCharacterException(_state,b,buffer);
else
_string.append((char)ch);
_string.append((char)b);
break;
case SPACE1:
if (ch > HttpTokens.SPACE || ch<0)
if (b > HttpTokens.SPACE || b<0)
{
if (_responseHandler!=null)
{
setState(State.STATUS);
setResponseStatus(ch-'0');
setResponseStatus(b-'0');
}
else
{
@ -712,25 +713,25 @@ public class HttpParser
buffer.position(i-buffer.arrayOffset());
}
else
_uri.append(ch);
_uri.append(b);
}
}
else if (ch < HttpTokens.SPACE)
else if (b < HttpTokens.SPACE)
{
throw new BadMessageException(HttpStatus.BAD_REQUEST_400,_requestHandler!=null?"No URI":"No Status");
}
break;
case STATUS:
if (ch == HttpTokens.SPACE)
if (b == HttpTokens.SPACE)
{
setState(State.SPACE2);
}
else if (ch>='0' && ch<='9')
else if (b>='0' && b<='9')
{
_responseStatus=_responseStatus*10+(ch-'0');
_responseStatus=_responseStatus*10+(b-'0');
}
else if (ch < HttpTokens.SPACE && ch>=0)
else if (b < HttpTokens.SPACE && b>=0)
{
setState(State.HEADER);
handle=_responseHandler.startResponse(_version, _responseStatus, null)||handle;
@ -742,11 +743,11 @@ public class HttpParser
break;
case URI:
if (ch == HttpTokens.SPACE)
if (b == HttpTokens.SPACE)
{
setState(State.SPACE2);
}
else if (ch < HttpTokens.SPACE && ch>=0)
else if (b < HttpTokens.SPACE && b>=0)
{
// HTTP/0.9
if (complianceViolation(RFC7230,"HTTP/0.9"))
@ -758,15 +759,15 @@ public class HttpParser
}
else
{
_uri.append(ch);
_uri.append(b);
}
break;
case SPACE2:
if (ch > HttpTokens.SPACE)
if (b > HttpTokens.SPACE)
{
_string.setLength(0);
_string.append((char)ch);
_string.append((char)b);
if (_responseHandler!=null)
{
_length=1;
@ -806,7 +807,7 @@ public class HttpParser
}
}
}
else if (ch == HttpTokens.LINE_FEED)
else if (b == HttpTokens.LINE_FEED)
{
if (_responseHandler!=null)
{
@ -825,12 +826,12 @@ public class HttpParser
handle= handleHeaderContentMessage() || handle;
}
}
else if (ch<0)
else if (b<0)
throw new BadMessageException();
break;
case REQUEST_VERSION:
if (ch == HttpTokens.LINE_FEED)
if (b == HttpTokens.LINE_FEED)
{
if (_version==null)
{
@ -852,25 +853,25 @@ public class HttpParser
handle=_requestHandler.startRequest(_methodString,_uri.toString(), _version)||handle;
continue;
}
else if (ch>=HttpTokens.SPACE)
_string.append((char)ch);
else if (b>=HttpTokens.SPACE)
_string.append((char)b);
else
throw new BadMessageException();
break;
case REASON:
if (ch == HttpTokens.LINE_FEED)
if (b == HttpTokens.LINE_FEED)
{
String reason=takeString();
setState(State.HEADER);
handle=_responseHandler.startResponse(_version, _responseStatus, reason)||handle;
continue;
}
else if (ch>=HttpTokens.SPACE)
else if (b>=HttpTokens.SPACE || ((b<0) && (b>=-96)))
{
_string.append((char)ch);
if (ch!=' '&&ch!='\t')
_string.append((char)(0xff&b));
if (b!=' '&&b!='\t')
_length=_string.length();
}
else
@ -1008,8 +1009,8 @@ public class HttpParser
while ((_state==State.HEADER || _state==State.TRAILER) && buffer.hasRemaining())
{
// process each character
byte ch=next(buffer);
if (ch==0)
byte b=next(buffer);
if (b==0)
break;
if (_maxHeaderBytes>0 && ++_headerBytes>_maxHeaderBytes)
@ -1024,7 +1025,7 @@ public class HttpParser
switch (_fieldState)
{
case FIELD:
switch(ch)
switch(b)
{
case HttpTokens.COLON:
case HttpTokens.SPACE:
@ -1127,7 +1128,7 @@ public class HttpParser
default:
{
// now handle the ch
if (ch<HttpTokens.SPACE)
if (b<HttpTokens.SPACE)
throw new BadMessageException();
// process previous header
@ -1185,15 +1186,15 @@ public class HttpParser
{
// Header and value
int pos=buffer.position()+n.length()+v.length()+1;
byte b=buffer.get(pos);
byte peek=buffer.get(pos);
if (b==HttpTokens.CARRIAGE_RETURN || b==HttpTokens.LINE_FEED)
if (peek==HttpTokens.CARRIAGE_RETURN || peek==HttpTokens.LINE_FEED)
{
_field=field;
_valueString=v;
setState(FieldState.IN_VALUE);
if (b==HttpTokens.CARRIAGE_RETURN)
if (peek==HttpTokens.CARRIAGE_RETURN)
{
_cr=true;
buffer.position(pos+1);
@ -1216,7 +1217,7 @@ public class HttpParser
// New header
setState(FieldState.IN_NAME);
_string.setLength(0);
_string.append((char)ch);
_string.append((char)b);
_length=1;
}
@ -1224,7 +1225,7 @@ public class HttpParser
break;
case IN_NAME:
if (ch==HttpTokens.COLON)
if (b==HttpTokens.COLON)
{
if (_headerString==null)
{
@ -1237,7 +1238,7 @@ public class HttpParser
break;
}
if (ch>HttpTokens.SPACE)
if (b>HttpTokens.SPACE)
{
if (_header!=null)
{
@ -1246,13 +1247,13 @@ public class HttpParser
_headerString=null;
}
_string.append((char)ch);
if (ch>HttpTokens.SPACE)
_string.append((char)b);
if (b>HttpTokens.SPACE)
_length=_string.length();
break;
}
if (ch==HttpTokens.LINE_FEED && !complianceViolation(RFC7230,"name only header"))
if (b==HttpTokens.LINE_FEED && !complianceViolation(RFC7230,"name only header"))
{
if (_headerString==null)
{
@ -1268,21 +1269,21 @@ public class HttpParser
break;
}
throw new IllegalCharacterException(_state,ch,buffer);
throw new IllegalCharacterException(_state,b,buffer);
case VALUE:
if (ch>HttpTokens.SPACE || ch<0)
if (b>HttpTokens.SPACE || b<0)
{
_string.append((char)(0xff&ch));
_string.append((char)(0xff&b));
_length=_string.length();
setState(FieldState.IN_VALUE);
break;
}
if (ch==HttpTokens.SPACE || ch==HttpTokens.TAB)
if (b==HttpTokens.SPACE || b==HttpTokens.TAB)
break;
if (ch==HttpTokens.LINE_FEED)
if (b==HttpTokens.LINE_FEED)
{
_value=null;
_string.setLength(0);
@ -1292,10 +1293,10 @@ public class HttpParser
setState(FieldState.FIELD);
break;
}
throw new IllegalCharacterException(_state,ch,buffer);
throw new IllegalCharacterException(_state,b,buffer);
case IN_VALUE:
if (ch>=HttpTokens.SPACE || ch<0 || ch==HttpTokens.TAB)
if (b>=HttpTokens.SPACE || b<0 || b==HttpTokens.TAB)
{
if (_valueString!=null)
{
@ -1303,13 +1304,13 @@ public class HttpParser
_valueString=null;
_field=null;
}
_string.append((char)(0xff&ch));
if (ch>HttpTokens.SPACE || ch<0)
_string.append((char)(0xff&b));
if (b>HttpTokens.SPACE || b<0)
_length=_string.length();
break;
}
if (ch==HttpTokens.LINE_FEED)
if (b==HttpTokens.LINE_FEED)
{
if (_length > 0)
{
@ -1321,7 +1322,7 @@ public class HttpParser
break;
}
throw new IllegalCharacterException(_state,ch,buffer);
throw new IllegalCharacterException(_state,b,buffer);
default:
throw new IllegalStateException(_state.toString());

View File

@ -155,7 +155,7 @@ public class HttpGeneratorServerTest
assertEquals(HttpGenerator.Result.NEED_INFO, result);
assertEquals(HttpGenerator.State.START, gen.getState());
MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, null, new HttpFields(), 10);
MetaData.Response info = new MetaData.Response(HttpVersion.HTTP_1_1, 200, "ØÆ", new HttpFields(), 10);
info.getFields().add("Content-Type", "test/data;\r\nextra=value");
info.getFields().add("Last-Modified", DateGenerator.__01Jan1970);
@ -176,7 +176,7 @@ public class HttpGeneratorServerTest
assertEquals(10, gen.getContentPrepared());
assertThat(response, containsString("HTTP/1.1 200 OK"));
assertThat(response, containsString("HTTP/1.1 200 ØÆ"));
assertThat(response, containsString("Last-Modified: Thu, 01 Jan 1970 00:00:00 GMT"));
assertThat(response, containsString("Content-Type: test/data; extra=value"));
assertThat(response, containsString("Content-Length: 10"));

View File

@ -573,7 +573,9 @@ public class HttpParserTest
BufferUtil.put(BufferUtil.toBuffer(" HTTP/1.0\r\n"), buffer);
BufferUtil.put(BufferUtil.toBuffer("Header1: "), buffer);
buffer.put("\u00e6 \u00e6".getBytes(StandardCharsets.ISO_8859_1));
BufferUtil.put(BufferUtil.toBuffer(" \r\n\r\n"), buffer);
BufferUtil.put(BufferUtil.toBuffer(" \r\nHeader2: "), buffer);
buffer.put((byte)-1);
BufferUtil.put(BufferUtil.toBuffer("\r\n\r\n"), buffer);
BufferUtil.flipToFlush(buffer, 0);
HttpParser.RequestHandler handler = new Handler();
@ -585,7 +587,9 @@ public class HttpParserTest
Assert.assertEquals("HTTP/1.0", _versionOrReason);
Assert.assertEquals("Header1", _hdr[0]);
Assert.assertEquals("\u00e6 \u00e6", _val[0]);
Assert.assertEquals(0, _headers);
Assert.assertEquals("Header2", _hdr[1]);
Assert.assertEquals(""+(char)255, _val[1]);
Assert.assertEquals(1, _headers);
Assert.assertEquals(null, _bad);
}
@ -1304,6 +1308,22 @@ public class HttpParserTest
Assert.assertTrue(_messageCompleted);
}
@Test
public void testResponseReasonIso8859_1() throws Exception
{
ByteBuffer buffer = BufferUtil.toBuffer(
"HTTP/1.1 302 déplacé temporairement\r\n"
+ "Content-Length: 0\r\n"
+ "\r\n",StandardCharsets.ISO_8859_1);
HttpParser.ResponseHandler handler = new Handler();
HttpParser parser = new HttpParser(handler);
parser.parseNext(buffer);
Assert.assertEquals("HTTP/1.1", _methodOrVersion);
Assert.assertEquals("302", _uriOrStatus);
Assert.assertEquals("déplacé temporairement", _versionOrReason);
}
@Test
public void testSeekEOF() throws Exception
{

View File

@ -1056,5 +1056,4 @@ public class StringUtil
{
return object==null?null:String.valueOf(object);
}
}