From c58e58a491b128273c4e0a522051fd5b61e949e7 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 29 Aug 2008 03:11:35 +0000 Subject: [PATCH] Adding tests for secured forms. Fixes the issues related to checkboxes in multi row forms. git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@7533 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/controller/components/security.php | 6 +- cake/libs/view/helpers/form.php | 11 +- .../controller/components/security.test.php | 166 ++++++++++++++++++ .../cases/libs/view/helpers/form.test.php | 23 ++- 4 files changed, 194 insertions(+), 12 deletions(-) diff --git a/cake/libs/controller/components/security.php b/cake/libs/controller/components/security.php index b09f27b46..df03a5350 100644 --- a/cake/libs/controller/components/security.php +++ b/cake/libs/controller/components/security.php @@ -603,16 +603,16 @@ class SecurityComponent extends Object { $values = array_values($value); $k = array_keys($value); $count = count($k); - + if (is_numeric($k[0])) { for ($i = 0; $count > $i; $i++) { foreach ($values[$i] as $key2 => $value1) { - if ($value1 === '0') { + if ($value1 === '0' && !in_array($key2, $field[$newKey][$i])) { $field[$newKey][$i] = array_merge($field[$newKey][$i], array($key2)); } } } - $controller->data[$newKey] = Set::pushDiff($controller->data[$key], $controller->data[$newKey]); + $controller->data[$newKey] = Set::pushDiff($controller->data[$newKey], $controller->data[$key]); } for ($i = 0; $count > $i; $i++) { diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index ff537679f..24237ae84 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -361,9 +361,18 @@ class FormHelper extends AppHelper { } return; } + if ((isset($this->fields[$model]) && !in_array($field, $this->fields[$model], true)) || !isset($this->fields[$model])) { if (is_numeric($field)) { - $this->fields[$model][$field][] = $fieldSuffix; + if (!isset($this->fields[$model][$field])) { + $this->fields[$model][$field][] = $fieldSuffix; + } else if (!in_array($fieldSuffix, $this->fields[$model][$field])) { + if (!isset($this->fields[$model][$field])) { + $this->fields[$model][$field][] = $fieldSuffix; + } else if (!in_array($fieldSuffix, $this->fields[$model][$field])) { + $this->fields[$model][$field][] = $fieldSuffix; + } + } } else if (is_null($field)) { $this->fields[] = $model; } else { diff --git a/cake/tests/cases/libs/controller/components/security.test.php b/cake/tests/cases/libs/controller/components/security.test.php index 202740705..3d0bbf249 100644 --- a/cake/tests/cases/libs/controller/components/security.test.php +++ b/cake/tests/cases/libs/controller/components/security.test.php @@ -495,6 +495,9 @@ DIGEST; } /** * testValidatePostCheckbox method + * + * First block tests un-checked checkbox + * Second block tests checked checkbox * * @access public * @return void @@ -525,6 +528,34 @@ DIGEST; unset($data['_Model']); $data['Model']['valid'] = '0'; $this->assertEqual($this->Controller->data, $data); + + + $this->Controller->data = array(); + $this->Controller->Security->startup($this->Controller); + $key = $this->Controller->params['_Token']['key']; + + $data['Model']['username'] = ''; + $data['Model']['password'] = ''; + $data['Model']['valid'] = '1'; + $data['_Model']['valid'] = '0'; + $data['__Token']['key'] = $key; + + $fields = array( + 'Model' => array('username', 'password', 'valid'), + '_Model' => array('valid' => '0'), + '__Token' => array('key' => $key) + ); + $fields = $this->__sortFields($fields); + + $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt'))); + $data['__Token']['fields'] = $fields; + + $this->Controller->data = $data; + $result = $this->Controller->Security->validatePost($this->Controller); + $this->assertTrue($result); + + unset($data['_Model']); + $this->assertEqual($this->Controller->data, $data); } /** * testValidatePostHidden method @@ -690,6 +721,141 @@ DIGEST; $this->assertTrue($this->Controller->data == $data); } + +/** + * testValidateHasManyRecordsPass method + * + * @access public + * @return void + */ + function testValidateHasManyRecordsPass() { + $this->Controller->Security->startup($this->Controller); + $key = $this->Controller->params['_Token']['key']; + + $data = array( + 'Address' => array( + 0 => array( + 'title' => 'home', + 'first_name' => 'Bilbo', + 'last_name' => 'Baggins', + 'address' => '23 Bag end way', + 'city' => 'the shire', + 'phone' => 'N/A', + 'primary' => '1', + ), + 1 => array( + 'title' => 'home', + 'first_name' => 'Frodo', + 'last_name' => 'Baggins', + 'address' => '50 Bag end way', + 'city' => 'the shire', + 'phone' => 'N/A', + 'primary' => '1', + ), + ), + '_Address' => array( + 0 => array( + 'id' => '123', + 'primary' => '0', + ), + 1 => array( + 'id' => '124', + 'primary' => '0', + ) + ), + '__Token' => array( + 'key' => $key, + ), + ); + + $fields = array( + 'Address' => array( + 0 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary'), + 1 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary')), + '_Address' => array( + 0 => array('id' => '123', 'primary' => '0'), + 1 => array('id' => '124', 'primary' => '0')), + '__Token' => array('key' => $key) + ); + $fields = $this->__sortFields($fields); + $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt'))); + $data['__Token']['fields'] = $fields; + + $this->Controller->data = $data; + $result = $this->Controller->Security->validatePost($this->Controller); + $this->assertTrue($result); + + unset($data['_Address']); + $data['Address'][0]['id'] = '123'; + $data['Address'][1]['id'] = '124'; + + $this->assertEqual($this->Controller->data, $data); + } +/** + * testValidateHasManyRecords method + * + * validatePost should fail, hidden fields have been changed. + * + * @access public + * @return void + */ + function testValidateHasManyRecordsFail() { + $this->Controller->Security->startup($this->Controller); + $key = $this->Controller->params['_Token']['key']; + + $data = array( + 'Address' => array( + 0 => array( + 'title' => 'home', + 'first_name' => 'Bilbo', + 'last_name' => 'Baggins', + 'address' => '23 Bag end way', + 'city' => 'the shire', + 'phone' => 'N/A', + 'primary' => '1', + ), + 1 => array( + 'title' => 'home', + 'first_name' => 'Frodo', + 'last_name' => 'Baggins', + 'address' => '50 Bag end way', + 'city' => 'the shire', + 'phone' => 'N/A', + 'primary' => '1', + ), + ), + '_Address' => array( + 0 => array( + 'id' => '123', + 'primary' => '23', + ), + 1 => array( + 'id' => '124', + 'primary' => '0', + ) + ), + '__Token' => array( + 'key' => $key, + ), + ); + + $fields = array( + 'Address' => array( + 0 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary'), + 1 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary')), + '_Address' => array( + 0 => array('id' => '123', 'primary' => '0'), + 1 => array('id' => '124', 'primary' => '0')), + '__Token' => array('key' => $key) + ); + $fields = $this->__sortFields($fields); + $fields = urlencode(Security::hash(serialize($fields) . Configure::read('Security.salt'))); + $data['__Token']['fields'] = $fields; + + $this->Controller->data = $data; + $result = $this->Controller->Security->validatePost($this->Controller); + $this->assertFalse($result); + } /** * testLoginRequest method * diff --git a/cake/tests/cases/libs/view/helpers/form.test.php b/cake/tests/cases/libs/view/helpers/form.test.php index 6b2c1f167..03cf07a5f 100644 --- a/cake/tests/cases/libs/view/helpers/form.test.php +++ b/cake/tests/cases/libs/view/helpers/form.test.php @@ -685,7 +685,7 @@ class FormHelperTest extends CakeTestCase { function testFormSecurityMultipleInputFields() { $key = 'testKey'; $this->Form->params['_Token']['key'] = $key; - $this->Form->create(); + $this->Form->create('Addresses'); $this->Form->hidden('Addresses.0.id', array('value' => '123456')); $this->Form->input('Addresses.0.title'); @@ -694,6 +694,8 @@ class FormHelperTest extends CakeTestCase { $this->Form->input('Addresses.0.address'); $this->Form->input('Addresses.0.city'); $this->Form->input('Addresses.0.phone'); + $this->Form->input('Addresses.0.primary', array('type' => 'checkbox')); + $this->Form->hidden('Addresses.1.id', array('value' => '654321')); $this->Form->input('Addresses.1.title'); $this->Form->input('Addresses.1.first_name'); @@ -701,15 +703,19 @@ class FormHelperTest extends CakeTestCase { $this->Form->input('Addresses.1.address'); $this->Form->input('Addresses.1.city'); $this->Form->input('Addresses.1.phone'); + $this->Form->input('Addresses.1.primary', array('type' => 'checkbox')); $fields = array( 'Addresses' => array( - 0 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone'), - 1 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone')), + 0 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary'), + 1 => array('title', 'first_name', 'last_name', 'address', 'city', 'phone', 'primary') + ), '_Addresses' => array( - 0 => array('id' => '123456'), - 1 => array('id' => '654321')), - '__Token' => array('key' => $key)); + 0 => array('id' => '123456', 'primary' => '0'), + 1 => array('id' => '654321', 'primary' => '0') + ), + '__Token' => array('key' => $key) + ); $fields = $this->__sortFields($fields); $result = $this->Form->secure($this->Form->fields); @@ -721,6 +727,7 @@ class FormHelperTest extends CakeTestCase { ); $this->assertTags($result, $expected); } + /** * testFormSecurityMultipleInputDisabledFields method * @@ -4408,11 +4415,11 @@ class FormHelperTest extends CakeTestCase { */ function __sortFields($fields) { foreach ($fields as $key => $value) { - if ($key{0} !== '_') { + if ($key[0] != '_' && is_array($fields[$key])) { sort($fields[$key]); } } - ksort($fields); + ksort($fields, SORT_STRING); return $fields; } }