391622 Be lenient on RFC6265 restriction on duplicate cookie names in same response

This commit is contained in:
Jan Bartel 2012-10-11 16:09:35 +11:00
parent 86b51e608f
commit 5277122dd8
2 changed files with 75 additions and 8 deletions

View File

@ -934,6 +934,9 @@ public class HttpFields
QuotedStringTokenizer.quoteIfNeeded(buf, name, delim); QuotedStringTokenizer.quoteIfNeeded(buf, name, delim);
buf.append('='); buf.append('=');
String start=buf.toString(); String start=buf.toString();
boolean hasDomain = false;
boolean hasPath = false;
if (value != null && value.length() > 0) if (value != null && value.length() > 0)
QuotedStringTokenizer.quoteIfNeeded(buf, value, delim); QuotedStringTokenizer.quoteIfNeeded(buf, value, delim);
@ -945,6 +948,7 @@ public class HttpFields
if (path != null && path.length() > 0) if (path != null && path.length() > 0)
{ {
hasPath = true;
buf.append(";Path="); buf.append(";Path=");
if (path.trim().startsWith("\"")) if (path.trim().startsWith("\""))
buf.append(path); buf.append(path);
@ -953,6 +957,7 @@ public class HttpFields
} }
if (domain != null && domain.length() > 0) if (domain != null && domain.length() > 0)
{ {
hasDomain = true;
buf.append(";Domain="); buf.append(";Domain=");
QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim); QuotedStringTokenizer.quoteIfNeeded(buf,domain.toLowerCase(),delim);
} }
@ -985,14 +990,20 @@ public class HttpFields
Field last=null; Field last=null;
while (field!=null) while (field!=null)
{ {
if (field._value!=null && field._value.toString().startsWith(start)) String val = (field._value == null ? null : field._value.toString());
if (val!=null && val.startsWith(start))
{ {
_fields.remove(field); //existing cookie has same name, does it also match domain and path?
if (last==null) if (((!hasDomain && !val.contains("Domain")) || (hasDomain && val.contains("Domain="+domain))) &&
_names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next); ((!hasPath && !val.contains("Path")) || (hasPath && val.contains("Path="+path))))
else {
last._next=field._next; _fields.remove(field);
break; if (last==null)
_names.put(HttpHeaders.SET_COOKIE_BUFFER,field._next);
else
last._next=field._next;
break;
}
} }
last=field; last=field;
field=field._next; field=field._next;

View File

@ -364,7 +364,8 @@ public class HttpFieldsTest
assertEquals("minimal=value",fields.getStringField("Set-Cookie")); assertEquals("minimal=value",fields.getStringField("Set-Cookie"));
fields.clear(); fields.clear();
fields.addSetCookie("everything","wrong","wrong","wrong",0,"to be replaced",true,true,0); //test cookies with same name, domain and path, only 1 allowed
fields.addSetCookie("everything","wrong","domain","path",0,"to be replaced",true,true,0);
fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0); fields.addSetCookie("everything","value","domain","path",0,"comment",true,true,0);
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie")); assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",fields.getStringField("Set-Cookie"));
Enumeration<String> e =fields.getValues("Set-Cookie"); Enumeration<String> e =fields.getValues("Set-Cookie");
@ -372,6 +373,61 @@ public class HttpFieldsTest
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement()); assertEquals("everything=value;Comment=comment;Path=path;Domain=domain;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements()); assertFalse(e.hasMoreElements());
assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires")); assertEquals("Thu, 01 Jan 1970 00:00:00 GMT",fields.getStringField("Expires"));
assertFalse(e.hasMoreElements());
//test cookies with same name, different domain
fields.clear();
fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
fields.addSetCookie("everything","value","domain2","path",0,"comment",true,true,0);
e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=other;Comment=blah;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Comment=comment;Path=path;Domain=domain2;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements());
//test cookies with same name, same path, one with domain, one without
fields.clear();
fields.addSetCookie("everything","other","domain1","path",0,"blah",true,true,0);
fields.addSetCookie("everything","value","","path",0,"comment",true,true,0);
e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=other;Comment=blah;Path=path;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Comment=comment;Path=path;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements());
//test cookies with same name, different path
fields.clear();
fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
fields.addSetCookie("everything","value","domain1","path2",0,"comment",true,true,0);
e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=other;Comment=blah;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Comment=comment;Path=path2;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements());
//test cookies with same name, same domain, one with path, one without
fields.clear();
fields.addSetCookie("everything","other","domain1","path1",0,"blah",true,true,0);
fields.addSetCookie("everything","value","domain1","",0,"comment",true,true,0);
e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=other;Comment=blah;Path=path1;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Comment=comment;Domain=domain1;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements());
//test cookies same name only, no path, no domain
fields.clear();
fields.addSetCookie("everything","other","","",0,"blah",true,true,0);
fields.addSetCookie("everything","value","","",0,"comment",true,true,0);
e =fields.getValues("Set-Cookie");
assertTrue(e.hasMoreElements());
assertEquals("everything=value;Comment=comment;Expires=Thu, 01-Jan-1970 00:00:00 GMT;Secure;HttpOnly",e.nextElement());
assertFalse(e.hasMoreElements());
fields.clear(); fields.clear();
fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,2); fields.addSetCookie("ev erything","va lue","do main","pa th",1,"co mment",true,true,2);