From: <mgu...@us...> - 2012-11-23 10:15:04
|
Revision: 7757 http://sourceforge.net/p/htmlunit/code/7757 Author: mguillem Date: 2012-11-23 10:14:58 +0000 (Fri, 23 Nov 2012) Log Message: ----------- - Cookies: use 1970 as two digits year start for the expiration date. - Cookies: accept more non standard date formats for the expiration date. Modified Paths: -------------- trunk/htmlunit/src/changes/changes.xml trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManagerTest.java Modified: trunk/htmlunit/src/changes/changes.xml =================================================================== --- trunk/htmlunit/src/changes/changes.xml 2012-11-23 07:17:17 UTC (rev 7756) +++ trunk/htmlunit/src/changes/changes.xml 2012-11-23 10:14:58 UTC (rev 7757) @@ -8,6 +8,12 @@ <body> <release version="2.12" date="???" description="Bugfixes"> + <action type="fix" dev="mguillem"> + Cookies: use 1970 as two digits year start for the expiration date. + </action> + <action type="fix" dev="mguillem"> + Cookies: accept more non standard date formats for the expiration date. + </action> <action type="fix" dev="asashour" issue="1463"> Properly handle spaces after "em" element. </action> Modified: trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java =================================================================== --- trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2012-11-23 07:17:17 UTC (rev 7756) +++ trunk/htmlunit/src/main/java/com/gargoylesoftware/htmlunit/HttpWebConnection.java 2012-11-23 10:14:58 UTC (rev 7757) @@ -29,14 +29,13 @@ import java.net.URISyntaxException; import java.net.URL; import java.nio.charset.Charset; -import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; +import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.Date; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Random; @@ -97,6 +96,8 @@ import org.apache.http.impl.cookie.BasicClientCookie; import org.apache.http.impl.cookie.BasicPathHandler; import org.apache.http.impl.cookie.BrowserCompatSpec; +import org.apache.http.impl.cookie.DateParseException; +import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.BasicHeader; import org.apache.http.params.BasicHttpParams; import org.apache.http.params.CoreConnectionPNames; @@ -734,9 +735,27 @@ */ private static final Comparator<Cookie> COOKIE_COMPARATOR = new CookiePathComparator(); - private static final SimpleDateFormat INCORRECT_FORMAT - = new SimpleDateFormat("EEE,dd MMM yyyy HH:mm:ss z", Locale.US); + private static final Date DATE_1_1_1970; + static { + final Calendar calendar = Calendar.getInstance(); + calendar.setTimeZone(DateUtils.GMT); + calendar.set(1970, Calendar.JANUARY, 1, 0, 0, 0); + calendar.set(Calendar.MILLISECOND, 0); + DATE_1_1_1970 = calendar.getTime(); + } + + // simplified patterns from BrowserCompatSpec, with yy patterns before similar yyyy patterns + private static final String[] DEFAULT_DATE_PATTERNS = new String[] { + "EEE dd MMM yy HH mm ss zzz", + "EEE dd MMM yyyy HH mm ss zzz", + "EEE MMM d HH mm ss yyyy", + "EEE dd MMM yy HH mm ss z ", + "EEE dd MMM yyyy HH mm ss z ", + "EEE dd MM yy HH mm ss z ", + "EEE dd MM yyyy HH mm ss z ", + }; + HtmlUnitBrowserCompatCookieSpec(final IncorrectnessListener incorrectnessListener) { super(); final BasicPathHandler pathHandler = new BasicPathHandler() { @@ -749,6 +768,7 @@ final CookieAttributeHandler originalExpiresHandler = getAttribHandler(ClientCookie.EXPIRES_ATTR); final CookieAttributeHandler wrapperExpiresHandler = new CookieAttributeHandler() { + public void validate(final Cookie cookie, final CookieOrigin origin) throws MalformedCookieException { originalExpiresHandler.validate(cookie, origin); } @@ -757,22 +777,11 @@ if (value.startsWith("\"") && value.endsWith("\"")) { value = value.substring(1, value.length() - 1); } - final int length = value.length(); - if (value.endsWith("GMT") && length > 16 && !Character.isDigit(value.charAt(length - 16))) { - //add "19" prefix to the year - value = value.substring(0, length - 15) + "19" + value.substring(length - 15); - try { - INCORRECT_FORMAT.parse(value); - value = value.substring(0, 4) + ' ' + value.substring(4); - } - catch (final Exception e) { - //this is ok - } - } + value = value.replaceAll("[ ,:-]+", " "); try { - originalExpiresHandler.parse(cookie, value); + cookie.setExpiryDate(DateUtils.parseDate(value, DEFAULT_DATE_PATTERNS, DATE_1_1_1970)); } - catch (final MalformedCookieException e) { + catch (final DateParseException e) { incorrectnessListener.notify("Incorrect cookie expiration time: " + value, this); } } Modified: trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManagerTest.java =================================================================== --- trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManagerTest.java 2012-11-23 07:17:17 UTC (rev 7756) +++ trunk/htmlunit/src/test/java/com/gargoylesoftware/htmlunit/CookieManagerTest.java 2012-11-23 10:14:58 UTC (rev 7757) @@ -281,9 +281,63 @@ } /** + * Two digits years should be interpreted as 20xx if before 1970 and as 19xx otherwise. * @throws Exception if the test fails */ @Test + @Alerts("cookie1=1; cookie2=2; cookie3=3") + public void setCookieExpires_twoDigits() throws Exception { + final List<NameValuePair> responseHeader1 = new ArrayList<NameValuePair>(); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie1=1;expires=Sun 01-Dec-68 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie2=2;expires=Thu 01-Dec-69 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie3=3;expires=Mon 31-Dec-69 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie4=4;expires=Thu 01-Jan-70 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie5=5;expires=Tue 01-Dec-70 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie6=6;expires=Wed 01-Dec-71 16:00:00 GMT")); + getMockWebConnection().setResponse(getDefaultUrl(), HTML_ALERT_COOKIE, 200, "OK", "text/html", responseHeader1); + + loadPageWithAlerts2(getDefaultUrl()); + } + + /** + * Two digits years should be interpreted as 20xx if before 1970 and as 19xx otherwise. + * @throws Exception if the test fails + */ + @Test + @Alerts("cookie1=1; cookie2=2; cookie3=3") + public void setCookieExpires_twoDigits2() throws Exception { + final List<NameValuePair> responseHeader1 = new ArrayList<NameValuePair>(); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie1=1;expires=Sun,01 Dec 68 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie2=2;expires=Thu,01 Dec 69 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie3=3;expires=Mon,31 Dec 69 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie4=4;expires=Thu,01 Jan 70 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie5=5;expires=Tue,01 Dec 70 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie6=6;expires=Wed,01 Dec 71 16:00:00 GMT")); + getMockWebConnection().setResponse(getDefaultUrl(), HTML_ALERT_COOKIE, 200, "OK", "text/html", responseHeader1); + + loadPageWithAlerts2(getDefaultUrl()); + } + + /** + * Two digits years should be interpreted as 20xx if before 1970 and as 19xx otherwise, + * even with a quite strange date format. + * @throws Exception if the test fails + */ + @Test + @Alerts("cookie1=1") + public void setCookieExpires_badDateFormat() throws Exception { + final List<NameValuePair> responseHeader1 = new ArrayList<NameValuePair>(); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie1=1;expires=Sun-01 Dec 68 16:00:00 GMT")); + responseHeader1.add(new NameValuePair("Set-Cookie", "cookie6=6;expires=Wed-01 Dec 71 16:00:00 GMT")); + getMockWebConnection().setResponse(getDefaultUrl(), HTML_ALERT_COOKIE, 200, "OK", "text/html", responseHeader1); + + loadPageWithAlerts2(getDefaultUrl()); + } + + /** + * @throws Exception if the test fails + */ + @Test @Alerts public void setCookieExpired_badDateFormat2() throws Exception { final List<NameValuePair> responseHeader1 = new ArrayList<NameValuePair>(); |