Browse Source

Merge remote-tracking branch 'origin/2.6' into 3.0

Conflicts:
	lib/Cake/Console/ShellDispatcher.php
	lib/Cake/Controller/Component/SecurityComponent.php
	lib/Cake/Model/Model.php
	lib/Cake/Test/Case/View/Helper/FormHelperTest.php
	lib/Cake/View/Helper/FormHelper.php
	src/Utility/Inflector.php
	tests/TestCase/Controller/Component/SecurityComponentTest.php
mark_story 12 years ago
parent
commit
449f60798c

+ 1 - 1
src/Console/ShellDispatcher.php

@@ -52,7 +52,7 @@ class ShellDispatcher {
  */
 	public function __construct($args = [], $bootstrap = true) {
 		set_time_limit(0);
-		$this->args = $args;
+		$this->args = (array)$args;
 
 		if ($bootstrap) {
 			$this->_initEnvironment();

+ 7 - 3
src/Controller/Component/SecurityComponent.php

@@ -1,7 +1,5 @@
 <?php
 /**
- * Security Component
- *
  * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  *
@@ -333,7 +331,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);
 	}
 

+ 16 - 0
src/Utility/Inflector.php

@@ -191,9 +191,11 @@ class Inflector {
 		'Å' => 'A',
 		'Ǻ' => 'A',
 		'Ā' => 'A',
+		'Å' => 'A',
 		'Ă' => 'A',
 		'Ą' => 'A',
 		'Ǎ' => 'A',
+		'Ä' => 'Ae',
 		'à' => 'a',
 		'á' => 'a',
 		'â' => 'a',
@@ -230,6 +232,7 @@ class Inflector {
 		'Ė' => 'E',
 		'Ę' => 'E',
 		'Ě' => 'E',
+		'Ë' => 'E',
 		'è' => 'e',
 		'é' => 'e',
 		'ê' => 'e',
@@ -243,17 +246,21 @@ class Inflector {
 		'Ğ' => 'G',
 		'Ġ' => 'G',
 		'Ģ' => 'G',
+		'Ґ' => 'G',
 		'ĝ' => 'g',
 		'ğ' => 'g',
 		'ġ' => 'g',
 		'ģ' => 'g',
+		'ґ' => 'g',
 		'Ĥ' => 'H',
 		'Ħ' => 'H',
 		'ĥ' => 'h',
 		'ħ' => 'h',
+		'І' => 'I',
 		'Ì' => 'I',
 		'Í' => 'I',
 		'Î' => 'I',
+		'Ї' => 'Yi',
 		'Ï' => 'I',
 		'Ĩ' => 'I',
 		'Ī' => 'I',
@@ -261,10 +268,12 @@ class Inflector {
 		'Ǐ' => 'I',
 		'Į' => 'I',
 		'İ' => 'I',
+		'і' => 'i',
 		'ì' => 'i',
 		'í' => 'i',
 		'î' => 'i',
 		'ï' => 'i',
+		'ї' => 'yi',
 		'ĩ' => 'i',
 		'ī' => 'i',
 		'ĭ' => 'i',
@@ -305,6 +314,7 @@ class Inflector {
 		'Ơ' => 'O',
 		'Ø' => 'O',
 		'Ǿ' => 'O',
+		'Ö' => 'Oe',
 		'ò' => 'o',
 		'ó' => 'o',
 		'ô' => 'o',
@@ -328,6 +338,7 @@ class Inflector {
 		'Ş' => 'S',
 		'Ș' => 'S',
 		'Š' => 'S',
+		'ẞ' => 'SS',
 		'ś' => 's',
 		'ŝ' => 's',
 		'ş' => 's',
@@ -357,6 +368,7 @@ class Inflector {
 		'Ǘ' => 'U',
 		'Ǚ' => 'U',
 		'Ǜ' => 'U',
+		'Ü' => 'Ue',
 		'ù' => 'u',
 		'ú' => 'u',
 		'û' => 'u',
@@ -393,6 +405,10 @@ class Inflector {
 		'ij' => 'ij',
 		'Œ' => 'OE',
 		'ƒ' => 'f',
+		'Þ' => 'TH',
+		'þ' => 'th',
+		'Є' => 'Ye',
+		'є' => 'ye',
 	);
 
 /**

+ 17 - 1
src/View/Helper/FormHelper.php

@@ -163,6 +163,14 @@ class FormHelper extends Helper {
 	protected $_contextProviders;
 
 /**
+ * The action attribute value of the last created form.
+ * Used to make form/request specific hashes for SecurityComponent.
+ *
+ * @var string
+ */
+	protected $_lastAction = '';
+
+/**
  * Construct the widgets and binds the default context providers
  *
  * @param \Cake\View\View $View The View this helper is being attached to.
@@ -337,6 +345,8 @@ class FormHelper extends Helper {
 		if (!empty($append)) {
 			$append = $templater->format('hiddenblock', ['content' => $append]);
 		}
+		$this->_lastAction = $action;
+
 		$actionAttr = $templater->formatAttributes(['action' => $action, 'escape' => false]);
 		return $templater->format('formstart', [
 			'attrs' => $templater->formatAttributes($htmlAttributes) . $actionAttr
@@ -468,7 +478,13 @@ class FormHelper extends Helper {
 
 		$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
src/View/Helper/TextHelper.php

@@ -114,7 +114,7 @@ class TextHelper extends Helper {
 		$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'),

+ 23 - 19
tests/TestCase/Controller/Component/SecurityComponentTest.php

@@ -133,8 +133,12 @@ class SecurityComponentTest extends TestCase {
 	public function setUp() {
 		parent::setUp();
 
-		$request = new Request('posts/index');
+		$request = $this->getMock('Cake\Network\Request', ['here'], ['posts/index']);
 		$request->addParams(array('controller' => 'posts', 'action' => 'index'));
+		$request->expects($this->any())
+			->method('here')
+			->will($this->returnValue('/articles/index'));
+
 		$this->Controller = new SecurityTestController($request);
 		$this->Controller->constructClasses();
 		$this->Controller->Security = $this->Controller->TestSecurity;
@@ -321,7 +325,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
+		$fields = '68730b0747d4889ec2766f9117405f9635f5fd5e%3AModel.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -401,7 +405,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = 'f7d573650a295b94e0938d32b323fde775e5f32b%3A';
+		$fields = '8e26ef05379e5402c2c619f37ee91152333a0264%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -420,7 +424,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = '540ac9c60d323c22bafe997b72c0790f39a8bdef%3A';
+		$fields = 'a1c3724b7ba85e7022413611e30ba2c6181d5aba%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -441,7 +445,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = '69f493434187b867ea14b901fdf58b55d27c935d%3A';
+		$fields = 'b0914d06dfb04abf1fada53e16810e87d157950b%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -462,7 +466,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = 'c9118120e680a7201b543f562e5301006ccfcbe2%3AAddresses.0.id%7CAddresses.1.id';
+		$fields = 'b65c7463e44a61d8d2eaecce2c265b406c9c4742%3AAddresses.0.id%7CAddresses.1.id';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -491,7 +495,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
 
-		$fields = '422cde416475abc171568be690a98cad20e66079%3A';
+		$fields = '8d8da68ba03b3d6e7e145b948abfe26741422169%3A';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -515,7 +519,7 @@ class SecurityComponentTest extends TestCase {
 		$result = $this->Controller->Security->validatePost($this->Controller);
 		$this->assertTrue($result);
 
-		$fields = '19464422eafe977ee729c59222af07f983010c5f%3A';
+		$fields = 'eae2adda1628b771a30cc133342d16220c6520fe%3A';
 		$this->Controller->request->data = array(
 			'User.password' => 'bar', 'User.name' => 'foo', 'User.is_valid' => '1',
 			'Tag' => array('Tag' => array(1)),
@@ -536,7 +540,7 @@ class SecurityComponentTest extends TestCase {
 	public function testValidatePostCheckbox() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877%3AModel.valid';
+		$fields = '68730b0747d4889ec2766f9117405f9635f5fd5e%3AModel.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -547,7 +551,7 @@ class SecurityComponentTest extends TestCase {
 		$result = $this->Controller->Security->validatePost($this->Controller);
 		$this->assertTrue($result);
 
-		$fields = '874439ca69f89b4c4a5f50fb9c36ff56a28f5d42%3A';
+		$fields = 'f63e4a69b2edd31f064e8e602a04dd59307cfe9c%3A';
 
 		$this->Controller->request->data = array(
 			'Model' => array('username' => '', 'password' => '', 'valid' => '0'),
@@ -577,7 +581,7 @@ class SecurityComponentTest extends TestCase {
 	public function testValidatePostHidden() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = '51ccd8cb0997c7b3d4523ecde5a109318405ef8c%3AModel.hidden%7CModel.other_hidden';
+		$fields = '973a8939a68ac014cc6f7666cec9aa6268507350%3AModel.hidden%7CModel.other_hidden';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -600,7 +604,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->config('disabledFields', ['Model.username', 'Model.password']);
 		$this->Controller->Security->startup($event);
-		$fields = 'ef1082968c449397bcd849f963636864383278b1%3AModel.hidden';
+		$fields = '1c59acfbca98bd870c11fb544d545cbf23215880%3AModel.hidden';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -624,7 +628,7 @@ class SecurityComponentTest extends TestCase {
 		$this->Controller->Security->startup($event);
 		$unlocked = 'Model.username';
 		$fields = array('Model.hidden', 'Model.password');
-		$fields = urlencode(Security::hash(serialize($fields) . $unlocked . Configure::read('Security.salt')));
+		$fields = urlencode(Security::hash('/articles/index' . serialize($fields) . $unlocked . Configure::read('Security.salt')));
 
 		$this->Controller->request->data = array(
 			'Model' => array(
@@ -699,7 +703,7 @@ class SecurityComponentTest extends TestCase {
 	public function testValidateHiddenMultipleModel() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = 'a2d01072dc4660eea9d15007025f35a7a5b58e18%3AModel.valid%7CModel2.valid%7CModel3.valid';
+		$fields = '075ca6c26c38a09a78d871201df89faf52cbbeb8%3AModel.valid%7CModel2.valid%7CModel3.valid';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -720,7 +724,7 @@ class SecurityComponentTest extends TestCase {
 	public function testValidateHasManyModel() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = '51e3b55a6edd82020b3f29c9ae200e14bbeb7ee5%3AModel.0.hidden%7CModel.0.valid';
+		$fields = '24a753fb62ef7839389987b58e3f7108f564e529%3AModel.0.hidden%7CModel.0.valid';
 		$fields .= '%7CModel.1.hidden%7CModel.1.valid';
 		$unlocked = '';
 
@@ -750,7 +754,7 @@ class SecurityComponentTest extends TestCase {
 	public function testValidateHasManyRecordsPass() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = '7a203edb3d345bbf38fe0dccae960da8842e11d7%3AAddress.0.id%7CAddress.0.primary%7C';
+		$fields = '8f7d82bf7656cf068822d9bdab109ebed1be1825%3AAddress.0.id%7CAddress.0.primary%7C';
 		$fields .= 'Address.1.id%7CAddress.1.primary';
 		$unlocked = '';
 
@@ -794,7 +798,7 @@ class SecurityComponentTest extends TestCase {
 		$this->Controller->Security->startup($event);
 		$unlocked = '';
 		$hashFields = array('TaxonomyData');
-		$fields = urlencode(Security::hash(serialize($hashFields) . $unlocked . Configure::read('Security.salt')));
+		$fields = urlencode(Security::hash('/articles/index' . serialize($hashFields) . $unlocked . Configure::read('Security.salt')));
 
 		$this->Controller->request->data = array(
 			'TaxonomyData' => array(
@@ -860,7 +864,7 @@ class SecurityComponentTest extends TestCase {
 		$event = new Event('Controller.startup', $this->Controller);
 
 		$this->Controller->Security->startup($event);
-		$fields = '11842060341b9d0fc3808b90ba29fdea7054d6ad%3An%3A0%3A%7B%7D';
+		$fields = '9da2b3fa2b5b8ac0bfbc1bbce145e58059629125%3An%3A0%3A%7B%7D';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(
@@ -890,7 +894,7 @@ class SecurityComponentTest extends TestCase {
 	public function testRadio() {
 		$event = new Event('Controller.startup', $this->Controller);
 		$this->Controller->Security->startup($event);
-		$fields = '575ef54ca4fc8cab468d6d898e9acd3a9671c17e%3An%3A0%3A%7B%7D';
+		$fields = 'c2226a8879c3f4b513691295fc2519a29c44c8bb%3An%3A0%3A%7B%7D';
 		$unlocked = '';
 
 		$this->Controller->request->data = array(

+ 65 - 0
tests/TestCase/Utility/InflectorTest.php

@@ -28,6 +28,57 @@ use Cake\Utility\Inflector;
 class InflectorTest extends TestCase {
 
 /**
+ * A list of chars to test transliteration.
+ *
+ * @var array
+ */
+	public static $maps = array (
+		'de' => array ( /* German */
+			'Ä' => 'Ae', 'Ö' => 'Oe', 'Ü' => 'Ue', 'ä' => 'ae', 'ö' => 'oe', 'ü' => 'ue', 'ß' => 'ss',
+			'ẞ' => 'SS'
+		),
+		'latin' => array (
+			'À' => 'A', 'Á' => 'A', 'Â' => 'A', 'Ã' => 'A', 'Å' => 'A', 'Ă' => 'A', 'Æ' => 'AE', 'Ç' =>
+			'C', 'È' => 'E', 'É' => 'E', 'Ê' => 'E', 'Ë' => 'E', 'Ì' => 'I', 'Í' => 'I', 'Î' => 'I',
+			'Ï' => 'I', 'Ð' => 'D', 'Ñ' => 'N', 'Ò' => 'O', 'Ó' => 'O', 'Ô' => 'O', 'Õ' => 'O', 'Ő' => 'O', 'Ø' => 'O',
+			'Ș' => 'S', 'Ț' => 'T', 'Ù' => 'U', 'Ú' => 'U', 'Û' => 'U', 'Ű' => 'U',
+			'Ý' => 'Y', 'Þ' => 'TH', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a',
+			'å' => 'a', 'ă' => 'a', 'æ' => 'ae', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 'ë' => 'e',
+			'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 'ñ' => 'n', 'ò' => 'o', 'ó' =>
+			'o', 'ô' => 'o', 'õ' => 'o', 'ő' => 'o', 'ø' => 'o', 'ș' => 's', 'ț' => 't', 'ù' => 'u', 'ú' => 'u',
+			'û' => 'u', 'ű' => 'u', 'ý' => 'y', 'þ' => 'th', 'ÿ' => 'y'
+		),
+		'tr' => array ( /* Turkish */
+			'ş' => 's', 'Ş' => 'S', 'ı' => 'i', 'İ' => 'I', 'ç' => 'c', 'Ç' => 'C', 'ğ' => 'g', 'Ğ' => 'G'
+		),
+		'uk' => array ( /* Ukrainian */
+			'Є' => 'Ye', 'І' => 'I', 'Ї' => 'Yi', 'Ґ' => 'G', 'є' => 'ye', 'і' => 'i', 'ї' => 'yi', 'ґ' => 'g'
+		),
+		'cs' => array ( /* Czech */
+			'č' => 'c', 'ď' => 'd', 'ě' => 'e', 'ň' => 'n', 'ř' => 'r', 'š' => 's', 'ť' => 't', 'ů' => 'u',
+			'ž' => 'z', 'Č' => 'C', 'Ď' => 'D', 'Ě' => 'E', 'Ň' => 'N', 'Ř' => 'R', 'Š' => 'S', 'Ť' => 'T',
+			'Ů' => 'U', 'Ž' => 'Z'
+		),
+		'pl' => array ( /* Polish */
+			'ą' => 'a', 'ć' => 'c', 'ę' => 'e', 'ł' => 'l', 'ń' => 'n', 'ó' => 'o', 'ś' => 's', 'ź' => 'z',
+			'ż' => 'z', 'Ą' => 'A', 'Ć' => 'C', 'Ł' => 'L', 'Ń' => 'N', 'Ó' => 'O', 'Ś' => 'S',
+			'Ź' => 'Z', 'Ż' => 'Z'
+		),
+		'ro' => array ( /* Romanian */
+			'ă' => 'a', 'â' => 'a', 'î' => 'i', 'ș' => 's', 'ț' => 't', 'Ţ' => 'T', 'ţ' => 't'
+		),
+		'lv' => array ( /* Latvian */
+			'ā' => 'a', 'č' => 'c', 'ē' => 'e', 'ģ' => 'g', 'ī' => 'i', 'ķ' => 'k', 'ļ' => 'l', 'ņ' => 'n',
+			'š' => 's', 'ū' => 'u', 'ž' => 'z', 'Ā' => 'A', 'Č' => 'C', 'Ē' => 'E', 'Ģ' => 'G', 'Ī' => 'I',
+			'Ķ' => 'K', 'Ļ' => 'L', 'Ņ' => 'N', 'Š' => 'S', 'Ū' => 'U', 'Ž' => 'Z'
+		),
+		'lt' => array ( /* Lithuanian */
+			'ą' => 'a', 'č' => 'c', 'ę' => 'e', 'ė' => 'e', 'į' => 'i', 'š' => 's', 'ų' => 'u', 'ū' => 'u', 'ž' => 'z',
+			'Ą' => 'A', 'Č' => 'C', 'Ę' => 'E', 'Ė' => 'E', 'Į' => 'I', 'Š' => 'S', 'Ų' => 'U', 'Ū' => 'U', 'Ž' => 'Z'
+		)
+	);
+
+/**
  * tearDown
  *
  * @return void
@@ -257,6 +308,20 @@ class InflectorTest extends TestCase {
 	}
 
 /**
+ * Test slug() with a complete list of special chars.
+ *
+ * @return void
+ */
+	public function testInflectorSlugCharList() {
+		foreach (self::$maps as $language => $list) {
+			foreach ($list as $from => $to) {
+				$result = Inflector::slug($from);
+				$this->assertEquals($to, $result, $from . ' (' . $language . ') should be ' . $to . ' - but is ' . $result);
+			}
+		}
+	}
+
+/**
  * testInflectorSlugWithMap method
  *
  * @return void

+ 18 - 18
tests/TestCase/Utility/SecurityTest.php

@@ -93,10 +93,10 @@ class SecurityTest extends TestCase {
 		$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');
@@ -106,25 +106,25 @@ class SecurityTest extends TestCase {
 
 		$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);
@@ -145,8 +145,8 @@ class SecurityTest extends TestCase {
 		$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);

+ 3 - 3
tests/TestCase/View/Helper/FormHelperTest.php

@@ -1111,7 +1111,7 @@ class FormHelperTest extends TestCase {
 
 		$result = $this->Form->secure($this->Form->fields);
 
-		$hash = 'c9118120e680a7201b543f562e5301006ccfcbe2%3AAddresses.0.id%7CAddresses.1.id';
+		$hash = '8bd3911b07b507408b1a969b31ee90c47b7d387e%3AAddresses.0.id%7CAddresses.1.id';
 
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
@@ -1173,7 +1173,7 @@ class FormHelperTest extends TestCase {
 		$this->Form->text('Addresses.1.phone');
 
 		$result = $this->Form->secure($this->Form->fields);
-		$hash = '629b6536dcece48aa41a117045628ce602ccbbb2%3AAddresses.0.id%7CAddresses.1.id';
+		$hash = '4fb10b46873df4ddd4ef5c3a19944a2f29b38991%3AAddresses.0.id%7CAddresses.1.id';
 
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
@@ -1223,7 +1223,7 @@ class FormHelperTest extends TestCase {
 
 		$result = $this->Form->secure($expected, ['data-foo' => 'bar']);
 
-		$hash = '2981c38990f3f6ba935e6561dc77277966fabd6d%3AAddresses.id';
+		$hash = 'a303becbdd99cb42ca14a1cf7e63dfd48696a3c5%3AAddresses.id';
 		$expected = array(
 			'div' => array('style' => 'display:none;'),
 			array('input' => array(

+ 4 - 0
tests/TestCase/View/Helper/TextHelperTest.php

@@ -276,6 +276,10 @@ class TextHelperTest extends TestCase {
 				'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'
 			),