Making CookieComponent use json_encode instead of a custom

serialization.  Fixes issues where values containing | or , would be
handled incorrectly.  Fixes #1593
This commit is contained in:
mark_story 2011-03-19 14:32:43 -04:00
parent 961208c9be
commit d4ff39206a
2 changed files with 51 additions and 47 deletions

View file

@ -459,31 +459,20 @@ class CookieComponent extends Component {
* Implode method to keep keys are multidimensional arrays * Implode method to keep keys are multidimensional arrays
* *
* @param array $array Map of key and values * @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) { protected function _implode(array $array) {
$string = ''; return json_encode($array);
foreach ($array as $key => $value) {
$string .= ',' . $key . '|' . $value;
}
return substr($string, 1);
} }
/** /**
* Explode method to return array from string set in CookieComponent::_implode() * 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 * @return array Map of key and values
*/ */
protected function _explode($string) { protected function _explode($string) {
$array = array(); $ret = json_decode($string, true);
foreach (explode(',', $string) as $pair) { return ($ret != null) ? $ret : $string;
$key = explode('|', $pair);
if (!isset($key[1])) {
return $key[0];
}
$array[$key[0]] = $key[1];
}
return $array;
} }
} }

View file

@ -238,6 +238,19 @@ class CookieComponentTest extends CakeTestCase {
$this->Cookie->delete('tag'); $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 * testReadingCookieValue
* *
@ -359,7 +372,6 @@ class CookieComponentTest extends CakeTestCase {
* @return void * @return void
*/ */
function testReadingCookieDataOnStartup() { function testReadingCookieDataOnStartup() {
$data = $this->Cookie->read('Encrytped_array'); $data = $this->Cookie->read('Encrytped_array');
$this->assertNull($data); $this->assertNull($data);
@ -378,28 +390,29 @@ class CookieComponentTest extends CakeTestCase {
'name' => $this->__encrypt('CakePHP'), 'name' => $this->__encrypt('CakePHP'),
'version' => $this->__encrypt('1.2.0.x'), 'version' => $this->__encrypt('1.2.0.x'),
'tag' => $this->__encrypt('CakePHP Rocks!')), '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( 'Plain_multi_cookies' => array(
'name' => 'CakePHP', 'name' => 'CakePHP',
'version' => '1.2.0.x', 'version' => '1.2.0.x',
'tag' => 'CakePHP Rocks!')); 'tag' => 'CakePHP Rocks!'));
$this->Cookie->startup(null); $this->Cookie->startup(null);
$data = $this->Cookie->read('Encrytped_array'); $data = $this->Cookie->read('Encrytped_array');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Encrytped_multi_cookies');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Plain_array');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Plain_multi_cookies');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!');
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$this->Cookie->destroy(); $this->Cookie->destroy();
unset($_COOKIE['CakeTestCookie']); unset($_COOKIE['CakeTestCookie']);
} }
@ -413,19 +426,19 @@ class CookieComponentTest extends CakeTestCase {
function testReadingCookieDataWithoutStartup() { function testReadingCookieDataWithoutStartup() {
$data = $this->Cookie->read('Encrytped_array'); $data = $this->Cookie->read('Encrytped_array');
$expected = null; $expected = null;
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$data = $this->Cookie->read('Encrytped_multi_cookies'); $data = $this->Cookie->read('Encrytped_multi_cookies');
$expected = null; $expected = null;
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$data = $this->Cookie->read('Plain_array'); $data = $this->Cookie->read('Plain_array');
$expected = null; $expected = null;
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$data = $this->Cookie->read('Plain_multi_cookies'); $data = $this->Cookie->read('Plain_multi_cookies');
$expected = null; $expected = null;
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$_COOKIE['CakeTestCookie'] = array( $_COOKIE['CakeTestCookie'] = array(
'Encrytped_array' => $this->__encrypt(array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!')), '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'), 'name' => $this->__encrypt('CakePHP'),
'version' => $this->__encrypt('1.2.0.x'), 'version' => $this->__encrypt('1.2.0.x'),
'tag' => $this->__encrypt('CakePHP Rocks!')), '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( 'Plain_multi_cookies' => array(
'name' => 'CakePHP', 'name' => 'CakePHP',
'version' => '1.2.0.x', 'version' => '1.2.0.x',
@ -441,19 +454,19 @@ class CookieComponentTest extends CakeTestCase {
$data = $this->Cookie->read('Encrytped_array'); $data = $this->Cookie->read('Encrytped_array');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Encrytped_multi_cookies');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Plain_array');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $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'); $data = $this->Cookie->read('Plain_multi_cookies');
$expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!'); $expected = array('name' => 'CakePHP', 'version' => '1.2.0.x', 'tag' =>'CakePHP Rocks!');
$this->assertEqual($data, $expected); $this->assertEquals($expected, $data);
$this->Cookie->destroy(); $this->Cookie->destroy();
unset($_COOKIE['CakeTestCookie']); unset($_COOKIE['CakeTestCookie']);
} }
@ -470,6 +483,22 @@ class CookieComponentTest extends CakeTestCase {
$this->assertNull($this->Cookie->read('value')); $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 * encrypt method
@ -480,23 +509,9 @@ class CookieComponentTest extends CakeTestCase {
*/ */
function __encrypt($value) { function __encrypt($value) {
if (is_array($value)) { if (is_array($value)) {
$value = $this->__implode($value); $value = $this->_implode($value);
} }
return "Q2FrZQ==." . base64_encode(Security::cipher($value, $this->Cookie->key)); 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);
}
} }