HttpField.contains ignores ;q=0 items

This commit is contained in:
Greg Wilkins 2014-07-11 16:08:18 +10:00
parent 5e281dd449
commit f594a6fc66
2 changed files with 219 additions and 15 deletions

View File

@ -25,6 +25,7 @@ import java.util.ArrayList;
*/ */
public class HttpField public class HttpField
{ {
private final static String __zeroquality="q=0";
private final HttpHeader _header; private final HttpHeader _header;
private final String _name; private final String _name;
private final String _value; private final String _value;
@ -180,28 +181,187 @@ public class HttpField
/** Look for a value in a possible multi valued field /** Look for a value in a possible multi valued field
* @param search Values to search for * @param search Values to search for
* @return True iff the value is contained in the field value entirely or * @return True iff the value is contained in the field value entirely or
* as an element of a quoted comma separated list. List element parameters (eg qualities) are ignored. * as an element of a quoted comma separated list. List element parameters (eg qualities) are ignored,
* except if they are q=0, in which case the item itself is ignored.
*/ */
public boolean contains(String search) public boolean contains(String search)
{ {
if (_value==null || search==null) if (_value==null || search==null)
return _value==search; return _value==search;
if (search.length()==0)
return false;
if (_value.equals(search)) int state=0;
return true; int match=0;
int param=0;
String[] values = getValues(); for (int i=0;i<_value.length();i++)
for (String v:values)
{ {
if (v.equals(search)) char c = _value.charAt(i);
return true; switch(state)
if (v.startsWith(search) && v.charAt(search.length())==';') {
return true; case 0: // initial white space
switch(c)
{
case '"': // open quote
match=0;
state=2;
break;
case ',': // ignore leading empty field
break;
case ';': // ignore leading empty field parameter
param=-1;
match=-1;
state=5;
break;
case ' ': // more white space
case '\t':
break;
default: // character
match = c==search.charAt(0)?1:-1;
state=1;
break;
}
break;
case 1: // In token
switch(c)
{
case ',': // next field
// Have we matched the token?
if (match==search.length())
return true;
state=0;
break;
case ';':
param=match>=0?0:-1;
state=5; // parameter
break;
default:
if (match>0)
{
if (match<search.length())
match=c==search.charAt(match)?(match+1):-1;
else if (c!=' ' && c!= '\t')
match=-1;
}
break;
}
break;
case 2: // In Quoted token
switch(c)
{
case '\\': // quoted character
state=3;
break;
case '"': // end quote
state=4;
break;
default:
if (match>=0)
{
if (match<search.length())
match=c==search.charAt(match)?(match+1):-1;
else
match=-1;
}
}
break;
case 3: // In Quoted character in quoted token
if (match>=0)
{
if (match<search.length())
match=c==search.charAt(match)?(match+1):-1;
else
match=-1;
}
state=2;
break;
case 4: // WS after end quote
switch(c)
{
case ' ': // white space
case '\t': // white space
break;
case ';':
state=5; // parameter
break;
case ',': // end token
// Have we matched the token?
if (match==search.length())
return true;
state=0;
break;
default:
// This is an illegal token, just ignore
match=-1;
}
break;
case 5: // parameter
switch(c)
{
case ',': // end token
// Have we matched the token and not q=0?
if (param!=__zeroquality.length() && match==search.length())
return true;
param=0;
state=0;
break;
case ' ': // white space
case '\t': // white space
break;
default:
if (param>=0)
{
if (param<__zeroquality.length())
param=c==__zeroquality.charAt(param)?(param+1):-1;
else if (c!='0'&&c!='.'&&c!=' ')
param=-1;
}
}
break;
default:
throw new IllegalStateException();
}
} }
return false; return param!=__zeroquality.length() && match==search.length();
} }
@Override @Override
public String toString() public String toString()
{ {

View File

@ -73,8 +73,52 @@ public class HttpFieldTest
} }
@Test
public void testQualityContainsList() throws Exception
{
HttpField field;
field = new HttpField("name","yes");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name",",yes,");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","other,yes,other");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","other, yes ,other");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","other, y s ,other");
assertTrue(field.contains("y s"));
assertFalse(field.contains("no"));
field = new HttpField("name","other, \"yes\" ,other");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","other, \"\\\"yes\\\"\" ,other");
assertTrue(field.contains("\"yes\""));
assertFalse(field.contains("no"));
field = new HttpField("name",";no,yes,;no");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","no;q=0,yes;q=1,no; q = 0");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
field = new HttpField("name","no;q=0.0000,yes;q=0.0001,no; q = 0.00000");
assertTrue(field.contains("yes"));
assertFalse(field.contains("no"));
}
@Test @Test
public void testValues() public void testValues()