added cookie v1 and v2 decoding support

This commit is contained in:
Andy Taylor 2009-03-13 11:58:29 +00:00
parent df3ac447ff
commit b8f03d60e4
4 changed files with 276 additions and 16 deletions

View File

@ -21,11 +21,11 @@
*/
package org.jboss.netty.handler.codec.http;
import org.jboss.netty.util.CaseIgnoringComparator;
import java.util.Map;
import java.util.TreeMap;
import org.jboss.netty.util.CaseIgnoringComparator;
/**
* @author The Netty Project (netty-dev@lists.jboss.org)
* @author Andy Taylor (andy.taylor@jboss.org)
@ -33,8 +33,11 @@ import org.jboss.netty.util.CaseIgnoringComparator;
*/
public class CookieDecoder {
private final static String semicolon = ";";
private final static String equals = "=";
private final static String SEMICOLON = ";";
private final static String EQUALS = "=";
private final static String COMMA = ",";
private final String charset;
@ -50,19 +53,88 @@ public class CookieDecoder {
}
public Map<String, Cookie> decode(String header) {
// FIXME: Support both version 0 and 1 cookies
// FIXME: Decode all cookie fields, including domain, path, maxAge, secure, and comment.
// FIXME: CookieDecoder cannot assume that the first field is always the name-value pair.
// FIXME: Check RFC 2109 - http://www.ietf.org/rfc/rfc2109.txt
Map<String, Cookie> cookies = new TreeMap<String, Cookie>(CaseIgnoringComparator.INSTANCE);
String[] split = header.split(semicolon);
for (String s : split) {
String[] cookie = s.split(equals);
if(cookie != null && cookie.length == 2) {
String[] split = header.split(SEMICOLON);
for (int i = 0; i < split.length; i++) {
DefaultCookie theCookie;
String s = split[i];
String[] cookie = s.split(EQUALS, 2);
if (cookie != null && cookie.length == 2) {
String name = cookie[0].trim();
String value = QueryStringDecoder.decodeComponent(cookie[1], charset);
cookies.put(name, new DefaultCookie(name, value));
theCookie = new DefaultCookie(name, value);
cookies.put(name, theCookie);
boolean discard = false;
boolean secure = false;
String comment = null;
String commentURL = null;
String domain = null;
String path = null;
int version = 0;
int maxAge = 0;
int[] ports = null;
for (int j = i + 1; j < split.length; j++, i++) {
String[] val = split[j].split(EQUALS, 2);
if (val != null && val.length == 1) {
if (CookieHeaderNames.DISCARD.equalsIgnoreCase(val[0])) {
discard = true;
}
else if (CookieHeaderNames.SECURE.equalsIgnoreCase(val[0])) {
secure = true;
}
}
else if (val != null && val.length == 2) {
name = val[0].trim();
value = val[1].trim();
if (CookieHeaderNames.COMMENT.equalsIgnoreCase(name)) {
comment = QueryStringDecoder.decodeComponent(value, charset);
}
else if (CookieHeaderNames.COMMENTURL.equalsIgnoreCase(name)) {
commentURL = QueryStringDecoder.decodeComponent(value, charset);
}
else if (CookieHeaderNames.DOMAIN.equalsIgnoreCase(name)) {
domain = QueryStringDecoder.decodeComponent(value, charset);
}
else if (CookieHeaderNames.PATH.equalsIgnoreCase(name)) {
path = QueryStringDecoder.decodeComponent(value, charset);
}
else if (CookieHeaderNames.EXPIRES.equalsIgnoreCase(name)) {
maxAge = Integer.valueOf(value);
}
else if (CookieHeaderNames.MAX_AGE.equalsIgnoreCase(name)) {
maxAge = Integer.valueOf(value);
}
else if (CookieHeaderNames.VERSION.equalsIgnoreCase(name)) {
version = Integer.valueOf(value);
}
else if (CookieHeaderNames.PORTLIST.equalsIgnoreCase(name)) {
String[] portList = value.split(COMMA);
ports = new int[portList.length];
for (int i1 = 0; i1 < portList.length; i1++) {
String s1 = portList[i1];
ports[i1] = Integer.valueOf(s1);
}
}
else {
break;
}
}
}
theCookie.setVersion(version);
theCookie.setMaxAge(maxAge);
theCookie.setPath(path);
theCookie.setDomain(domain);
theCookie.setSecure(secure);
if (version > 0) {
theCookie.setComment(comment);
}
if (version > 1) {
theCookie.setCommentURL(commentURL);
theCookie.setPortList(ports);
theCookie.setDiscard(discard);
}
}
}
return cookies;
}

View File

@ -27,9 +27,9 @@ package org.jboss.netty.handler.codec.http;
public class CookieHeaderNames {
public static final String PATH = "path";
private static final String EXPIRES = "expires";
public static final String EXPIRES = "expires";
private static final String MAX_AGE = "max-age";
public static final String MAX_AGE = "max-age";
public static final String DOMAIN = "domain";

View File

@ -0,0 +1,188 @@
/*
* JBoss, Home of Professional Open Source
* Copyright 2005-2008, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.netty.handler.codec.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import java.util.Map;
/**
* @author <a href="mailto:andy.taylor@jboss.org">Andy Taylor</a>
*/
public class CookieDecoderTest {
@Test
public void testDecodingSingleCookieV0() {
String cookieString = "myCookie=myValue;expires=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;";
CookieDecoder cookieDecoder = new CookieDecoder();
Map<String, Cookie> cookieMap = cookieDecoder.decode(cookieString);
assertEquals(1, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertNotNull(cookie);
assertEquals("myValue", cookie.getValue());
assertNull(cookie.getComment());
assertNull(cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNull(cookie.getPortList());
assertTrue(cookie.isSecure());
assertEquals(0, cookie.getVersion());
}
@Test
public void testDecodingSingleCookieV0ExtraParamsIgnored() {
String cookieString = "myCookie=myValue;max-age=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;comment=this%20is%20a%20comment;version=0;commentURL=http%2F%3Aaurl.com;port=80,8080;discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Map<String, Cookie> cookieMap = cookieDecoder.decode(cookieString);
assertEquals(1, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertNotNull(cookie);
assertEquals("myValue", cookie.getValue());
assertNull(cookie.getComment());
assertNull(cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNull(cookie.getPortList());
assertTrue(cookie.isSecure());
assertEquals(0, cookie.getVersion());
}
@Test
public void testDecodingSingleCookieV1() {
String cookieString = "myCookie=myValue;max-age=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;comment=this%20is%20a%20comment;version=1;";
CookieDecoder cookieDecoder = new CookieDecoder();
Map<String, Cookie> cookieMap = cookieDecoder.decode(cookieString);
assertEquals(1, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertEquals("myValue", cookie.getValue());
assertNotNull(cookie);
assertEquals("this is a comment", cookie.getComment());
assertNull(cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNull(cookie.getPortList());
assertTrue(cookie.isSecure());
assertEquals(1, cookie.getVersion());
}
@Test
public void testDecodingSingleCookieV1ExtraParamsIgnored() {
String cookieString = "myCookie=myValue;max-age=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;comment=this%20is%20a%20comment;version=1;commentURL=http%2F%3Aaurl.com;port=80,8080;discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Map<String, Cookie> cookieMap = cookieDecoder.decode(cookieString);
assertEquals(1, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertNotNull(cookie);
assertEquals("myValue", cookie.getValue());
assertEquals("this is a comment", cookie.getComment());
assertNull(cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNull(cookie.getPortList());
assertTrue(cookie.isSecure());
assertEquals(1, cookie.getVersion());
}
@Test
public void testDecodingSingleCookieV2() {
String cookieString = "myCookie=myValue;max-age=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;comment=this%20is%20a%20comment;version=2;commentURL=http%2F%3Aaurl.com;port=80,8080;discard;";
CookieDecoder cookieDecoder = new CookieDecoder();
Map<String, Cookie> cookieMap = cookieDecoder.decode(cookieString);
assertEquals(1, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertNotNull(cookie);
assertEquals("myValue", cookie.getValue());
assertEquals("this is a comment", cookie.getComment());
assertEquals("http/:aurl.com", cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertTrue(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNotNull(cookie.getPortList());
assertEquals(2, cookie.getPortList().length);
assertEquals(80, cookie.getPortList()[0]);
assertEquals(8080, cookie.getPortList()[1]);
assertTrue(cookie.isSecure());
assertEquals(2, cookie.getVersion());
}
@Test
public void testDecodingMultipleCookies() {
String c1 = "myCookie=myValue;max-age=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;comment=this%20is%20a%20comment;version=2;commentURL=http%2F%3Aaurl.com;port=80,8080;discard;";
String c2 = "myCookie2=myValue2;max-age=0;path=%2Fanotherpathsomewhere;domain=%2Fanotherdomainsomewhere;comment=this%20is%20another%20comment;version=2;commentURL=http%2F%3Aanotherurl.com;";
String c3 = "myCookie3=myValue3;max-age=0;version=2;";
CookieDecoder decoder = new CookieDecoder();
Map<String, Cookie> cookieMap = decoder.decode(c1 + c2 + c3);
assertEquals(3, cookieMap.size());
Cookie cookie = cookieMap.get("MyCookie");
assertNotNull(cookie);
assertEquals("myValue", cookie.getValue());
assertEquals("this is a comment", cookie.getComment());
assertEquals("http/:aurl.com", cookie.getCommentURL());
assertEquals("/adomainsomewhere", cookie.getDomain());
assertTrue(cookie.isDiscard());
assertEquals(50, cookie.getMaxAge());
assertEquals("/apathsomewhere", cookie.getPath());
assertNotNull(cookie.getPortList());
assertEquals(2, cookie.getPortList().length);
assertEquals(80, cookie.getPortList()[0]);
assertEquals(8080, cookie.getPortList()[1]);
assertTrue(cookie.isSecure());
assertEquals(2, cookie.getVersion());
cookie = cookieMap.get("MyCookie2");
assertNotNull(cookie);
assertEquals("myValue2", cookie.getValue());
assertEquals("this is another comment", cookie.getComment());
assertEquals("http/:anotherurl.com", cookie.getCommentURL());
assertEquals("/anotherdomainsomewhere", cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(0, cookie.getMaxAge());
assertEquals("/anotherpathsomewhere", cookie.getPath());
assertNull(cookie.getPortList());
assertFalse(cookie.isSecure());
assertEquals(2, cookie.getVersion());
cookie = cookieMap.get("MyCookie3");
assertNotNull(cookie);
assertEquals("myValue3", cookie.getValue());
assertNull( cookie.getComment());
assertNull(cookie.getCommentURL());
assertNull(cookie.getDomain());
assertFalse(cookie.isDiscard());
assertEquals(0, cookie.getMaxAge());
assertNull(cookie.getPath());
assertNull(cookie.getPortList());
assertFalse(cookie.isSecure());
assertEquals(2, cookie.getVersion());
}
}

View File

@ -28,7 +28,7 @@ import org.junit.Test;
/**
* @author <a href="mailto:andy.taylor@jboss.org">Andy Taylor</a>
*/
public class HttpCookieEncoderTest {
public class CookieEncoderTest {
@Test
public void testEncodingSingleCookieV0() {
String result = "myCookie=myValue;expires=50;path=%2Fapathsomewhere;domain=%2Fadomainsomewhere;secure;";