Skip to content

Implements a cookie-date parsing utility #76

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
{
}