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
{
private final static String __zeroquality="q=0";
private final HttpHeader _header;
private final String _name;
private final String _value;
@ -180,27 +181,186 @@ public class HttpField
/** Look for a value in a possible multi valued field
* @param search Values to search for
* @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)
{
if (_value==null || search==null)
return _value==search;
if (_value.equals(search))
return true;
String[] values = getValues();
for (String v:values)
{
if (v.equals(search))
return true;
if (v.startsWith(search) && v.charAt(search.length())==';')
return true;
}
if (search.length()==0)
return false;
int state=0;
int match=0;
int param=0;
for (int i=0;i<_value.length();i++)
{
char c = _value.charAt(i);
switch(state)
{
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 param!=__zeroquality.length() && match==search.length();
}
@Override
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
public void testValues()