浏览代码

fix supported cookie date formats

Johannes Schmitt 14 年之前
父节点
当前提交
0b3ff39704
共有 2 个文件被更改,包括 48 次插入8 次删除
  1. 30 7
      src/Symfony/Component/BrowserKit/Cookie.php
  2. 18 1
      tests/Symfony/Tests/Component/BrowserKit/CookieTest.php

+ 30 - 7
src/Symfony/Component/BrowserKit/Cookie.php

@@ -20,7 +20,18 @@ namespace Symfony\Component\BrowserKit;
  */
 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 $value;
@@ -74,7 +85,7 @@ class Cookie
         $cookie = sprintf('%s=%s', $this->name, $this->rawValue);
 
         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) {
@@ -159,11 +170,7 @@ class Cookie
 
             if (2 === count($elements = explode('=', $part, 2))) {
                 if ('expires' === $elements[0]) {
-                    if (false === $date = \DateTime::createFromFormat(static::DATE_FORMAT, $elements[1], new \DateTimeZone('UTC'))) {
-                        throw new \InvalidArgumentException(sprintf('The expires part of cookie is not valid (%s).', $elements[1]));
-                    }
-
-                    $elements[1] = $date->getTimestamp();
+                    $elements[1] = self::parseDate($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.
      *

+ 18 - 1
tests/Symfony/Tests/Component/BrowserKit/CookieTest.php

@@ -27,7 +27,6 @@ class CookieTest extends \PHPUnit_Framework_TestCase
     {
         return array(
             array('foo=bar'),
-            array('foo=bar; expires=Fri, 31-Dec-2010 23:59:59 GMT'),
             array('foo=bar; path=/foo'),
             array('foo=bar; domain=google.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());
     }
 
+    /**
+     * @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()
     {
         $this->assertEquals('foo=bar; domain=www.example.com', (string) Cookie::FromString('foo=bar', 'http://www.example.com/'));