parse cookie values containing the equal sign

This commit is contained in:
Christian Flothmann 2021-01-02 13:40:41 +01:00
parent e1b81d513e
commit 29d2da572e
3 changed files with 60 additions and 27 deletions

View File

@ -193,17 +193,23 @@ class HeaderUtils
return $disposition.'; '.self::toString($params, ';'); return $disposition.'; '.self::toString($params, ';');
} }
private static function groupParts(array $matches, string $separators): array private static function groupParts(array $matches, string $separators, bool $first = true): array
{ {
$separator = $separators[0]; $separator = $separators[0];
$partSeparators = substr($separators, 1); $partSeparators = substr($separators, 1);
$i = 0; $i = 0;
$partMatches = []; $partMatches = [];
$previousMatchWasSeparator = false;
foreach ($matches as $match) { foreach ($matches as $match) {
if (isset($match['separator']) && $match['separator'] === $separator) { if (!$first && $previousMatchWasSeparator && isset($match['separator']) && $match['separator'] === $separator) {
$previousMatchWasSeparator = true;
$partMatches[$i][] = $match;
} elseif (isset($match['separator']) && $match['separator'] === $separator) {
$previousMatchWasSeparator = true;
++$i; ++$i;
} else { } else {
$previousMatchWasSeparator = false;
$partMatches[$i][] = $match; $partMatches[$i][] = $match;
} }
} }
@ -211,12 +217,19 @@ class HeaderUtils
$parts = []; $parts = [];
if ($partSeparators) { if ($partSeparators) {
foreach ($partMatches as $matches) { foreach ($partMatches as $matches) {
$parts[] = self::groupParts($matches, $partSeparators); $parts[] = self::groupParts($matches, $partSeparators, false);
} }
} else { } else {
foreach ($partMatches as $matches) { foreach ($partMatches as $matches) {
$parts[] = self::unquote($matches[0][0]); $parts[] = self::unquote($matches[0][0]);
} }
if (!$first && 2 < \count($parts)) {
$parts = [
$parts[0],
implode($separator, \array_slice($parts, 1)),
];
}
} }
return $parts; return $parts;

View File

@ -227,6 +227,12 @@ class CookieTest extends TestCase
$cookie = Cookie::fromString('foo', true); $cookie = Cookie::fromString('foo', true);
$this->assertEquals(Cookie::create('foo', null, 0, '/', null, false, false, false, null), $cookie); $this->assertEquals(Cookie::create('foo', null, 0, '/', null, false, false, false, null), $cookie);
$cookie = Cookie::fromString('foo_cookie=foo=1&bar=2&baz=3; expires=Tue, 22-Sep-2020 06:27:09 GMT; path=/');
$this->assertEquals(Cookie::create('foo_cookie', 'foo=1&bar=2&baz=3', strtotime('Tue, 22-Sep-2020 06:27:09 GMT'), '/', null, false, false, true, null), $cookie);
$cookie = Cookie::fromString('foo_cookie=foo==; expires=Tue, 22-Sep-2020 06:27:09 GMT; path=/');
$this->assertEquals(Cookie::create('foo_cookie', 'foo==', strtotime('Tue, 22-Sep-2020 06:27:09 GMT'), '/', null, false, false, true, null), $cookie);
} }
public function testFromStringWithHttpOnly() public function testFromStringWithHttpOnly()

View File

@ -16,33 +16,47 @@ use Symfony\Component\HttpFoundation\HeaderUtils;
class HeaderUtilsTest extends TestCase class HeaderUtilsTest extends TestCase
{ {
public function testSplit() /**
* @dataProvider provideHeaderToSplit
*/
public function testSplit(array $expected, string $header, string $separator)
{ {
$this->assertSame(['foo=123', 'bar'], HeaderUtils::split('foo=123,bar', ',')); $this->assertSame($expected, HeaderUtils::split($header, $separator));
$this->assertSame(['foo=123', 'bar'], HeaderUtils::split('foo=123, bar', ',')); }
$this->assertSame([['foo=123', 'bar']], HeaderUtils::split('foo=123; bar', ',;'));
$this->assertSame([['foo=123'], ['bar']], HeaderUtils::split('foo=123, bar', ',;'));
$this->assertSame(['foo', '123, bar'], HeaderUtils::split('foo=123, bar', '='));
$this->assertSame(['foo', '123, bar'], HeaderUtils::split(' foo = 123, bar ', '='));
$this->assertSame([['foo', '123'], ['bar']], HeaderUtils::split('foo=123, bar', ',='));
$this->assertSame([[['foo', '123']], [['bar'], ['foo', '456']]], HeaderUtils::split('foo=123, bar; foo=456', ',;='));
$this->assertSame([[['foo', 'a,b;c=d']]], HeaderUtils::split('foo="a,b;c=d"', ',;='));
$this->assertSame(['foo', 'bar'], HeaderUtils::split('foo,,,, bar', ',')); public function provideHeaderToSplit(): array
$this->assertSame(['foo', 'bar'], HeaderUtils::split(',foo, bar,', ',')); {
$this->assertSame(['foo', 'bar'], HeaderUtils::split(' , foo, bar, ', ',')); return [
$this->assertSame(['foo bar'], HeaderUtils::split('foo "bar"', ',')); [['foo=123', 'bar'], 'foo=123,bar', ','],
$this->assertSame(['foo bar'], HeaderUtils::split('"foo" bar', ',')); [['foo=123', 'bar'], 'foo=123, bar', ','],
$this->assertSame(['foo bar'], HeaderUtils::split('"foo" "bar"', ',')); [[['foo=123', 'bar']], 'foo=123; bar', ',;'],
[[['foo=123'], ['bar']], 'foo=123, bar', ',;'],
[['foo', '123, bar'], 'foo=123, bar', '='],
[['foo', '123, bar'], ' foo = 123, bar ', '='],
[[['foo', '123'], ['bar']], 'foo=123, bar', ',='],
[[[['foo', '123']], [['bar'], ['foo', '456']]], 'foo=123, bar; foo=456', ',;='],
[[[['foo', 'a,b;c=d']]], 'foo="a,b;c=d"', ',;='],
// These are not a valid header values. We test that they parse anyway, [['foo', 'bar'], 'foo,,,, bar', ','],
// and that both the valid and invalid parts are returned. [['foo', 'bar'], ',foo, bar,', ','],
$this->assertSame([], HeaderUtils::split('', ',')); [['foo', 'bar'], ' , foo, bar, ', ','],
$this->assertSame([], HeaderUtils::split(',,,', ',')); [['foo bar'], 'foo "bar"', ','],
$this->assertSame(['foo', 'bar', 'baz'], HeaderUtils::split('foo, "bar", "baz', ',')); [['foo bar'], '"foo" bar', ','],
$this->assertSame(['foo', 'bar, baz'], HeaderUtils::split('foo, "bar, baz', ',')); [['foo bar'], '"foo" "bar"', ','],
$this->assertSame(['foo', 'bar, baz\\'], HeaderUtils::split('foo, "bar, baz\\', ','));
$this->assertSame(['foo', 'bar, baz\\'], HeaderUtils::split('foo, "bar, baz\\\\', ',')); [[['foo_cookie', 'foo=1&bar=2&baz=3'], ['expires', 'Tue, 22-Sep-2020 06:27:09 GMT'], ['path', '/']], 'foo_cookie=foo=1&bar=2&baz=3; expires=Tue, 22-Sep-2020 06:27:09 GMT; path=/', ';='],
[[['foo_cookie', 'foo=='], ['expires', 'Tue, 22-Sep-2020 06:27:09 GMT'], ['path', '/']], 'foo_cookie=foo==; expires=Tue, 22-Sep-2020 06:27:09 GMT; path=/', ';='],
[[['foo_cookie', 'foo=a=b'], ['expires', 'Tue, 22-Sep-2020 06:27:09 GMT'], ['path', '/']], 'foo_cookie=foo="a=b"; expires=Tue, 22-Sep-2020 06:27:09 GMT; path=/', ';='],
// These are not a valid header values. We test that they parse anyway,
// and that both the valid and invalid parts are returned.
[[], '', ','],
[[], ',,,', ','],
[['foo', 'bar', 'baz'], 'foo, "bar", "baz', ','],
[['foo', 'bar, baz'], 'foo, "bar, baz', ','],
[['foo', 'bar, baz\\'], 'foo, "bar, baz\\', ','],
[['foo', 'bar, baz\\'], 'foo, "bar, baz\\\\', ','],
];
} }
public function testCombine() public function testCombine()