=htc #16500 parse Sunday dates and dates with long weekday names correctly

Also, make sure not to parse well-known parameters into the extension block.

Thanks, @richdougherty for the first version of this patch and the additional
test cases.
This commit is contained in:
Johannes Rudolph 2014-12-10 16:18:22 +01:00
parent bd3ee6b54f
commit 88a79556cb
2 changed files with 70 additions and 5 deletions

View file

@ -71,13 +71,13 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒
} }
def `IMF-fixdate` = rule { // mixture of the spec-ed `IMF-fixdate` and `rfc850-date` def `IMF-fixdate` = rule { // mixture of the spec-ed `IMF-fixdate` and `rfc850-date`
(`day-name` | `day-name-l`) ~ ", " ~ (date1 | date2) ~ ' ' ~ `time-of-day` ~ ' ' ~ ("GMT" | "UTC") ~> { (`day-name-l` | `day-name`) ~ ", " ~ (date1 | date2) ~ ' ' ~ `time-of-day` ~ ' ' ~ ("GMT" | "UTC") ~> {
(wkday, day, month, year, hour, min, sec) createDateTime(year, month, day, hour, min, sec, wkday) (wkday, day, month, year, hour, min, sec) createDateTime(year, month, day, hour, min, sec, wkday)
} }
} }
def `day-name` = rule( def `day-name` = rule(
"Mon" ~ push(1) | "Tue" ~ push(2) | "Wed" ~ push(3) | "Thu" ~ push(4) | "Fri" ~ push(5) | "Sat" ~ push(6) | "Sun" ~ push(7)) "Sun" ~ push(0) | "Mon" ~ push(1) | "Tue" ~ push(2) | "Wed" ~ push(3) | "Thu" ~ push(4) | "Fri" ~ push(5) | "Sat" ~ push(6))
def date1 = rule { day ~ ' ' ~ month ~ ' ' ~ year } def date1 = rule { day ~ ' ' ~ month ~ ' ' ~ year }
@ -101,8 +101,8 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒
def date2 = rule { day ~ '-' ~ month ~ '-' ~ digit2 } def date2 = rule { day ~ '-' ~ month ~ '-' ~ digit2 }
def `day-name-l` = rule( def `day-name-l` = rule(
"Monday" ~ push(1) | "Tuesday" ~ push(2) | "Wednesday" ~ push(3) | "Thursday" ~ push(4) | "Friday" ~ push(5) | "Sunday" ~ push(0) | "Monday" ~ push(1) | "Tuesday" ~ push(2) | "Wednesday" ~ push(3) | "Thursday" ~ push(4) |
"Saturday" ~ push(6) | "Sunday" ~ push(7)) "Friday" ~ push(5) | "Saturday" ~ push(6))
def `asctime-date` = rule { def `asctime-date` = rule {
`day-name` ~ ' ' ~ date3 ~ ' ' ~ `time-of-day` ~ ' ' ~ year ~> { `day-name` ~ ' ' ~ date3 ~ ' ' ~ `time-of-day` ~ ' ' ~ year ~> {
@ -269,7 +269,13 @@ private[parser] trait CommonRules { this: Parser with StringBuilding ⇒
// http://www.rfc-editor.org/errata_search.php?rfc=6265 // http://www.rfc-editor.org/errata_search.php?rfc=6265
def `extension-av` = rule { def `extension-av` = rule {
capture(zeroOrMore(`av-octet`)) ~ OWS ~> { (c: HttpCookie, s: String) c.copy(extension = Some(s)) } !(ignoreCase("expires=")
| ignoreCase("max-age=")
| ignoreCase("domain=")
| ignoreCase("path=")
| ignoreCase("secure")
| ignoreCase("httponly")) ~
capture(zeroOrMore(`av-octet`)) ~ OWS ~> { (c: HttpCookie, s: String) c.copy(extension = Some(s)) }
} }
// ****************************************************************************************** // ******************************************************************************************

View file

@ -361,6 +361,65 @@ class HttpHeaderSpec extends FreeSpec with Matchers {
`Set-Cookie`(HttpCookie("foo", "bar", domain = Some("example.com"), path = Some("/this is a path with blanks"), `Set-Cookie`(HttpCookie("foo", "bar", domain = Some("example.com"), path = Some("/this is a path with blanks"),
extension = Some("extension with blanks"))).renderedTo( extension = Some("extension with blanks"))).renderedTo(
"foo=bar; Domain=example.com; Path=/this is a path with blanks; extension with blanks") "foo=bar; Domain=example.com; Path=/this is a path with blanks; extension with blanks")
// test all weekdays
"Set-Cookie: lang=; Expires=Sun, 07 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 7, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Sunday, 07 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 7, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Sun, 07 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Mon, 08 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 8, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Monday, 08 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 8, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Mon, 08 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Tue, 09 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 9, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Tuesday, 09 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 9, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Tue, 09 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Wed, 10 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 10, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Wednesday, 10 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 10, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Wed, 10 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Thu, 11 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 11, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Thursday, 11 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 11, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Thu, 11 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Fri, 12 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 12, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Friday, 12 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 12, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Fri, 12 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Sat, 13 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 13, 0, 42, 55)), maxAge = Some(12345)))
"Set-Cookie: lang=; Expires=Saturday, 13 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
`Set-Cookie`(HttpCookie("lang", "", expires = Some(DateTime(2014, 12, 13, 0, 42, 55)), maxAge = Some(12345)))
.renderedTo("lang=; Expires=Sat, 13 Dec 2014 00:42:55 GMT; Max-Age=12345")
"Set-Cookie: lang=; Expires=Mon, 13 Dec 2014 00:42:55 GMT; Max-Age=12345" =!=
ErrorInfo("Illegal HTTP header 'Set-Cookie': Illegal weekday in date 2014-12-13T00:42:55", "is 'Mon' but should be 'Sat'")
"Set-Cookie: lang=; Expires=xxxx" =!=
ErrorInfo(
"Illegal HTTP header 'Set-Cookie': Invalid input 'x', expected '\\r', WSP, 'S', 'M', 'T', 'W', 'F' or '0' (line 1, column 16)",
"lang=; Expires=xxxx\n ^")
// extra examples from play
"Set-Cookie: PLAY_FLASH=\"success=found\"; Path=/; HTTPOnly" =!=
`Set-Cookie`(HttpCookie("PLAY_FLASH", "success=found", path = Some("/"), httpOnly = true))
.renderedTo("PLAY_FLASH=success=found; Path=/; HttpOnly")
"Set-Cookie: PLAY_FLASH=; Expires=Sun, 07 Dec 2014 22:48:47 GMT; Path=/; HTTPOnly" =!=
`Set-Cookie`(HttpCookie("PLAY_FLASH", "", expires = Some(DateTime(2014, 12, 7, 22, 48, 47)), path = Some("/"), httpOnly = true))
.renderedTo("PLAY_FLASH=; Expires=Sun, 07 Dec 2014 22:48:47 GMT; Path=/; HttpOnly")
} }
"User-Agent" in { "User-Agent" in {