Skip to content

Commit

Permalink
Implements a cookie-date parsing utility
Browse files Browse the repository at this point in the history
  • Loading branch information
aaa2000 committed Jun 16, 2017
1 parent d36c45f commit caa5344
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 0 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@

## Unreleased

### Added

- CookieUtil::parseDate to create a date from cookie date string

## 1.5.0 - 2017-02-14

### Added
Expand Down
76 changes: 76 additions & 0 deletions spec/CookieUtilSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php

namespace spec\Http\Message;

use Http\Message\Exception\UnexpectedValueException;
use PhpSpec\ObjectBehavior;

class CookieUtilSpec extends ObjectBehavior
{
/**
* @dataProvider getCookieStrings
*/
function it_parses_cookie_date_string($cookieDateString, $expectedString)
{
$this->beConstructedThrough('parseDate', [$cookieDateString]);
$this->shouldHaveType('\DateTime');
$this->format('l, d-M-Y H:i:s O')->shouldReturn($expectedString);
}

/**
* @dataProvider getInvalidCookieDateStrings
*/
function it_throws_an_exception_if_cookie_date_string_is_unparseable($cookieDateString)
{
$this->beConstructedThrough('parseDate', [$cookieDateString]);
$this->shouldThrow('Http\Message\Exception\UnexpectedValueException');
}

/**
* Provides examples for valid cookie date string.
*
* @return array
*/
public function getCookieStrings()
{
return [
['Friday, 31 Jul 20 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Friday, 31-Jul-20 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Fri, 31-Jul-2020 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Fri, 31 Jul 2020 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Fri, 31-07-2020 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Fri, 31-07-20 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Friday, 31-Jul-20 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Fri Jul 31 08:49:37 2020', 'Friday, 31-Jul-2020 08:49:37 +0000'],
['Friday July 31st 2020, 08:49:37 GMT', 'Friday, 31-Jul-2020 08:49:37 +0000'],
// https://github.com/salesforce/tough-cookie/blob/master/test/date_test.js#L52
['Wed, 09 Jun 2021 10:18:14 GMT', 'Wednesday, 09-Jun-2021 10:18:14 +0000'],
['Wed, 09 Jun 2021 22:18:14 GMT', 'Wednesday, 09-Jun-2021 22:18:14 +0000'],
['Tue, 18 Oct 2011 07:42:42.123 GMT', 'Tuesday, 18-Oct-2011 07:42:42 +0000'],
['18 Oct 2011 07:42:42 GMT', 'Tuesday, 18-Oct-2011 07:42:42 +0000'],
['8 Oct 2011 7:42:42 GMT', 'Saturday, 08-Oct-2011 07:42:42 +0000'],
['8 Oct 2011 7:2:42 GMT', 'Saturday, 08-Oct-2011 07:02:42 +0000'],
['Oct 18 2011 07:42:42 GMT', 'Tuesday, 18-Oct-2011 07:42:42 +0000'],
['Tue Oct 18 2011 07:05:03 GMT+0000 (GMT)', 'Tuesday, 18-Oct-2011 07:05:03 +0000'],
['09 Jun 2021 10:18:14 GMT', 'Wednesday, 09-Jun-2021 10:18:14 +0000'],
['01 Jan 1970 00:00:00 GMT', 'Thursday, 01-Jan-1970 00:00:00 +0000'],
['01 Jan 1601 00:00:00 GMT', 'Monday, 01-Jan-1601 00:00:00 +0000'],
['10 Feb 81 13:00:00 GMT', 'Tuesday, 10-Feb-1981 13:00:00 +0000'], // implicit year
['Thu, 17-Apr-2014 02:12:29 GMT', 'Thursday, 17-Apr-2014 02:12:29 +0000'], // dashes
['Thu, 17-Apr-2014 02:12:29 UTC', 'Thursday, 17-Apr-2014 02:12:29 +0000'], // dashes and UTC
];
}

/**
* Provides examples for invalid cookie date string.
*
* @return array
*/
public function getInvalidCookieDateStrings()
{
return [
['Flursday July 31st 2020, 08:49:37 GMT'],
['99 Jix 3038 48:86:72 ZMT'],
];
}
}
53 changes: 53 additions & 0 deletions src/CookieUtil.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace Http\Message;

use Http\Message\Exception\UnexpectedValueException;

final class CookieUtil
{
/**
* 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 = [
'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, 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',
'D M d H:i:s Y T',
];

/**
* @see https://github.com/symfony/symfony/blob/master/src/Symfony/Component/BrowserKit/Cookie.php
*
* @param string $dateValue
*
* @return \DateTime
*
* @throws UnexpectedValueException if we cannot parse the cookie date string.
*/
public static function parseDate($dateValue)
{
foreach (self::$dateFormats as $dateFormat) {
if (false !== $date = \DateTime::createFromFormat($dateFormat, $dateValue, new \DateTimeZone('GMT'))) {
return $date;
}
}

// attempt a fallback for unusual formatting
if (false !== $date = date_create($dateValue, new \DateTimeZone('GMT'))) {
return $date;
}

throw new UnexpectedValueException(sprintf(
'Unparseable cookie date string "%s"',
$dateValue
));
}
}
10 changes: 10 additions & 0 deletions src/Exception.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

namespace Http\Message;

/**
* An interface implemented by all HTTP message related exceptions.
*/
interface Exception
{
}
9 changes: 9 additions & 0 deletions src/Exception/UnexpectedValueException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

namespace Http\Message\Exception;

use Http\Message\Exception;

final class UnexpectedValueException extends \UnexpectedValueException implements Exception
{
}

0 comments on commit caa5344

Please sign in to comment.