fix supported cookie date formats

This commit is contained in:
Johannes Schmitt 2011-07-24 21:13:25 +02:00
parent 858cce84d5
commit 0b3ff39704
2 changed files with 48 additions and 8 deletions

View File

@ -20,7 +20,18 @@ namespace Symfony\Component\BrowserKit;
*/ */
class Cookie class Cookie
{ {
const DATE_FORMAT = 'D, d-M-Y H:i:s T'; /**
* Handles dates as defined by RFC 2616 section 3.3.1, and also some other
* non-standard, but common formats.
*
* @var array
*/
private static $dateFormats = array(
'D, d M Y H:i:s T',
'D, d-M-y H:i:s T',
'D, d-M-Y H:i:s T',
'D M j G:i:s Y',
);
protected $name; protected $name;
protected $value; protected $value;
@ -74,7 +85,7 @@ class Cookie
$cookie = sprintf('%s=%s', $this->name, $this->rawValue); $cookie = sprintf('%s=%s', $this->name, $this->rawValue);
if (null !== $this->expires) { if (null !== $this->expires) {
$cookie .= '; expires='.substr(\DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('UTC'))->format(static::DATE_FORMAT), 0, -5); $cookie .= '; expires='.substr(\DateTime::createFromFormat('U', $this->expires, new \DateTimeZone('GMT'))->format(self::$dateFormats[0]), 0, -5);
} }
if ('' !== $this->domain) { if ('' !== $this->domain) {
@ -159,11 +170,7 @@ class Cookie
if (2 === count($elements = explode('=', $part, 2))) { if (2 === count($elements = explode('=', $part, 2))) {
if ('expires' === $elements[0]) { if ('expires' === $elements[0]) {
if (false === $date = \DateTime::createFromFormat(static::DATE_FORMAT, $elements[1], new \DateTimeZone('UTC'))) { $elements[1] = self::parseDate($elements[1]);
throw new \InvalidArgumentException(sprintf('The expires part of cookie is not valid (%s).', $elements[1]));
}
$elements[1] = $date->getTimestamp();
} }
$values[strtolower($elements[0])] = $elements[1]; $values[strtolower($elements[0])] = $elements[1];
@ -182,6 +189,22 @@ class Cookie
); );
} }
private static function parseDate($dateValue)
{
// trim single quotes around date if present
if (($length = strlen($dateValue)) > 1 && "'" === $dateValue[0] && "'" === $dateValue[$length-1]) {
$dateValue = substr($dateValue, 1, -1);
}
foreach (self::$dateFormats as $dateFormat) {
if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) {
return $date->getTimestamp();
}
}
throw new \InvalidArgumentException(sprintf('Could not parse date "%s".', $dateValue));
}
/** /**
* Gets the name of the cookie. * Gets the name of the cookie.
* *

View File

@ -27,7 +27,6 @@ class CookieTest extends \PHPUnit_Framework_TestCase
{ {
return array( return array(
array('foo=bar'), array('foo=bar'),
array('foo=bar; expires=Fri, 31-Dec-2010 23:59:59 GMT'),
array('foo=bar; path=/foo'), array('foo=bar; path=/foo'),
array('foo=bar; domain=google.com'), array('foo=bar; domain=google.com'),
array('foo=bar; domain=example.com; secure', 'https://example.com/'), array('foo=bar; domain=example.com; secure', 'https://example.com/'),
@ -44,6 +43,24 @@ class CookieTest extends \PHPUnit_Framework_TestCase
$this->assertFalse(Cookie::fromString('foo=bar; secure', 'http://example.com/')->isSecure()); $this->assertFalse(Cookie::fromString('foo=bar; secure', 'http://example.com/')->isSecure());
} }
/**
* @dataProvider getExpireCookieStrings
*/
public function testFromStringAcceptsSeveralExpiresDateFormats($cookie)
{
$this->assertEquals(1596185377, Cookie::fromString($cookie)->getExpiresTime());
}
public function getExpireCookieStrings()
{
return array(
array('foo=bar; expires=Fri, 31-Jul-2020 08:49:37 GMT'),
array('foo=bar; expires=Fri, 31 Jul 2020 08:49:37 GMT'),
array('foo=bar; expires=Friday, 31-Jul-20 08:49:37 GMT'),
array('foo=bar; expires=Fri Jul 31 08:49:37 2020'),
);
}
public function testFromStringWithUrl() public function testFromStringWithUrl()
{ {
$this->assertEquals('foo=bar; domain=www.example.com', (string) Cookie::FromString('foo=bar', 'http://www.example.com/')); $this->assertEquals('foo=bar; domain=www.example.com', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));