From 8be685504e9afd0dea75bd5fa9fecd7a328bc5f7 Mon Sep 17 00:00:00 2001 From: phpnut Date: Wed, 2 May 2007 02:31:06 +0000 Subject: [PATCH] Adding ability to disable specific form data fields from being added to the validation key. Example of using this would be javascript that changes hidden fields, adding additional fields added using javascript, etc. This is set in a Controller::beforeFilter(). Example usage: {{{ $this->Security->disabledFields = array('fieldname', 'additional fields'); $this->Security->disabledFields = array('Model.fieldname', 'OtherModel.fieldname'); }}} git-svn-id: https://svn.cakephp.org/repo/branches/1.2.x.x@4978 3807eeeb-6ff5-0310-8944-8be069107fe0 --- cake/libs/controller/components/security.php | 46 +++++++++++++++++-- cake/libs/view/helpers/form.php | 48 +++++++++++++++++--- 2 files changed, 83 insertions(+), 11 deletions(-) diff --git a/cake/libs/controller/components/security.php b/cake/libs/controller/components/security.php index 10c11d3cd..e7afec2d1 100644 --- a/cake/libs/controller/components/security.php +++ b/cake/libs/controller/components/security.php @@ -114,6 +114,12 @@ class SecurityComponent extends Object { * @see SecurityComponent::requireAuth() */ var $allowedActions = array(); +/** + * Form fields to disable + * + * @var array + */ + var $disabledFields = array(); /** * Other components used by the Security component * @@ -443,10 +449,41 @@ class SecurityComponent extends Object { return null; } } - $fields = $controller->data['__Token']['fields']; + $form = $controller->data['__Token']['fields']; $check = $controller->data; unset($check['__Token']['fields']); + if(!empty($this->disabledFields)) { + foreach($check as $model => $fields) { + foreach($fields as $field => $value) { + $key[] = $model . '.' . $field; + } + unset($field); + } + + foreach($this->disabledFields as $value) { + $parts = preg_split('/\/|\./', $value); + + if (count($parts) == 1) { + $key1[] = $controller->modelClass . '.' . $parts['0']; + } elseif (count($parts) == 2) { + $key1[] = $parts['0'] . '.' . $parts['1']; + } + } + + foreach ($key1 as $value) { + + if(in_array($value, $key)) { + $remove = explode('.', $value); + unset($check[$remove['0']][$remove['1']]); + } elseif (in_array('_' . $value, $key)) { + $remove = explode('.', $value); + $controller->data[$remove['0']][$remove['1']] = $controller->data['_' . $remove['0']][$remove['1']]; + unset($check['_' . $remove['0']][$remove['1']]); + } + } + } + foreach($check as $key => $value) { if($key === '__Token') { $field[$key] = $value; @@ -464,7 +501,7 @@ class SecurityComponent extends Object { if(isset($values['0']) && empty($values['0'])) { $k = array_keys($value); if(isset($values['0'])) { - $field[$key][$k['0']] = null; + $field[$key][$k['0']] = ''; } } else { $field[$key] = $value; @@ -476,7 +513,7 @@ class SecurityComponent extends Object { } $check = urlencode(Security::hash(serialize($field) . CAKE_SESSION_STRING)); - if($fields !== $check) { + if($form !== $check) { if(!$this->blackHole($controller, 'auth')) { return null; } @@ -498,7 +535,8 @@ class SecurityComponent extends Object { $token = array('key' => $authKey, 'expires' => $expires, 'allowedControllers' => $this->allowedControllers, - 'allowedActions' => $this->allowedActions); + 'allowedActions' => $this->allowedActions, + 'disabledFields' => $this->disabledFields); if(!isset($controller->data)) { $controller->data = array(); diff --git a/cake/libs/view/helpers/form.php b/cake/libs/view/helpers/form.php index d132b83b0..b44ce3c79 100644 --- a/cake/libs/view/helpers/form.php +++ b/cake/libs/view/helpers/form.php @@ -253,6 +253,40 @@ class FormHelper extends AppHelper { $append .= '

'; return $append; } + function __secure($model = null, $options = null) { + if(!$model) { + $model = $this->model(); + } + + if(isset($this->params['_Token']) && !empty($this->params['_Token'])) { + if(!empty($this->params['_Token']['disabledFields'])) { + foreach ($this->params['_Token']['disabledFields'] as $value) { + $parts = preg_split('/\/|\./', $value); + if (count($parts) == 1) { + if($parts[0] === $this->field()) { + return; + } + } elseif (count($parts) == 2) { + if($parts[0] === $this->model() && $parts[1] === $this->field()) { + return; + } + } + } + if(!is_null($options)) { + $this->fields[$model][$this->field()] = $options; + return; + } + $this->fields[$model][] = $this->field(); + return; + } + if(!is_null($options)) { + $this->fields[$model][$this->field()] = $options; + return; + } + $this->fields[$model][] = $this->field(); + return; + } + } /** * Returns true if there is an error for the given field, otherwise false * @@ -556,7 +590,7 @@ class FormHelper extends AppHelper { * @return string An HTML text input element */ function text($fieldName, $options = array()) { - $this->fields[$this->model()][] = $this->field(); + $this->__secure(); $options = $this->__initInputField($fieldName, am(array('type' => 'text'), $options)); return $this->output(sprintf($this->Html->tags['input'], $this->model(), $this->field(), $this->_parseAttributes($options, null, null, ' '))); } @@ -568,7 +602,7 @@ class FormHelper extends AppHelper { * @return string */ function password($fieldName, $options = array()) { - $this->fields[$this->model()][] = $this->field(); + $this->__secure(); $options = $this->__initInputField($fieldName, $options); return $this->output(sprintf($this->Html->tags['password'], $this->model(), $this->field(), $this->_parseAttributes($options, null, null, ' '))); } @@ -580,7 +614,7 @@ class FormHelper extends AppHelper { * @return string An HTML text input element */ function textarea($fieldName, $options = array()) { - $this->fields[$this->model()][] = $this->field(); + $this->__secure(); $options = $this->__initInputField($fieldName, $options); unset($options['type']); $value = null; @@ -606,12 +640,12 @@ class FormHelper extends AppHelper { if(isset($this->params['_Token']) && !empty($this->params['_Token'])) { $model = '_' . $model; } - $this->fields[$model][$this->field()] = $options['value']; + $this->__secure($model, ife($options['value'], $options['value'], '')); if (in_array($fieldName, array('_method', '_fields'))) { $model = null; } - return $this->output(sprintf($this->Html->tags['hidden'], $model, $this->field(), $this->_parseAttributes($options, null, ' ', ' '))); + return $this->output(sprintf($this->Html->tags['hidden'], $model, $this->field(), $this->_parseAttributes($options, null, '', ' '))); } /** * Creates file input widget. @@ -622,7 +656,7 @@ class FormHelper extends AppHelper { * @access public */ function file($fieldName, $options = array()) { - $this->fields[$this->model()][] = $this->field(); + $this->__secure(); $options = $this->__initInputField($fieldName, $options); return $this->output(sprintf($this->Html->tags['file'], $this->model(), $this->field(), $this->_parseAttributes($options, null, '', ' '))); } @@ -727,7 +761,7 @@ class FormHelper extends AppHelper { function select($fieldName, $options = array(), $selected = null, $attributes = array(), $showEmpty = '') { $showParents = false; $this->setFormTag($fieldName); - $this->fields[$this->model()][] = $this->field(); + $this->__secure(); $attributes = $this->domId((array)$attributes); if ($this->tagIsInvalid()) {