Browse Source

changed FormHelper::secure() and FormHelper::end() to support attributes in the hidden CSRF-protection tags that are being generated for SecurityComponent to allow specification of additional html attributes like HTML5s "form" attribute. This allows separation of Form instantiation/controls and form data - for instance within html tables

improved tests for testing against additional attributes for Form::secure()

improved tests for testing against additional attributes for Form::end()

removed array cast, fixed test

fixed docblock format

format

Fixed a bug, this won't work as some forms are just empty
Jonas 12 years ago
parent
commit
b32deed4aa

+ 21 - 7
lib/Cake/Test/Case/View/Helper/FormHelperTest.php

@@ -689,9 +689,10 @@ class FormHelperTest extends CakeTestCase {
 	public function testFormSecurityFields() {
 		$key = 'testKey';
 		$fields = array('Model.password', 'Model.username', 'Model.valid' => '0');
-
+		$secureAttributes = array('form' => 'MyTestForm');
+		
 		$this->Form->request['_Token'] = array('key' => $key);
-		$result = $this->Form->secure($fields);
+		$result = $this->Form->secure($fields, $secureAttributes);
 
 		$hash = Security::hash(serialize($fields) . Configure::read('Security.salt'));
 		$hash .= ':' . 'Model.valid';
@@ -701,11 +702,13 @@ class FormHelperTest extends CakeTestCase {
 			'div' => array('style' => 'display:none;'),
 			array('input' => array(
 				'type' => 'hidden', 'name' => 'data[_Token][fields]',
-				'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
+				'value' => $hash, 'id' => 'preg:/TokenFields\d+/',
+				'form' => 'MyTestForm',
 			)),
 			array('input' => array(
 				'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
-				'value' => '', 'id' => 'preg:/TokenUnlocked\d+/'
+				'value' => '', 'id' => 'preg:/TokenUnlocked\d+/',
+				'form' => 'MyTestForm',
 			)),
 			'/div'
 		);
@@ -713,16 +716,18 @@ class FormHelperTest extends CakeTestCase {
 
 		$path = CAKE . 'Test' . DS . 'test_app' . DS . 'Config' . DS;
 		$this->Form->Html->loadConfig('htmlhelper_tags', $path);
-		$result = $this->Form->secure($fields);
+		$result = $this->Form->secure($fields, $secureAttributes);
 		$expected = array(
 			'div' => array('class' => 'hidden'),
 			array('input' => array(
 				'type' => 'hidden', 'name' => 'data[_Token][fields]',
-				'value' => $hash, 'id' => 'preg:/TokenFields\d+/'
+				'value' => $hash, 'id' => 'preg:/TokenFields\d+/',
+				'form' => 'MyTestForm',
 			)),
 			array('input' => array(
 				'type' => 'hidden', 'name' => 'data[_Token][unlocked]',
-				'value' => '', 'id' => 'preg:/TokenUnlocked\d+/'
+				'value' => '', 'id' => 'preg:/TokenUnlocked\d+/',
+				'form' => 'MyTestForm',
 			)),
 			'/div'
 		);
@@ -9047,6 +9052,15 @@ class FormHelperTest extends CakeTestCase {
 	public function testFormEnd() {
 		$this->assertEquals('</form>', $this->Form->end());
 
+		$result = $this->Form->end('', array('form' => 'MyTestFormWithSupportForSecurityComponent'));
+		$expected = array(
+			'div' => array('class' => 'submit'),
+			'input' => array('type' => 'submit', 'value' => '', 'form' => 'MyTestFormWithSupportForSecurityComponent'),
+			'/div',
+			'/form'
+		);
+		$this->assertTags($result, $expected);
+
 		$result = $this->Form->end('');
 		$expected = array(
 			'div' => array('class' => 'submit'),

+ 23 - 9
lib/Cake/View/Helper/FormHelper.php

@@ -498,11 +498,16 @@ class FormHelper extends AppHelper {
  * array('label' => 'save', 'name' => 'Whatever', 'div' => array('class' => 'good')); <div class="good"> value="save" name="Whatever"
  * }}}
  *
+ * If $secureAttributes is set, these html attributes will be merged into the hidden input tags generated for the
+ * Security Component. This is especially useful to set HTML5 attributes like 'form'
+ *
  * @param string|array $options as a string will use $options as the value of button,
+ * @param array $secureAttributes will be passed as html attributes into the hidden input elements generated for the
+ *   Security Component.
  * @return string a closing FORM tag optional submit button.
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#closing-the-form
  */
-	public function end($options = null) {
+	public function end($options = null, $secureAttributes = array()) {
 		$out = null;
 		$submit = null;
 
@@ -524,7 +529,7 @@ class FormHelper extends AppHelper {
 			isset($this->request['_Token']) &&
 			!empty($this->request['_Token'])
 		) {
-			$out .= $this->secure($this->fields);
+			$out .= $this->secure($this->fields, $secureAttributes);
 			$this->fields = array();
 		}
 		$this->setEntity(null);
@@ -538,17 +543,24 @@ class FormHelper extends AppHelper {
 /**
  * Generates a hidden field with a security hash based on the fields used in the form.
  *
- * @param array $fields The list of fields to use when generating the hash
+ * If $secureAttributes is set, these html attributes will be merged into the hidden input tags generated for the
+ * Security Component. This is especially useful to set HTML5 attributes like 'form'.
+ *
+ * @param array|null $fields If set specifies the list of fields to use when generating the hash, else $this->fields
+ *   is being used.
+ * @param array $secureAttributes will be passed as html attributes into the hidden input elements generated for the
+ *   Security Component.
  * @return string A hidden input field with a security hash
  * @link http://book.cakephp.org/2.0/en/core-libraries/helpers/form.html#FormHelper::secure
  */
-	public function secure($fields = array()) {
+	public function secure($fields = array(), $secureAttributes = array()) {
+		
 		if (!isset($this->request['_Token']) || empty($this->request['_Token'])) {
 			return;
 		}
 		$locked = array();
 		$unlockedFields = $this->_unlockedFields;
-
+		
 		foreach ($fields as $key => $value) {
 			if (!is_int($key)) {
 				$locked[$key] = $value;
@@ -565,14 +577,16 @@ class FormHelper extends AppHelper {
 		$unlocked = implode($unlockedFields, '|');
 		$fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'), 'sha1');
 
-		$out = $this->hidden('_Token.fields', array(
+		$tokenFields = array_merge($secureAttributes, array(
 			'value' => urlencode($fields . ':' . $locked),
-			'id' => 'TokenFields' . mt_rand()
+			'id' => 'TokenFields' . mt_rand(),
 		));
-		$out .= $this->hidden('_Token.unlocked', array(
+		$out = $this->hidden('_Token.fields', $tokenFields);
+		$tokenUnlocked = array_merge($secureAttributes, array(
 			'value' => urlencode($unlocked),
-			'id' => 'TokenUnlocked' . mt_rand()
+			'id' => 'TokenUnlocked' . mt_rand(),
 		));
+		$out .= $this->hidden('_Token.unlocked', $tokenUnlocked);
 		return $this->Html->useTag('hiddenblock', $out);
 	}