From d4ff39206ac90acffc81972f2a0f13d2201e3df6 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 19 Mar 2011 14:32:43 -0400 Subject: [PATCH] Making CookieComponent use json_encode instead of a custom serialization. Fixes issues where values containing | or , would be handled incorrectly. Fixes #1593 --- .../Controller/Component/CookieComponent.php | 23 ++---- .../Component/CookieComponentTest.php | 75 +++++++++++-------- 2 files changed, 51 insertions(+), 47 deletions(-) diff --git a/lib/Cake/Controller/Component/CookieComponent.php b/lib/Cake/Controller/Component/CookieComponent.php index cca49a5bf..e515ea2e7 100644 --- a/lib/Cake/Controller/Component/CookieComponent.php +++ b/lib/Cake/Controller/Component/CookieComponent.php @@ -459,31 +459,20 @@ class CookieComponent extends Component { * Implode method to keep keys are multidimensional arrays * * @param array $array Map of key and values - * @return string String in the form key1|value1,key2|value2 + * @return string A json encoded string. */ - protected function _implode($array) { - $string = ''; - foreach ($array as $key => $value) { - $string .= ',' . $key . '|' . $value; - } - return substr($string, 1); + protected function _implode(array $array) { + return json_encode($array); } /** * Explode method to return array from string set in CookieComponent::_implode() * - * @param string $string String in the form key1|value1,key2|value2 + * @param string $string A string containing JSON encoded data, or a bare string. * @return array Map of key and values */ protected function _explode($string) { - $array = array(); - foreach (explode(',', $string) as $pair) { - $key = explode('|', $pair); - if (!isset($key[1])) { - return $key[0]; - } - $array[$key[0]] = $key[1]; - } - return $array; + $ret = json_decode($string, true); + return ($ret != null) ? $ret : $string; } } diff --git a/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php b/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php index 9254ef94c..2c9f2fa2d 100644 --- a/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php +++ b/lib/Cake/tests/Case/Controller/Component/CookieComponentTest.php @@ -238,6 +238,19 @@ class CookieComponentTest extends CakeTestCase { $this->Cookie->delete('tag'); } +/** + * test writing values that are not scalars + * + * @return void + */ + function testWriteArrayValues() { + $this->Cookie->secure = false; + $this->Cookie->expects($this->once())->method('_setcookie') + ->with('CakeTestCookie[Testing]', '[1,2,3]', time() + 10, '/', '', false, false); + + $this->Cookie->write('Testing', array(1, 2, 3), false); + } + /** * testReadingCookieValue * @@ -359,7 +372,6 @@ class CookieComponentTest extends CakeTestCase { * @return void */ function testReadingCookieDataOnStartup() { - $data = $this->Cookie->read('Encrytped_array'); $this->assertNull($data); @@ -378,28 +390,29 @@ class CookieComponentTest extends CakeTestCase { 'name' => $this->__encrypt('CakePHP'), 'version' => $this->__encrypt('1.2.0.x'), 'tag' => $this->__encrypt('CakePHP Rocks!')), - 'Plain_array' => 'name|CakePHP,version|1.2.0.x,tag|CakePHP Rocks!', + 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' => 'CakePHP Rocks!')); + $this->Cookie->startup(null); $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } @@ -413,19 +426,19 @@ class CookieComponentTest extends CakeTestCase { function testReadingCookieDataWithoutStartup() { $data = $this->Cookie->read('Encrytped_array'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = null; - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $_COOKIE['CakeTestCookie'] = array( 'Encrytped_array' => $this->__encrypt(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!')), @@ -433,7 +446,7 @@ class CookieComponentTest extends CakeTestCase { 'name' => $this->__encrypt('CakePHP'), 'version' => $this->__encrypt('1.2.0.x'), 'tag' => $this->__encrypt('CakePHP Rocks!')), - 'Plain_array' => 'name|CakePHP,version|1.2.0.x,tag|CakePHP Rocks!', + 'Plain_array' => '{"name":"CakePHP","version":"1.2.0.x","tag":"CakePHP Rocks!"}', 'Plain_multi_cookies' => array( 'name' => 'CakePHP', 'version' => '1.2.0.x', @@ -441,19 +454,19 @@ class CookieComponentTest extends CakeTestCase { $data = $this->Cookie->read('Encrytped_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Encrytped_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_array'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $data = $this->Cookie->read('Plain_multi_cookies'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); - $this->assertEqual($data, $expected); + $this->assertEquals($expected, $data); $this->Cookie->destroy(); unset($_COOKIE['CakeTestCookie']); } @@ -470,6 +483,22 @@ class CookieComponentTest extends CakeTestCase { $this->assertNull($this->Cookie->read('value')); } + +/** + * Implode method to keep keys are multidimensional arrays + * + * @param array $array Map of key and values + * @return string String in the form key1|value1,key2|value2 + */ + protected function _implode(array $array) { + return json_encode($array); + + $string = ''; + foreach ($array as $key => $value) { + $string .= ',' . $key . '|' . $value; + } + return substr($string, 1); + } /** * encrypt method @@ -480,23 +509,9 @@ class CookieComponentTest extends CakeTestCase { */ function __encrypt($value) { if (is_array($value)) { - $value = $this->__implode($value); + $value = $this->_implode($value); } return "Q2FrZQ==." . base64_encode(Security::cipher($value, $this->Cookie->key)); } -/** - * implode method - * - * @param array $value - * @return string - * @access private - */ - function __implode($array) { - $string = ''; - foreach ($array as $key => $value) { - $string .= ',' . $key . '|' . $value; - } - return substr($string, 1); - } }