From 9740b1f93876bdde4c72e4e3341f22ce6ba1994c Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Wed, 4 Sep 2013 23:29:18 +0200 Subject: [PATCH 1/9] add json value support for setCookie header with unittest --- src/Header/SetCookie.php | 10 +++------- test/Header/SetCookieTest.php | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/src/Header/SetCookie.php b/src/Header/SetCookie.php index 7a36cf3aed..d3ac6bbea6 100644 --- a/src/Header/SetCookie.php +++ b/src/Header/SetCookie.php @@ -205,13 +205,9 @@ public function getFieldValue() return ''; } - $value = $this->getValue(); - if (strpos($value, '"')!==false) { - $value = '"'.urlencode(str_replace('"', '', $value)).'"'; - } else { - $value = urlencode($value); - } - $fieldValue = $this->getName() . '=' . $value; + $value = urlencode($this->getValue()); + + $fieldValue = $this->getName() . '="' . $value .'"'; $version = $this->getVersion(); if ($version!==null) { diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 2c070e9a4b..43141cf58e 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -306,6 +306,26 @@ public function testToString($cStr, $info, $expected) $this->assertEquals($cookie->getFieldName() . ': ' . $expected, $cookie->toString()); } + public function testSetJsonValue() + { + $cookieName ="fooCookie"; + $jsonData = json_encode(array('foo'=>'bar')); + + $cookie= new SetCookie($cookieName,$jsonData); + + $regExp = sprintf('#^%s="%s"#',$cookieName,urlencode($jsonData)); + $this->assertRegExp($regExp,$cookie->getFieldValue()); + + $cookieName ="fooCookie"; + $jsonData = json_encode(array('foo'=>'bar')); + + $cookie= new SetCookie($cookieName,$jsonData); + $cookie->setDomain('example.org'); + + $regExp = sprintf('#^%s="%s"; Domain=#',$cookieName,urlencode($jsonData)); + $this->assertRegExp($regExp,$cookie->getFieldValue()); + } + /** * Provide valid cookie strings with information about them * From 0333db611671c495dde6c390c7cdd97e92aedbbf Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Thu, 5 Sep 2013 00:02:46 +0200 Subject: [PATCH 2/9] remove unneeded quote --- src/Header/SetCookie.php | 2 +- test/Header/SetCookieTest.php | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Header/SetCookie.php b/src/Header/SetCookie.php index d3ac6bbea6..b02a569797 100644 --- a/src/Header/SetCookie.php +++ b/src/Header/SetCookie.php @@ -207,7 +207,7 @@ public function getFieldValue() $value = urlencode($this->getValue()); - $fieldValue = $this->getName() . '="' . $value .'"'; + $fieldValue = $this->getName() . '=' . $value; $version = $this->getVersion(); if ($version!==null) { diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 43141cf58e..2f95dfb029 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -308,22 +308,22 @@ public function testToString($cStr, $info, $expected) public function testSetJsonValue() { - $cookieName ="fooCookie"; - $jsonData = json_encode(array('foo'=>'bar')); + $cookieName ="fooCookie"; + $jsonData = json_encode(array('foo'=>'bar')); - $cookie= new SetCookie($cookieName,$jsonData); + $cookie= new SetCookie($cookieName,$jsonData); - $regExp = sprintf('#^%s="%s"#',$cookieName,urlencode($jsonData)); - $this->assertRegExp($regExp,$cookie->getFieldValue()); + $regExp = sprintf('#^%s=%s#',$cookieName,urlencode($jsonData)); + $this->assertRegExp($regExp,$cookie->getFieldValue()); - $cookieName ="fooCookie"; - $jsonData = json_encode(array('foo'=>'bar')); + $cookieName ="fooCookie"; + $jsonData = json_encode(array('foo'=>'bar')); - $cookie= new SetCookie($cookieName,$jsonData); - $cookie->setDomain('example.org'); + $cookie= new SetCookie($cookieName,$jsonData); + $cookie->setDomain('example.org'); - $regExp = sprintf('#^%s="%s"; Domain=#',$cookieName,urlencode($jsonData)); - $this->assertRegExp($regExp,$cookie->getFieldValue()); + $regExp = sprintf('#^%s=%s; Domain=#',$cookieName,urlencode($jsonData)); + $this->assertRegExp($regExp,$cookie->getFieldValue()); } /** From 9d6af4b2d39740742bc8b8d98a26b33de7fb233c Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Thu, 5 Sep 2013 19:55:47 +0200 Subject: [PATCH 3/9] use regexp to detect the headValue support qouted value without urldecode bug --- src/Header/SetCookie.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Header/SetCookie.php b/src/Header/SetCookie.php index b02a569797..ad9e8957fe 100644 --- a/src/Header/SetCookie.php +++ b/src/Header/SetCookie.php @@ -100,8 +100,9 @@ public static function fromString($headerLine, $bypassHeaderFieldName = false) $keyValuePairs = preg_split('#;\s*#', $headerLine); foreach ($keyValuePairs as $keyValue) { - if (strpos($keyValue, '=')) { - list($headerKey, $headerValue) = preg_split('#=\s*#', $keyValue, 2); + if (preg_match('#^(?[^=]+)=\s*("?)(?[^"]+)\2#',$keyValue,$matches)) { + $headerKey = $matches['headerKey']; + $headerValue= $matches['headerValue']; } else { $headerKey = $keyValue; $headerValue = null; From 9e97869356f8e1956e51afe4cd1afc07d1fa1931 Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Thu, 5 Sep 2013 21:26:10 +0200 Subject: [PATCH 4/9] add missing quotes around the header Value from set-cookie header --- src/Header/SetCookie.php | 2 +- test/Header/SetCookieTest.php | 32 ++++++++++++++++---------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/Header/SetCookie.php b/src/Header/SetCookie.php index ad9e8957fe..243cf92290 100644 --- a/src/Header/SetCookie.php +++ b/src/Header/SetCookie.php @@ -208,7 +208,7 @@ public function getFieldValue() $value = urlencode($this->getValue()); - $fieldValue = $this->getName() . '=' . $value; + $fieldValue = $this->getName() . '="' . $value . '"'; $version = $this->getVersion(); if ($version!==null) { diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 2f95dfb029..37a4bbe08a 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -338,7 +338,7 @@ public static function validCookieWithInfoProvider() return array( array( - 'Set-Cookie: justacookie=foo; domain=example.com', + 'Set-Cookie: justacookie="foo"; domain=example.com', array( 'name' => 'justacookie', 'value' => 'foo', @@ -348,10 +348,10 @@ public static function validCookieWithInfoProvider() 'secure' => false, 'httponly'=> false ), - 'justacookie=foo; Domain=example.com' + 'justacookie="foo"; Domain=example.com' ), array( - 'Set-Cookie: expires=tomorrow; secure; path=/Space Out/; expires=Tue, 21-Nov-2006 08:33:44 GMT; domain=.example.com', + 'Set-Cookie: expires="tomorrow"; secure; path=/Space Out/; expires=Tue, 21-Nov-2006 08:33:44 GMT; domain=.example.com', array( 'name' => 'expires', 'value' => 'tomorrow', @@ -361,10 +361,10 @@ public static function validCookieWithInfoProvider() 'secure' => true, 'httponly'=> false ), - 'expires=tomorrow; Expires=Tue, 21-Nov-2006 08:33:44 GMT; Domain=.example.com; Path=/Space Out/; Secure' + 'expires="tomorrow"; Expires=Tue, 21-Nov-2006 08:33:44 GMT; Domain=.example.com; Path=/Space Out/; Secure' ), array( - 'Set-Cookie: domain=unittests; expires=' . gmdate('D, d-M-Y H:i:s', $now) . ' GMT; domain=example.com; path=/some%20value/', + 'Set-Cookie: domain="unittests"; expires=' . gmdate('D, d-M-Y H:i:s', $now) . ' GMT; domain=example.com; path=/some%20value/', array( 'name' => 'domain', 'value' => 'unittests', @@ -374,10 +374,10 @@ public static function validCookieWithInfoProvider() 'secure' => false, 'httponly'=> false ), - 'domain=unittests; Expires=' . gmdate('D, d-M-Y H:i:s', $now) . ' GMT; Domain=example.com; Path=/some%20value/' + 'domain="unittests"; Expires=' . gmdate('D, d-M-Y H:i:s', $now) . ' GMT; Domain=example.com; Path=/some%20value/' ), array( - 'Set-Cookie: path=indexAction; path=/; domain=.foo.com; expires=' . gmdate('D, d-M-Y H:i:s', $yesterday) . ' GMT', + 'Set-Cookie: path="indexAction"; path=/; domain=.foo.com; expires=' . gmdate('D, d-M-Y H:i:s', $yesterday) . ' GMT', array( 'name' => 'path', 'value' => 'indexAction', @@ -387,11 +387,11 @@ public static function validCookieWithInfoProvider() 'secure' => false, 'httponly'=> false ), - 'path=indexAction; Expires=' . gmdate('D, d-M-Y H:i:s', $yesterday) . ' GMT; Domain=.foo.com; Path=/' + 'path="indexAction"; Expires=' . gmdate('D, d-M-Y H:i:s', $yesterday) . ' GMT; Domain=.foo.com; Path=/' ), array( - 'Set-Cookie: secure=sha1; secure; SECURE; domain=some.really.deep.domain.com', + 'Set-Cookie: secure="sha1"; secure; SECURE; domain=some.really.deep.domain.com', array( 'name' => 'secure', 'value' => 'sha1', @@ -401,10 +401,10 @@ public static function validCookieWithInfoProvider() 'secure' => true, 'httponly'=> false ), - 'secure=sha1; Domain=some.really.deep.domain.com; Secure' + 'secure="sha1"; Domain=some.really.deep.domain.com; Secure' ), array( - 'Set-Cookie: justacookie=foo; domain=example.com; httpOnly', + 'Set-Cookie: justacookie="foo"; domain=example.com; httpOnly', array( 'name' => 'justacookie', 'value' => 'foo', @@ -414,10 +414,10 @@ public static function validCookieWithInfoProvider() 'secure' => false, 'httponly'=> true ), - 'justacookie=foo; Domain=example.com; HttpOnly' + 'justacookie="foo"; Domain=example.com; HttpOnly' ), array( - 'Set-Cookie: PHPSESSID=123456789+abcd%2Cef; secure; domain=.localdomain; path=/foo/baz; expires=Tue, 21-Nov-2006 08:33:44 GMT;', + 'Set-Cookie: PHPSESSID="123456789+abcd%2Cef"; secure; domain=.localdomain; path=/foo/baz; expires=Tue, 21-Nov-2006 08:33:44 GMT;', array( 'name' => 'PHPSESSID', 'value' => '123456789+abcd%2Cef', @@ -427,10 +427,10 @@ public static function validCookieWithInfoProvider() 'secure' => true, 'httponly'=> false ), - 'PHPSESSID=123456789+abcd%2Cef; Expires=Tue, 21-Nov-2006 08:33:44 GMT; Domain=.localdomain; Path=/foo/baz; Secure' + 'PHPSESSID="123456789+abcd%2Cef"; Expires=Tue, 21-Nov-2006 08:33:44 GMT; Domain=.localdomain; Path=/foo/baz; Secure' ), array( - 'Set-Cookie: myname=myvalue; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly', + 'Set-Cookie: myname="myvalue"; Domain=docs.foo.com; Path=/accounts; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Secure; HttpOnly', array( 'name' => 'myname', 'value' => 'myvalue', @@ -440,7 +440,7 @@ public static function validCookieWithInfoProvider() 'secure' => true, 'httponly'=> true ), - 'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Domain=docs.foo.com; Path=/accounts; Secure; HttpOnly' + 'myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT; Domain=docs.foo.com; Path=/accounts; Secure; HttpOnly' ), array( 'Set-Cookie:', From 67f7a3e277a09166e69b54dbb2aac3c1e38795b6 Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Thu, 5 Sep 2013 22:25:43 +0200 Subject: [PATCH 5/9] add last missing quotes --- test/Header/SetCookieTest.php | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 37a4bbe08a..27ec29988c 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -108,7 +108,7 @@ public function testSetCookieGetFieldValueReturnsProperValue() $setCookieHeader->setSecure(true); $setCookieHeader->setHttponly(true); - $target = 'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + $target = 'myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly'; @@ -126,7 +126,7 @@ public function testSetCookieToStringReturnsHeaderFormattedString() $setCookieHeader->setSecure(true); $setCookieHeader->setHttponly(true); - $target = 'Set-Cookie: myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly'; @@ -147,7 +147,7 @@ public function testSetCookieCanAppendOtherHeadersInWhenCreatingString() $appendCookie = new SetCookie('othername', 'othervalue'); $headerLine = $setCookieHeader->toStringMultipleHeaders(array($appendCookie)); - $target = 'Set-Cookie: myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly, othername=othervalue'; $this->assertEquals($target, $headerLine); @@ -164,7 +164,7 @@ public function testSetCookieAttributesAreUnsettable() $setCookieHeader->setSecure(true); $setCookieHeader->setHttponly(true); - $target = 'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + $target = 'myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly'; $this->assertSame($target, $setCookieHeader->getFieldValue()); // attributes set @@ -174,7 +174,7 @@ public function testSetCookieAttributesAreUnsettable() $setCookieHeader->setPath(NULL); $setCookieHeader->setSecure(NULL); $setCookieHeader->setHttponly(NULL); - $this->assertSame('myname=myvalue', $setCookieHeader->getFieldValue()); // attributes unset + $this->assertSame('myname="myvalue"', $setCookieHeader->getFieldValue()); // attributes unset $setCookieHeader->setValue(NULL); $this->assertSame('myname=', $setCookieHeader->getFieldValue()); @@ -199,7 +199,7 @@ public function testSetCookieFieldValueIsEmptyStringWhenNameIsUnset() $setCookieHeader->setSecure(true); $setCookieHeader->setHttponly(true); - $target = 'myname=myvalue; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + $target = 'myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly'; $this->assertSame($target, $setCookieHeader->getFieldValue()); // not empty @@ -220,7 +220,7 @@ public function testSetCookieSetExpiresWithZeroTimeStamp() $setCookieHeader->setExpires(0); $this->assertSame('Thu, 01-Jan-1970 00:00:00 GMT', $setCookieHeader->getExpires()); - $target = 'myname=myvalue; Expires=Thu, 01-Jan-1970 00:00:00 GMT'; + $target = 'myname="myvalue"; Expires=Thu, 01-Jan-1970 00:00:00 GMT'; $this->assertSame($target, $setCookieHeader->getFieldValue()); } @@ -237,7 +237,7 @@ public function testSetCookieSetExpiresWithUnixEpochString() $this->assertSame('Thu, 01-Jan-1970 00:00:00 GMT', $setCookieHeader->getExpires()); $this->assertSame(0, $setCookieHeader->getExpires(true)); - $target = 'myname=myvalue; Expires=Thu, 01-Jan-1970 00:00:00 GMT'; + $target = 'myname="myvalue"; Expires=Thu, 01-Jan-1970 00:00:00 GMT'; $this->assertSame($target, $setCookieHeader->getFieldValue()); } @@ -313,7 +313,7 @@ public function testSetJsonValue() $cookie= new SetCookie($cookieName,$jsonData); - $regExp = sprintf('#^%s=%s#',$cookieName,urlencode($jsonData)); + $regExp = sprintf('#^%s="%s"#',$cookieName,urlencode($jsonData)); $this->assertRegExp($regExp,$cookie->getFieldValue()); $cookieName ="fooCookie"; @@ -322,7 +322,7 @@ public function testSetJsonValue() $cookie= new SetCookie($cookieName,$jsonData); $cookie->setDomain('example.org'); - $regExp = sprintf('#^%s=%s; Domain=#',$cookieName,urlencode($jsonData)); + $regExp = sprintf('#^%s="%s"; Domain=#',$cookieName,urlencode($jsonData)); $this->assertRegExp($regExp,$cookie->getFieldValue()); } From 57d692e3d8371eea6e21b4d400c549a439dab1eb Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Thu, 5 Sep 2013 23:10:21 +0200 Subject: [PATCH 6/9] add last missing quotes --- test/Header/SetCookieTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 27ec29988c..e2e96b1dd7 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -149,7 +149,7 @@ public function testSetCookieCanAppendOtherHeadersInWhenCreatingString() $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' - . ' Secure; HttpOnly, othername=othervalue'; + . ' Secure; HttpOnly, othername="othervalue"'; $this->assertEquals($target, $headerLine); } @@ -177,7 +177,7 @@ public function testSetCookieAttributesAreUnsettable() $this->assertSame('myname="myvalue"', $setCookieHeader->getFieldValue()); // attributes unset $setCookieHeader->setValue(NULL); - $this->assertSame('myname=', $setCookieHeader->getFieldValue()); + $this->assertSame('myname=""', $setCookieHeader->getFieldValue()); $this->assertNull($setCookieHeader->getValue()); $this->assertNull($setCookieHeader->getExpires()); $this->assertNull($setCookieHeader->getDomain()); From 9301ec4f24007d34c55aa9f8b8d06e172ef57134 Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Fri, 6 Sep 2013 00:03:55 +0200 Subject: [PATCH 7/9] make Zend\Http\Header\SetCookie RFC conform --- src/Header/SetCookie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Header/SetCookie.php b/src/Header/SetCookie.php index 243cf92290..bc560a2464 100644 --- a/src/Header/SetCookie.php +++ b/src/Header/SetCookie.php @@ -601,7 +601,7 @@ public function toStringMultipleHeaders(array $headers) 'The SetCookie multiple header implementation can only accept an array of SetCookie headers' ); } - $headerLine .= ', ' . $header->getFieldValue(); + $headerLine .= "\n" . $header->toString(); } return $headerLine; } From bac22e0ced5b979e6d9d48f31ca952297cb0a21a Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Fri, 6 Sep 2013 09:56:51 +0200 Subject: [PATCH 8/9] update Unit-Test to RFC conform --- test/Header/SetCookieTest.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index e2e96b1dd7..5c8311301d 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -150,6 +150,12 @@ public function testSetCookieCanAppendOtherHeadersInWhenCreatingString() $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly, othername="othervalue"'; + $this->assertNotEquals($target, $headerLine); + + $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' + . ' Domain=docs.foo.com; Path=/accounts;' + . ' Secure; HttpOnly'; + $target.= 'Set-Cookie: othername="othervalue"'; $this->assertEquals($target, $headerLine); } From ebe7a2a88f23ee24a5cb94627eaff0dae43c4d0e Mon Sep 17 00:00:00 2001 From: Clemens Sahs Date: Fri, 6 Sep 2013 10:06:22 +0200 Subject: [PATCH 9/9] add missing linebreak in test --- test/Header/SetCookieTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/test/Header/SetCookieTest.php b/test/Header/SetCookieTest.php index 5c8311301d..17075864c9 100644 --- a/test/Header/SetCookieTest.php +++ b/test/Header/SetCookieTest.php @@ -155,6 +155,7 @@ public function testSetCookieCanAppendOtherHeadersInWhenCreatingString() $target = 'Set-Cookie: myname="myvalue"; Expires=Wed, 13-Jan-2021 22:23:01 GMT;' . ' Domain=docs.foo.com; Path=/accounts;' . ' Secure; HttpOnly'; + $target.= "\n"; $target.= 'Set-Cookie: othername="othervalue"'; $this->assertEquals($target, $headerLine); }