379423 Jetty URL Decoding fails for certain international characters

This commit is contained in:
Jan Bartel 2012-08-03 17:20:58 +10:00
parent c998abc8bc
commit 3f07564274
4 changed files with 71 additions and 8 deletions

View File

@ -581,6 +581,55 @@ public class HttpURI
_utf8b.append(bytes,0,n); _utf8b.append(bytes,0,n);
return _utf8b.toString(); return _utf8b.toString();
} }
public String getDecodedPath(String encoding)
{
if (_path==_param)
return null;
int length = _param-_path;
byte[] bytes=null;
int n=0;
for (int i=_path;i<_param;i++)
{
byte b = _raw[i];
if (b=='%')
{
if ((i+2)>=_param)
throw new IllegalArgumentException("Bad % encoding: "+this);
b=(byte)(0xff&TypeUtil.parseInt(_raw,i+1,2,16));
i+=2;
}
else if (bytes==null)
{
n++;
continue;
}
if (bytes==null)
{
bytes=new byte[length];
System.arraycopy(_raw,_path,bytes,0,n);
}
bytes[n++]=b;
}
if (bytes==null)
return StringUtil.toString(_raw,_path,_param-_path,encoding);
return StringUtil.toString(bytes,0,n,encoding);
}
public String getPathAndParam() public String getPathAndParam()
{ {

View File

@ -437,7 +437,20 @@ public abstract class AbstractHttpConnection extends AbstractConnection
try try
{ {
_uri.getPort(); _uri.getPort();
info=URIUtil.canonicalPath(_uri.getDecodedPath()); String path = null;
try
{
path = _uri.getDecodedPath();
}
catch (Exception e)
{
LOG.warn("Failed UTF-8 decode for request path, trying ISO-8859-1");
LOG.ignore(e);
path = _uri.getDecodedPath(StringUtil.__ISO_8859_1);
}
info=URIUtil.canonicalPath(path);
if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT)) if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT))
{ {
if (_uri.getScheme()!=null && _uri.getHost()!=null) if (_uri.getScheme()!=null && _uri.getHost()!=null)

View File

@ -189,12 +189,12 @@ public class HttpConnectionTest
response=connector.getResponses("GET /foo/bar%c0%00 HTTP/1.1\n"+ response=connector.getResponses("GET /foo/bar%c0%00 HTTP/1.1\n"+
"Host: localhost\n"+ "Host: localhost\n"+
"\015\012"); "\015\012");
checkContains(response,0,"HTTP/1.1 400"); checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1
response=connector.getResponses("GET /bad/utf8%c1 HTTP/1.1\n"+ response=connector.getResponses("GET /bad/utf8%c1 HTTP/1.1\n"+
"Host: localhost\n"+ "Host: localhost\n"+
"\015\012"); "\015\012");
checkContains(response,0,"HTTP/1.1 400"); checkContains(response,0,"HTTP/1.1 200"); //now fallback to iso-8859-1
} }
finally finally
{ {

View File

@ -181,10 +181,11 @@ public class HttpURITest
private final String[][] encoding_tests= private final String[][] encoding_tests=
{ {
/* 0*/ {"/path/info","/path/info"}, /* 0*/ {"/path/info","/path/info", "UTF-8"},
/* 1*/ {"/path/%69nfo","/path/info"}, /* 1*/ {"/path/%69nfo","/path/info", "UTF-8"},
/* 2*/ {"http://host/path/%69nfo","/path/info"}, /* 2*/ {"http://host/path/%69nfo","/path/info", "UTF-8"},
/* 3*/ {"http://host/path/%69nf%c2%a4","/path/inf\u00a4"}, /* 3*/ {"http://host/path/%69nf%c2%a4","/path/inf\u00a4", "UTF-8"},
/* 4*/ {"http://host/path/%E5", "/path/\u00e5", "ISO-8859-1"}
}; };
@Test @Test
@ -195,7 +196,7 @@ public class HttpURITest
for (int t=0;t<encoding_tests.length;t++) for (int t=0;t<encoding_tests.length;t++)
{ {
uri.parse(encoding_tests[t][0]); uri.parse(encoding_tests[t][0]);
assertEquals(""+t,encoding_tests[t][1],uri.getDecodedPath()); assertEquals(""+t,encoding_tests[t][1],uri.getDecodedPath(encoding_tests[t][2]));
} }
} }