Browse Source

Merge branch 'master' into 2.5

mark_story 12 years ago
parent
commit
de0062de77

+ 1 - 0
lib/Cake/Console/ShellDispatcher.php

@@ -323,6 +323,7 @@ class ShellDispatcher {
 	protected function _parsePaths($args) {
 		$parsed = array();
 		$keys = array('-working', '--working', '-app', '--app', '-root', '--root');
+		$args = (array)$args;
 		foreach ($keys as $key) {
 			while (($index = array_search($key, $args)) !== false) {
 				$keyname = str_replace('-', '', $key);

+ 7 - 1
lib/Cake/Controller/Component/SecurityComponent.php

@@ -510,7 +510,13 @@ class SecurityComponent extends Component {
 
 		$fieldList += $lockedFields;
 		$unlocked = implode('|', $unlocked);
-		$check = Security::hash(serialize($fieldList) . $unlocked . Configure::read('Security.salt'), 'sha1');
+		$hashParts = array(
+			$this->request->here(),
+			serialize($fieldList),
+			$unlocked,
+			Configure::read('Security.salt')
+		);
+		$check = Security::hash(implode('', $hashParts), 'sha1');
 		return ($token === $check);
 	}
 

+ 1 - 1
lib/Cake/Model/Model.php

@@ -1867,9 +1867,9 @@ class Model extends Object implements CakeEventListener {
 				$success = $this->data;
 			}
 
-			$this->data = false;
 			$this->_clearCache();
 			$this->validationErrors = array();
+			$this->data = false;
 		}
 
 		$this->whitelist = $_whitelist;

+ 34 - 19
lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php

@@ -142,8 +142,12 @@ class SecurityComponentTest extends CakeTestCase {
 	public function setUp() {
 		parent::setUp();
 
-		$request = new CakeRequest('posts/index', false);
+		$request = $this->getMock('CakeRequest', ['here'], ['posts/index', false]);
 		$request->addParams(array('controller' => 'posts', 'action' => 'index'));
+		$request->expects($this->any())
+			->method('here')
+			->will($this->returnValue('/posts/index'));
+
 		$this->Controller = new SecurityTestController($request);
 		$this->Controller->Components->init($this->Controller);
 		$this->Controller->Security = $this->Controller->TestSecurity;
@@ -485,7 +489,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
+		$fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -565,7 +569,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'f7d573650a295b94e0938d32b323fde775e5f32b%3A';
+		$fields = '38504e4a341d4e6eadb437217efd91270e558d55%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -584,7 +588,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '540ac9c60d323c22bafe997b72c0790f39a8bdef%3A';
+		$fields = 'c5bc49a6c938c820e7e538df3d8ab7bffbc97ef9%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -605,7 +609,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '69f493434187b867ea14b901fdf58b55d27c935d%3A';
+		$fields = '5415d31b4483c1e09ddb58d2a91ba9650b12aa83%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -626,7 +630,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'c9118120e680a7201b543f562e5301006ccfcbe2%3AAddresses.0.id%7CAddresses.1.id';
+		$fields = 'b72a99e923687687bb5e64025d3cc65e1cecced4%3AAddresses.0.id%7CAddresses.1.id';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -655,7 +659,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->startup($this->Controller);
 
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '422cde416475abc171568be690a98cad20e66079%3A';
+		$fields = '8a764bdb989132c1d46f9a45f64ce2da5f9eebb9%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -679,7 +683,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$result = $this->Controller->Security->validatePost($this->Controller);
 		$this->assertTrue($result);
 
-		$fields = '19464422eafe977ee729c59222af07f983010c5f%3A';
+		$fields = '722de3615e63fdff899e86e85e6498b11c50bb66%3A';
 		$this->Controller->request->data = array(
 			'User.password' => 'bar', 'User.name' => 'foo', 'User.is_valid' => '1',
 			'Tag' => array('Tag' => array(1)),
@@ -700,7 +704,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testValidatePostCheckbox() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
+		$fields = '01c1f6dbba02ac6f21b229eab1cc666839b14303%3AModel.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -711,7 +715,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$result = $this->Controller->Security->validatePost($this->Controller);
 		$this->assertTrue($result);
 
-		$fields = '874439ca69f89b4c4a5f50fb9c36ff56a28f5d42%3A';
+		$fields = 'efbcf463a2c31e97c85d95eedc41dff9e9c6a026%3A';
 
 		$this->Controller->request->data = array(
 			'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
@@ -742,7 +746,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testValidatePostHidden() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '51ccd8cb0997c7b3d4523ecde5a109318405ef8c%3AModel.hidden%7CModel.other_hidden';
+		$fields = 'baaf832a714b39a0618238ac89c7065fc8ec853e%3AModel.hidden%7CModel.other_hidden';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -765,7 +769,7 @@ class SecurityComponentTest extends CakeTestCase {
 		$this->Controller->Security->disabledFields = array('Model.username', 'Model.password');
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'ef1082968c449397bcd849f963636864383278b1%3AModel.hidden';
+		$fields = 'aa7f254ebd8bf2ef118bc5ca1e191d1ae96857f5%3AModel.hidden';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -789,7 +793,12 @@ class SecurityComponentTest extends CakeTestCase {
 		$key = $this->Controller->request->params['_Token']['key'];
 		$unlocked = 'Model.username';
 		$fields = array('Model.hidden', 'Model.password');
-		$fields = urlencode(Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt')));
+		$fields = urlencode(Security::hash(
+			'/posts/index' . 
+			serialize($fields) .
+			$unlocked .
+			Configure::read('Security.salt'))
+		);
 
 		$this->Controller->request->data = array(
 			'Model' => array(
@@ -864,7 +873,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testValidateHiddenMultipleModel() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = 'a2d01072dc4660eea9d15007025f35a7a5b58e18%3AModel.valid%7CModel2.valid%7CModel3.valid';
+		$fields = '38dd8a37bbb52e67ee4eb812bf1725a6a18b989b%3AModel.valid%7CModel2.valid%7CModel3.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -885,7 +894,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testValidateHasManyModel() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '51e3b55a6edd82020b3f29c9ae200e14bbeb7ee5%3AModel.0.hidden%7CModel.0.valid';
+		$fields = 'dcef68de6634c60d2e60484ad0e2faec003456e6%3AModel.0.hidden%7CModel.0.valid';
 		$fields .= '%7CModel.1.hidden%7CModel.1.valid';
 		$unlocked = '';
 
@@ -915,7 +924,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testValidateHasManyRecordsPass() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C';
+		$fields = '8b6880fbbd4b69279155f899652ecffdd9b4c5a1%3AAddress.0.id%7CAddress.0.primary%7C';
 		$fields .= 'Address.1.id%7CAddress.1.primary';
 		$unlocked = '';
 
@@ -959,7 +968,13 @@ class SecurityComponentTest extends CakeTestCase {
 		$key = $this->Controller->request->params['_Token']['key'];
 		$unlocked = '';
 		$hashFields = array('TaxonomyData');
-		$fields = urlencode(Security::hash(serialize($hashFields) . $unlocked . Configure::read('Security.salt')));
+		$fields = urlencode(
+			Security::hash(
+			'/posts/index' .
+			serialize($hashFields) .
+			$unlocked .
+			Configure::read('Security.salt'), 'sha1')
+		);
 
 		$this->Controller->request->data = array(
 			'TaxonomyData' => array(
@@ -1024,7 +1039,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testFormDisabledFields() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '11842060341b9d0fc3808b90ba29fdea7054d6ad%3An%3A0%3A%7B%7D';
+		$fields = '216ee717efd1a251a6d6e9efbb96005a9d09f1eb%3An%3A0%3A%7B%7D';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -1055,7 +1070,7 @@ class SecurityComponentTest extends CakeTestCase {
 	public function testRadio() {
 		$this->Controller->Security->startup($this->Controller);
 		$key = $this->Controller->request->params['_Token']['key'];
-		$fields = '575ef54ca4fc8cab468d6d898e9acd3a9671c17e%3An%3A0%3A%7B%7D';
+		$fields = '3be63770e7953c6d2119f5377a9303372040f66f%3An%3A0%3A%7B%7D';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(

+ 18 - 18
lib/Cake/Test/Case/Utility/SecurityTest.php

@@ -114,10 +114,10 @@ class SecurityTest extends CakeTestCase {
 		$key = 'someKey';
 		$hash = 'someHash';
 
-		$this->assertSame(strlen(Security::hash($key, null, false)), 40);
-		$this->assertSame(strlen(Security::hash($key, 'sha1', false)), 40);
-		$this->assertSame(strlen(Security::hash($key, null, true)), 40);
-		$this->assertSame(strlen(Security::hash($key, 'sha1', true)), 40);
+		$this->assertSame(40, strlen(Security::hash($key, null, false)));
+		$this->assertSame(40, strlen(Security::hash($key, 'sha1', false)));
+		$this->assertSame(40, strlen(Security::hash($key, null, true)));
+		$this->assertSame(40, strlen(Security::hash($key, 'sha1', true)));
 
 		$result = Security::hash($key, null, $hash);
 		$this->assertSame($result, 'e38fcb877dccb6a94729a81523851c931a46efb1');
@@ -127,25 +127,25 @@ class SecurityTest extends CakeTestCase {
 
 		$hashType = 'sha1';
 		Security::setHash($hashType);
-		$this->assertSame(Security::$hashType, $hashType);
-		$this->assertSame(strlen(Security::hash($key, null, true)), 40);
-		$this->assertSame(strlen(Security::hash($key, null, false)), 40);
+		$this->assertSame($hashType, Security::$hashType);
+		$this->assertSame(40, strlen(Security::hash($key, null, true)));
+		$this->assertSame(40, strlen(Security::hash($key, null, false)));
 
-		$this->assertSame(strlen(Security::hash($key, 'md5', false)), 32);
-		$this->assertSame(strlen(Security::hash($key, 'md5', true)), 32);
+		$this->assertSame(32, strlen(Security::hash($key, 'md5', false)));
+		$this->assertSame(32, strlen(Security::hash($key, 'md5', true)));
 
 		$hashType = 'md5';
 		Security::setHash($hashType);
-		$this->assertSame(Security::$hashType, $hashType);
-		$this->assertSame(strlen(Security::hash($key, null, false)), 32);
-		$this->assertSame(strlen(Security::hash($key, null, true)), 32);
+		$this->assertSame($hashType, Security::$hashType);
+		$this->assertSame(32, strlen(Security::hash($key, null, false)));
+		$this->assertSame(32, strlen(Security::hash($key, null, true)));
 
 		if (!function_exists('hash') && !function_exists('mhash')) {
-			$this->assertSame(strlen(Security::hash($key, 'sha256', false)), 32);
-			$this->assertSame(strlen(Security::hash($key, 'sha256', true)), 32);
+			$this->assertSame(32, strlen(Security::hash($key, 'sha256', false)));
+			$this->assertSame(32, strlen(Security::hash($key, 'sha256', true)));
 		} else {
-			$this->assertSame(strlen(Security::hash($key, 'sha256', false)), 64);
-			$this->assertSame(strlen(Security::hash($key, 'sha256', true)), 64);
+			$this->assertSame(64, strlen(Security::hash($key, 'sha256', false)));
+			$this->assertSame(64, strlen(Security::hash($key, 'sha256', true)));
 		}
 
 		Security::setHash($_hashType);
@@ -167,8 +167,8 @@ class SecurityTest extends CakeTestCase {
 		$hashType = 'blowfish';
 		Security::setHash($hashType);
 
-		$this->assertSame(Security::$hashType, $hashType);
-		$this->assertSame(strlen(Security::hash($key, null, false)), 60);
+		$this->assertSame($hashType, Security::$hashType);
+		$this->assertSame(60, strlen(Security::hash($key, null, false)));
 
 		$password = $submittedPassword = $key;
 		$storedPassword = Security::hash($password);

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

@@ -1009,7 +1009,7 @@ class FormHelperTest extends CakeTestCase {
 
 		$result = $this->Form->secure($this->Form->fields);
 
-		$hash = 'c9118120e680a7201b543f562e5301006ccfcbe2%3AAddresses.0.id%7CAddresses.1.id';
+		$hash = 'a3b9b2ba1cb688838f92818a5970e17dd7943a78%3AAddresses.0.id%7CAddresses.1.id';
 
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
@@ -1074,7 +1074,7 @@ class FormHelperTest extends CakeTestCase {
 		$this->Form->input('Addresses.1.phone');
 
 		$result = $this->Form->secure($this->Form->fields);
-		$hash = '629b6536dcece48aa41a117045628ce602ccbbb2%3AAddresses.0.id%7CAddresses.1.id';
+		$hash = '5c9cadf9da008cc444d3960b481391a425a5d979%3AAddresses.0.id%7CAddresses.1.id';
 
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
@@ -1124,7 +1124,7 @@ class FormHelperTest extends CakeTestCase {
 
 		$result = $this->Form->secure($expected);
 
-		$hash = '2981c38990f3f6ba935e6561dc77277966fabd6d%3AAddresses.id';
+		$hash = '40289bd07811587887ff56585a8526ff9da59d7a%3AAddresses.id';
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
 			array('input' => array(
@@ -1247,7 +1247,7 @@ class FormHelperTest extends CakeTestCase {
 		);
 		$this->assertEquals($expected, $result);
 
-		$hash = 'bd7c4a654e5361f9a433a43f488ff9a1065d0aaf%3AUserForm.hidden%7CUserForm.stuff';
+		$hash = '6014b4e1c4f39eb62389712111dbe6435bec66cb%3AUserForm.hidden%7CUserForm.stuff';
 
 		$result = $this->Form->secure($this->Form->fields);
 		$expected = array(

+ 4 - 0
lib/Cake/Test/Case/View/Helper/TextHelperTest.php

@@ -266,6 +266,10 @@ class TextHelperTest extends CakeTestCase {
 				'Text with a url <a href="http://www.not--work.com">http://www.not--work.com</a> and more',
 			),
 			array(
+				'Text with a url http://www.sub_domain.domain.pl and more',
+				'Text with a url <a href="http://www.sub_domain.domain.pl">http://www.sub_domain.domain.pl</a> and more',
+			),
+			array(
 				'Text with a partial www.küchenschöhn-not-working.de URL',
 				'Text with a partial <a href="http://www.küchenschöhn-not-working.de">www.küchenschöhn-not-working.de</a> URL'
 			),

+ 16 - 1
lib/Cake/View/Helper/FormHelper.php

@@ -118,6 +118,14 @@ class FormHelper extends AppHelper {
 	protected $_domIdSuffixes = array();
 
 /**
+ * The action attribute value of the last created form.
+ * Used to make form/request specific hashes for SecurityComponent.
+ *
+ * @var string
+ */
+	protected $_lastAction = '';
+
+/**
  * Copies the validationErrors variable from the View object into this instance
  *
  * @param View $View The View this helper is being attached to.
@@ -458,6 +466,7 @@ class FormHelper extends AppHelper {
 			$this->setEntity($model, true);
 			$this->_introspectModel($model, 'fields');
 		}
+		$this->_lastAction = $action;
 		return $this->Html->useTag('form', $action, $htmlAttributes) . $append;
 	}
 
@@ -576,7 +585,13 @@ class FormHelper extends AppHelper {
 
 		$locked = implode(array_keys($locked), '|');
 		$unlocked = implode($unlockedFields, '|');
-		$fields = Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt'), 'sha1');
+		$hashParts = array(
+			$this->_lastAction,
+			serialize($fields),
+			$unlocked,
+			Configure::read('Security.salt')
+		);
+		$fields = Security::hash(implode('', $hashParts), 'sha1');
 
 		$tokenFields = array_merge($secureAttributes, array(
 			'value' => urlencode($fields . ':' . $locked),

+ 1 - 1
lib/Cake/View/Helper/TextHelper.php

@@ -104,7 +104,7 @@ class TextHelper extends AppHelper {
 		$this->_placeholders = array();
 		$options += array('escape' => true);
 
-		$pattern = '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[\p{L}0-9.\-:]+(?:[/?][^\s<]*)?)#ui';
+		$pattern = '#(?<!href="|src="|">)((?:https?|ftp|nntp)://[\p{L}0-9.\-_:]+(?:[/?][^\s<]*)?)#ui';
 		$text = preg_replace_callback(
 			$pattern,
 			array(&$this, '_insertPlaceHolder'),