From b412b405f9ea5a3aff75879f9a165e21822d8a89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Thu, 23 Jul 2015 18:03:42 +0200 Subject: [PATCH 01/16] Make fixture import from table aware of records found --- lib/Cake/Console/Command/Task/FixtureTask.php | 11 +++++++++-- .../Case/Console/Command/Task/FixtureTaskTest.php | 8 +++++--- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Console/Command/Task/FixtureTask.php b/lib/Cake/Console/Command/Task/FixtureTask.php index b20c22b4b..05caa4629 100644 --- a/lib/Cake/Console/Command/Task/FixtureTask.php +++ b/lib/Cake/Console/Command/Task/FixtureTask.php @@ -414,19 +414,26 @@ class FixtureTask extends BakeTask { * @return array Array of records. */ protected function _getRecordsFromTable($modelName, $useTable = null) { + $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection)); if ($this->interactive) { $condition = null; $prompt = __d('cake_console', "Please provide a SQL fragment to use as conditions\nExample: WHERE 1=1"); while (!$condition) { $condition = $this->in($prompt, null, 'WHERE 1=1'); } + + $recordsFound = $modelObject->find('count', array( + 'conditions' => $condition, + 'recursive' => -1, + )); + $prompt = __d('cake_console', "How many records do you want to import?"); - $recordCount = $this->in($prompt, null, 10); + $recordCount = $this->in($prompt, null, ($recordsFound < 10 ) ? $recordsFound : 10); } else { $condition = 'WHERE 1=1'; $recordCount = (isset($this->params['count']) ? $this->params['count'] : 10); } - $modelObject = new Model(array('name' => $modelName, 'table' => $useTable, 'ds' => $this->connection)); + $records = $modelObject->find('all', array( 'conditions' => $condition, 'recursive' => -1, diff --git a/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php b/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php index dd62bd5f6..a649b7b75 100644 --- a/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php +++ b/lib/Cake/Test/Case/Console/Command/Task/FixtureTaskTest.php @@ -186,6 +186,9 @@ class FixtureTaskTest extends CakeTestCase { $this->Task->interactive = true; $this->Task->expects($this->at(0))->method('in') ->will($this->returnValue('WHERE 1=1')); + $this->Task->expects($this->at(1))->method('in') + ->with($this->anything(), $this->anything(), '3') + ->will($this->returnValue('2')); $this->Task->connection = 'test'; $this->Task->path = '/my/path/'; @@ -197,9 +200,8 @@ class FixtureTaskTest extends CakeTestCase { $this->assertContains('class ArticleFixture extends CakeTestFixture', $result); $this->assertContains('public $records', $result); $this->assertContains('public $import', $result); - $this->assertContains("'title' => 'First Article'", $result, 'Missing import data %s'); - $this->assertContains('Second Article', $result, 'Missing import data %s'); - $this->assertContains('Third Article', $result, 'Missing import data %s'); + $this->assertContains("'title' => 'First Article'", $result, 'Missing import data'); + $this->assertContains('Second Article', $result, 'Missing import data'); } /** From 418dcfd7f8a7767bc85bb4c51bde8cc20b3742ff Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 23 Jul 2015 21:42:26 -0400 Subject: [PATCH 02/16] Consistently remove plugin names in object collections. We were sometimes removing plugin prefixes (set, and some subclass methods). But many other methods were missing the pluginSplit() feature. This change makes all of the methods in ObjectCollection strip plugin prefixes, which increases consistency across the framework. Refs #7098 --- .../Case/Utility/ObjectCollectionTest.php | 29 +++++++++++++++++++ lib/Cake/Utility/ObjectCollection.php | 5 ++++ 2 files changed, 34 insertions(+) diff --git a/lib/Cake/Test/Case/Utility/ObjectCollectionTest.php b/lib/Cake/Test/Case/Utility/ObjectCollectionTest.php index c92c4923b..4d768d0d8 100644 --- a/lib/Cake/Test/Case/Utility/ObjectCollectionTest.php +++ b/lib/Cake/Test/Case/Utility/ObjectCollectionTest.php @@ -583,4 +583,33 @@ class ObjectCollectionTest extends CakeTestCase { $this->assertTrue($this->Objects->trigger($event)); } +/** + * test that the various methods ignore plugin prefixes + * + * plugin prefixes should be removed consistently as load() will + * remove them. Furthermore the __get() method does not support + * names with '.' in them. + * + * @return void + */ + public function testPluginPrefixes() { + $this->Objects->load('TestPlugin.First'); + $this->assertTrue($this->Objects->loaded('First')); + $this->assertTrue($this->Objects->loaded('TestPlugin.First')); + + $this->assertTrue($this->Objects->enabled('First')); + $this->assertTrue($this->Objects->enabled('TestPlugin.First')); + + $this->assertNull($this->Objects->disable('TestPlugin.First')); + $this->assertFalse($this->Objects->enabled('First')); + $this->assertFalse($this->Objects->enabled('TestPlugin.First')); + + $this->assertNull($this->Objects->enable('TestPlugin.First')); + $this->assertTrue($this->Objects->enabled('First')); + $this->assertTrue($this->Objects->enabled('TestPlugin.First')); + $this->Objects->setPriority('TestPlugin.First', 1000); + + $result = $this->Objects->prioritize(); + $this->assertEquals(1000, $result['First'][0]); + } } diff --git a/lib/Cake/Utility/ObjectCollection.php b/lib/Cake/Utility/ObjectCollection.php index 4bbb1a3ea..49e4ae9f8 100644 --- a/lib/Cake/Utility/ObjectCollection.php +++ b/lib/Cake/Utility/ObjectCollection.php @@ -176,6 +176,7 @@ abstract class ObjectCollection { public function enable($name, $prioritize = true) { $enabled = false; foreach ((array)$name as $object) { + list(, $object) = pluginSplit($object); if (isset($this->_loaded[$object]) && !isset($this->_enabled[$object])) { $priority = $this->defaultPriority; if (isset($this->_loaded[$object]->settings['priority'])) { @@ -219,6 +220,7 @@ abstract class ObjectCollection { $name = array($name => $priority); } foreach ($name as $object => $objectPriority) { + list(, $object) = pluginSplit($object); if (isset($this->_loaded[$object])) { if ($objectPriority === null) { $objectPriority = $this->defaultPriority; @@ -241,6 +243,7 @@ abstract class ObjectCollection { */ public function disable($name) { foreach ((array)$name as $object) { + list(, $object) = pluginSplit($object); unset($this->_enabled[$object]); } } @@ -255,6 +258,7 @@ abstract class ObjectCollection { */ public function enabled($name = null) { if (!empty($name)) { + list(, $name) = pluginSplit($name); return isset($this->_enabled[$name]); } return array_keys($this->_enabled); @@ -283,6 +287,7 @@ abstract class ObjectCollection { */ public function loaded($name = null) { if (!empty($name)) { + list(, $name) = pluginSplit($name); return isset($this->_loaded[$name]); } return array_keys($this->_loaded); From a239324a0d6370de86c998bcc1594d4c83474e0c Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Sun, 26 Jul 2015 15:35:03 +0200 Subject: [PATCH 03/16] use constant PHP_SAPI --- lib/Cake/Cache/Engine/XcacheEngine.php | 2 +- lib/Cake/Console/Templates/skel/webroot/index.php | 2 +- lib/Cake/Error/ErrorHandler.php | 2 +- lib/Cake/Test/Case/BasicsTest.php | 8 ++++---- lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php | 2 +- lib/Cake/Test/Case/Network/CakeResponseTest.php | 4 ++-- lib/Cake/Test/Case/Utility/DebuggerTest.php | 8 ++++---- lib/Cake/basics.php | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/lib/Cake/Cache/Engine/XcacheEngine.php b/lib/Cake/Cache/Engine/XcacheEngine.php index 9c1855605..97c851818 100644 --- a/lib/Cake/Cache/Engine/XcacheEngine.php +++ b/lib/Cake/Cache/Engine/XcacheEngine.php @@ -44,7 +44,7 @@ class XcacheEngine extends CacheEngine { * @return bool True if the engine has been successfully initialized, false if not */ public function init($settings = array()) { - if (php_sapi_name() !== 'cli') { + if (PHP_SAPI !== 'cli') { parent::init(array_merge(array( 'engine' => 'Xcache', 'prefix' => Inflector::slug(APP_DIR) . '_', diff --git a/lib/Cake/Console/Templates/skel/webroot/index.php b/lib/Cake/Console/Templates/skel/webroot/index.php index 4b67fafa4..e546e52ca 100644 --- a/lib/Cake/Console/Templates/skel/webroot/index.php +++ b/lib/Cake/Console/Templates/skel/webroot/index.php @@ -77,7 +77,7 @@ if (!defined('WWW_ROOT')) { } // for built-in server -if (php_sapi_name() === 'cli-server') { +if (PHP_SAPI === 'cli-server') { if ($_SERVER['REQUEST_URI'] !== '/' && file_exists(WWW_ROOT . $_SERVER['PHP_SELF'])) { return false; } diff --git a/lib/Cake/Error/ErrorHandler.php b/lib/Cake/Error/ErrorHandler.php index bde45f513..2cce57689 100644 --- a/lib/Cake/Error/ErrorHandler.php +++ b/lib/Cake/Error/ErrorHandler.php @@ -156,7 +156,7 @@ class ErrorHandler { $message .= "\nException Attributes: " . var_export($exception->getAttributes(), true); } } - if (php_sapi_name() !== 'cli') { + if (PHP_SAPI !== 'cli') { $request = Router::getRequest(); if ($request) { $message .= "\nRequest URL: " . $request->here(); diff --git a/lib/Cake/Test/Case/BasicsTest.php b/lib/Cake/Test/Case/BasicsTest.php index 25b9e3395..65821693e 100644 --- a/lib/Cake/Test/Case/BasicsTest.php +++ b/lib/Cake/Test/Case/BasicsTest.php @@ -952,7 +952,7 @@ EXPECTED; ########################### EXPECTED; - if (php_sapi_name() === 'cli') { + if (PHP_SAPI === 'cli') { $expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18); } else { $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 20); @@ -977,7 +977,7 @@ EXPECTED; ########################### EXPECTED; - if (php_sapi_name() === 'cli') { + if (PHP_SAPI === 'cli') { $expected = sprintf($expectedText, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 18); } else { $expected = sprintf($expectedHtml, str_replace(CAKE_CORE_INCLUDE_PATH, '', __FILE__), __LINE__ - 19); @@ -1043,7 +1043,7 @@ EXPECTED; * @return void */ public function testPr() { - $this->skipIf(php_sapi_name() === 'cli', 'Skipping web test in cli mode'); + $this->skipIf(PHP_SAPI === 'cli', 'Skipping web test in cli mode'); ob_start(); pr('this is a test'); $result = ob_get_clean(); @@ -1063,7 +1063,7 @@ EXPECTED; * @return void */ public function testPrCli() { - $this->skipIf(php_sapi_name() != 'cli', 'Skipping cli test in web mode'); + $this->skipIf(PHP_SAPI !== 'cli', 'Skipping cli test in web mode'); ob_start(); pr('this is a test'); $result = ob_get_clean(); diff --git a/lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php b/lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php index 91f019b62..9c56241c2 100644 --- a/lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php +++ b/lib/Cake/Test/Case/Cache/Engine/ApcEngineTest.php @@ -34,7 +34,7 @@ class ApcEngineTest extends CakeTestCase { parent::setUp(); $this->skipIf(!function_exists('apc_store'), 'Apc is not installed or configured properly.'); - if (php_sapi_name() === 'cli') { + if (PHP_SAPI === 'cli') { $this->skipIf(!ini_get('apc.enable_cli'), 'APC is not enabled for the CLI.'); } diff --git a/lib/Cake/Test/Case/Network/CakeResponseTest.php b/lib/Cake/Test/Case/Network/CakeResponseTest.php index 82a2f0419..41e2eba07 100644 --- a/lib/Cake/Test/Case/Network/CakeResponseTest.php +++ b/lib/Cake/Test/Case/Network/CakeResponseTest.php @@ -373,7 +373,7 @@ class CakeResponseTest extends CakeTestCase { * @return void */ public function testCompress() { - if (php_sapi_name() !== 'cli') { + if (PHP_SAPI !== 'cli') { $this->markTestSkipped('The response compression can only be tested in cli.'); } @@ -491,7 +491,7 @@ class CakeResponseTest extends CakeTestCase { if (!extension_loaded("zlib")) { $this->markTestSkipped('Skipping further tests for outputCompressed as zlib extension is not loaded'); } - if (php_sapi_name() !== 'cli') { + if (PHP_SAPI !== 'cli') { $this->markTestSkipped('Testing outputCompressed method with compression enabled done only in cli'); } diff --git a/lib/Cake/Test/Case/Utility/DebuggerTest.php b/lib/Cake/Test/Case/Utility/DebuggerTest.php index e967e7776..4179a7636 100644 --- a/lib/Cake/Test/Case/Utility/DebuggerTest.php +++ b/lib/Cake/Test/Case/Utility/DebuggerTest.php @@ -516,8 +516,8 @@ TEXT; Debugger::dump($var); $result = ob_get_clean(); - $open = php_sapi_name() === 'cli' ? "\n" : '
';
-		$close = php_sapi_name() === 'cli' ? "\n" : '
'; + $open = PHP_SAPI === 'cli' ? "\n" : '
';
+		$close = PHP_SAPI === 'cli' ? "\n" : '
'; $expected = << array( @@ -540,8 +540,8 @@ TEXT; Debugger::dump($var, 1); $result = ob_get_clean(); - $open = php_sapi_name() === 'cli' ? "\n" : '
';
-		$close = php_sapi_name() === 'cli' ? "\n" : '
'; + $open = PHP_SAPI === 'cli' ? "\n" : '
';
+		$close = PHP_SAPI === 'cli' ? "\n" : '
'; $expected = << array( diff --git a/lib/Cake/basics.php b/lib/Cake/basics.php index 3b8070942..51afffa18 100644 --- a/lib/Cake/basics.php +++ b/lib/Cake/basics.php @@ -100,7 +100,7 @@ HTML; TEXT; $template = $html; - if (php_sapi_name() === 'cli' || $showHtml === false) { + if (PHP_SAPI === 'cli' || $showHtml === false) { $template = $text; if ($showFrom) { $lineInfo = sprintf('%s (line %s)', $file, $line); @@ -275,7 +275,7 @@ if (!function_exists('pr')) { */ function pr($var) { if (Configure::read('debug') > 0) { - $template = php_sapi_name() !== 'cli' ? '
%s
' : "\n%s\n"; + $template = PHP_SAPI !== 'cli' ? '
%s
' : "\n%s\n"; printf($template, print_r($var, true)); } } From b16d627b36203c04cc54f3414d438cbd0abb63aa Mon Sep 17 00:00:00 2001 From: "t.gommers" Date: Mon, 27 Jul 2015 13:03:21 +0200 Subject: [PATCH 04/16] Disable SNI in HttpSocket --- lib/Cake/Network/Http/HttpSocket.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Network/Http/HttpSocket.php b/lib/Cake/Network/Http/HttpSocket.php index 44b514d9f..36c2985b5 100644 --- a/lib/Cake/Network/Http/HttpSocket.php +++ b/lib/Cake/Network/Http/HttpSocket.php @@ -719,7 +719,7 @@ class HttpSocket extends CakeSocket { unset($this->config[$key]); } if (version_compare(PHP_VERSION, '5.3.2', '>=')) { - if (empty($this->config['context']['ssl']['SNI_enabled'])) { + if (!isset($this->config['context']['ssl']['SNI_enabled'])) { $this->config['context']['ssl']['SNI_enabled'] = true; } if (version_compare(PHP_VERSION, '5.6.0', '>=')) { From 58ea40e32c3ea71766b94c7890042efbf10797ac Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 27 Jul 2015 22:12:25 -0400 Subject: [PATCH 05/16] Don't stop reading when only a '0' has been read. Make tests simpler by using onConsecutiveCalls() instead of trying to maintain mock method indexes. Refs #7121 --- lib/Cake/Network/Http/HttpSocket.php | 2 +- .../Test/Case/Network/Http/HttpSocketTest.php | 75 +++++++++++++++---- 2 files changed, 60 insertions(+), 17 deletions(-) diff --git a/lib/Cake/Network/Http/HttpSocket.php b/lib/Cake/Network/Http/HttpSocket.php index 36c2985b5..0fdf4a12d 100644 --- a/lib/Cake/Network/Http/HttpSocket.php +++ b/lib/Cake/Network/Http/HttpSocket.php @@ -378,7 +378,7 @@ class HttpSocket extends CakeSocket { $response = null; $inHeader = true; - while ($data = $this->read()) { + while (($data = $this->read()) !== false) { if ($this->_contentResource) { if ($inHeader) { $response .= $data; diff --git a/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php b/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php index de04f18ed..6ff788348 100644 --- a/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php +++ b/lib/Cake/Test/Case/Network/Http/HttpSocketTest.php @@ -307,6 +307,10 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testRequest() { + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->returnValue(false)); + $this->Socket->reset(); $response = $this->Socket->request(true); @@ -589,6 +593,10 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testGetWithSchemeAndPort() { + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->returnValue(false)); + $this->Socket->reset(); $request = array( 'uri' => array( @@ -609,6 +617,10 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testRequestWithStringQuery() { + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->returnValue(false)); + $this->Socket->reset(); $request = array( 'uri' => array( @@ -642,14 +654,18 @@ class HttpSocketTest extends CakeTestCase { */ public function testRequest2() { $this->Socket->reset(); + $request = array('uri' => 'htpp://www.cakephp.org/'); $number = mt_rand(0, 9999999); $this->Socket->expects($this->any())->method('connect')->will($this->returnValue(true)); $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

Hello, your lucky number is " . $number . "

"; $this->Socket->expects($this->at(0))->method('write') ->with("GET / HTTP/1.1\r\nHost: www.cakephp.org\r\nConnection: close\r\nUser-Agent: CakePHP\r\n\r\n"); - $this->Socket->expects($this->at(0))->method('read')->will($this->returnValue(false)); - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse, false)); + $response = (string)$this->Socket->request($request); $this->assertEquals($response, "

Hello, your lucky number is " . $number . "

"); } @@ -662,7 +678,11 @@ class HttpSocketTest extends CakeTestCase { public function testRequest3() { $request = array('uri' => 'htpp://www.cakephp.org/'); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a cookie test!

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse, false)); + $this->Socket->connected = true; $this->Socket->request($request); $result = $this->Socket->response['cookies']; @@ -711,9 +731,10 @@ class HttpSocketTest extends CakeTestCase { */ public function testRequestWithResource() { $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); - $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); - $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse, false, $serverResponse, false)); $this->Socket->connected = true; $f = fopen(TMP . 'download.txt', 'w'); @@ -744,8 +765,10 @@ class HttpSocketTest extends CakeTestCase { $this->Socket->config['request']['cookies'] = array(); $serverResponse = "HTTP/1.x 200 OK\r\nSet-Cookie: foo=bar\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; + $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); + $expected = array('www.cakephp.org' => array('foo' => array('value' => 'bar'))); $this->Socket->request('http://www.cakephp.org/'); $this->assertEquals($expected, $this->Socket->config['request']['cookies']); @@ -781,8 +804,9 @@ class HttpSocketTest extends CakeTestCase { public function testRequestCustomResponse() { $this->Socket->connected = true; $serverResponse = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

This is a test!

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); - $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse, false)); $this->Socket->responseClass = 'CustomResponse'; $response = $this->Socket->request('http://www.cakephp.org/'); @@ -817,6 +841,8 @@ class HttpSocketTest extends CakeTestCase { $this->Socket->expects($this->at(4)) ->method('read') ->will($this->returnValue($serverResponse2)); + $this->Socket->expects($this->any()) + ->method('read')->will($this->returnValue(false)); $response = $this->Socket->request($request); $this->assertEquals('

You have been redirected

', $response->body()); @@ -834,8 +860,10 @@ class HttpSocketTest extends CakeTestCase { ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

You have been redirected

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); - $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $response = $this->Socket->request($request); $this->assertEquals('

You have been redirected

', $response->body()); @@ -853,8 +881,10 @@ class HttpSocketTest extends CakeTestCase { ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 200 OK\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\n\r\n

You have been redirected

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); - $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $this->Socket->request($request); $this->assertEquals(1, $this->Socket->request['redirect']); @@ -872,8 +902,10 @@ class HttpSocketTest extends CakeTestCase { ); $serverResponse1 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/oneruri\r\n\r\n"; $serverResponse2 = "HTTP/1.x 302 Found\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\nContent-Type: text/html\r\nLocation: http://localhost/anotheruri\r\n\r\n"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse1)); - $this->Socket->expects($this->at(4))->method('read')->will($this->returnValue($serverResponse2)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse1, false, $serverResponse2, false)); $response = $this->Socket->request($request); $this->assertEquals(0, $this->Socket->request['redirect']); @@ -1113,6 +1145,9 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testAuth() { + $this->Socket->expects($this->any()) + ->method('read')->will($this->returnValue(false)); + $this->Socket->get('http://mark:secret@example.com/test'); $this->assertTrue(strpos($this->Socket->request['header'], 'Authorization: Basic bWFyazpzZWNyZXQ=') !== false); @@ -1154,6 +1189,9 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testConsecutiveGetResetsAuthCredentials() { + $this->Socket->expects($this->any()) + ->method('read')->will($this->returnValue(false)); + $this->Socket->get('http://mark:secret@example.com/test'); $this->assertEquals('mark', $this->Socket->request['uri']['user']); $this->assertEquals('secret', $this->Socket->request['uri']['pass']); @@ -1813,6 +1851,9 @@ class HttpSocketTest extends CakeTestCase { * @return void */ public function testConfigContext() { + $this->Socket->expects($this->any()) + ->method('read')->will($this->returnValue(false)); + $this->Socket->reset(); $this->Socket->request('http://example.com'); $this->assertTrue($this->Socket->config['context']['ssl']['verify_peer']); @@ -1869,8 +1910,10 @@ class HttpSocketTest extends CakeTestCase { public function testResponseStatusParsing($status, $code, $msg = '') { $this->Socket->connected = true; $serverResponse = $status . "\r\nDate: Mon, 16 Apr 2007 04:14:16 GMT\r\nServer: CakeHttp Server\r\n\r\n

This is a test!

"; - $this->Socket->expects($this->at(1))->method('read')->will($this->returnValue($serverResponse)); - $this->Socket->expects($this->at(2))->method('read')->will($this->returnValue(false)); + + $this->Socket->expects($this->any()) + ->method('read') + ->will($this->onConsecutiveCalls($serverResponse, false)); $response = $this->Socket->request('http://www.cakephp.org/'); $this->assertInstanceOf('HttpSocketResponse', $response); From 00d0a50dc27b54b0e59f7870f43d8352d25f909f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Tue, 28 Jul 2015 20:02:06 +0200 Subject: [PATCH 06/16] Add "Reporting a Security Issue" Backport of #7104 --- CONTRIBUTING.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5bb121179..c991e2460 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -63,6 +63,10 @@ Check the [cakephp-codesniffer](https://github.com/cakephp/cakephp-codesniffer) repository to setup the CakePHP standard. The [README](https://github.com/cakephp/cakephp-codesniffer/blob/master/README.md) contains installation info for the sniff and phpcs. +## Reporting a Security Issue + +If you've found a security related issue in CakePHP, please don't open an issue in GitHub. Instead contact us at security@cakephp.org. For more information on how we handle security issues, [see the CakePHP Security Issue Process](http://book.cakephp.org/2.0/en/contributing/tickets.html#reporting-security-issues). + # Additional Resources * [CakePHP coding standards](http://book.cakephp.org/2.0/en/contributing/cakephp-coding-conventions.html) From a3bb420a7b67fd046f14e9d6d9fe69b9a2bddb74 Mon Sep 17 00:00:00 2001 From: Luis Ramos Date: Tue, 28 Jul 2015 17:58:38 -0500 Subject: [PATCH 07/16] Set .htaccess indentation to 4 spaces --- .htaccess | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.htaccess b/.htaccess index f23dbaf66..f23967b59 100644 --- a/.htaccess +++ b/.htaccess @@ -1,5 +1,5 @@ - RewriteEngine on - RewriteRule ^$ app/webroot/ [L] - RewriteRule (.*) app/webroot/$1 [L] + RewriteEngine on + RewriteRule ^$ app/webroot/ [L] + RewriteRule (.*) app/webroot/$1 [L] \ No newline at end of file From 26ab829d5ad62e19c8de172a8dbfb0f1ad93da19 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 29 Jul 2015 22:01:27 -0400 Subject: [PATCH 08/16] Bootstrap Configure after the mb_* shims have been defined. By bootstrapping after the shims have been defined allows the shims to be used by Inflector which is often involved with bootstrapping. Refs #7135 --- lib/Cake/bootstrap.php | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/lib/Cake/bootstrap.php b/lib/Cake/bootstrap.php index 4ad77a21b..b17c9f68f 100644 --- a/lib/Cake/bootstrap.php +++ b/lib/Cake/bootstrap.php @@ -172,17 +172,6 @@ Configure::write('App.imageBaseUrl', IMAGES_URL); Configure::write('App.cssBaseUrl', CSS_URL); Configure::write('App.jsBaseUrl', JS_URL); -Configure::bootstrap(isset($boot) ? $boot : true); - -if (function_exists('mb_internal_encoding')) { - $encoding = Configure::read('App.encoding'); - if (!empty($encoding)) { - mb_internal_encoding($encoding); - } - if (!empty($encoding) && function_exists('mb_regex_encoding')) { - mb_regex_encoding($encoding); - } -} if (!function_exists('mb_stripos')) { @@ -438,3 +427,15 @@ if (!function_exists('mb_encode_mimeheader')) { } } + +Configure::bootstrap(isset($boot) ? $boot : true); + +if (function_exists('mb_internal_encoding')) { + $encoding = Configure::read('App.encoding'); + if (!empty($encoding)) { + mb_internal_encoding($encoding); + } + if (!empty($encoding) && function_exists('mb_regex_encoding')) { + mb_regex_encoding($encoding); + } +} From a73fc25657d50de729a62946166f286d0f27565d Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 30 Jul 2015 22:28:55 -0400 Subject: [PATCH 09/16] Fix incorrectly parsed mo file context. The context from mo files should be parsed correctly. Refs #7118 --- lib/Cake/I18n/I18n.php | 8 ++++++-- lib/Cake/Test/Case/I18n/I18nTest.php | 16 ++++++++++++++++ .../Locale/nld_mo/LC_MESSAGES/default.mo | Bin 0 -> 335 bytes 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 lib/Cake/Test/test_app/Locale/nld_mo/LC_MESSAGES/default.mo diff --git a/lib/Cake/I18n/I18n.php b/lib/Cake/I18n/I18n.php index 9f0d06fea..1ce5aae48 100644 --- a/lib/Cake/I18n/I18n.php +++ b/lib/Cake/I18n/I18n.php @@ -497,6 +497,9 @@ class I18n { $msgid = substr($data, $r["offs"], $r["len"]); unset($msgid_plural); + if (strpos($msgid, "\x04") !== false) { + list($context, $msgid) = explode("\x04", $msgid); + } if (strpos($msgid, "\000")) { list($msgid, $msgid_plural) = explode("\000", $msgid); } @@ -508,9 +511,10 @@ class I18n { } if ($msgid != '') { - $msgstr = array($context => $msgstr); + $translations[$msgid][$context] = $msgstr; + } else { + $translations[$msgid] = $msgstr; } - $translations[$msgid] = $msgstr; if (isset($msgid_plural)) { $translations[$msgid_plural] =& $translations[$msgid]; diff --git a/lib/Cake/Test/Case/I18n/I18nTest.php b/lib/Cake/Test/Case/I18n/I18nTest.php index 79657c461..faac0e069 100644 --- a/lib/Cake/Test/Case/I18n/I18nTest.php +++ b/lib/Cake/Test/Case/I18n/I18nTest.php @@ -2040,6 +2040,22 @@ class I18nTest extends CakeTestCase { $this->assertSame("saldo", __x('money', 'balance')); } +/** + * Test basic context support using mo files. + * + * @return void + */ + public function testContextMoFile() { + Configure::write('Config.language', 'nld_mo'); + + $this->assertSame("brief", __x('mail', 'letter')); + $this->assertSame("letter", __x('character', 'letter')); + $this->assertSame("bal", __x('spherical object', 'ball')); + $this->assertSame("danspartij", __x('social gathering', 'ball')); + $this->assertSame("balans", __('balance')); + $this->assertSame("saldo", __x('money', 'balance')); + } + /** * Singular method * diff --git a/lib/Cake/Test/test_app/Locale/nld_mo/LC_MESSAGES/default.mo b/lib/Cake/Test/test_app/Locale/nld_mo/LC_MESSAGES/default.mo new file mode 100644 index 0000000000000000000000000000000000000000..bb89fa6e9ae1b1f1848449c9ce986d282aa6232d GIT binary patch literal 335 zcmZY2O%4Gu7{>8ejE_i25D5v112}<|y(`$fQ$?jZ(l!zYv14iD8V+G+=M*-c*I=W` ze}2=i^xjGigi%F(G?NL&G3RXs|0k57GwPxXYNIQvqZ{g=$Hym>(JT;^VG9;v4>sTc z%DoXR!7;4C36yhFNGV%(N{g1%iao2SePVS4loM#f#{R8kPVbZN{g5fccDUrY(%!hG uY*-3gnJH{!=~}CpujY>i;q$`pq0}3_Ao=dJqri5a(VSh_vX5r{zVQOW)=BCB literal 0 HcmV?d00001 From 27c88a872bcd09ffce5e6f6745dcb03e2c2cfb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Sat, 1 Aug 2015 00:39:10 +0200 Subject: [PATCH 10/16] Use tabs and single spaces in all .htaccess files --- .htaccess | 6 +++--- app/.htaccess | 6 +++--- app/webroot/.htaccess | 8 ++++---- lib/Cake/Console/Templates/skel/.htaccess | 6 +++--- lib/Cake/Console/Templates/skel/webroot/.htaccess | 8 ++++---- 5 files changed, 17 insertions(+), 17 deletions(-) diff --git a/.htaccess b/.htaccess index f23967b59..2ac5e0e7a 100644 --- a/.htaccess +++ b/.htaccess @@ -1,5 +1,5 @@ - RewriteEngine on - RewriteRule ^$ app/webroot/ [L] - RewriteRule (.*) app/webroot/$1 [L] + RewriteEngine on + RewriteRule ^$ app/webroot/ [L] + RewriteRule (.*) app/webroot/$1 [L] \ No newline at end of file diff --git a/app/.htaccess b/app/.htaccess index fc3aac4b2..128e7871b 100644 --- a/app/.htaccess +++ b/app/.htaccess @@ -1,5 +1,5 @@ - RewriteEngine on - RewriteRule ^$ webroot/ [L] - RewriteRule (.*) webroot/$1 [L] + RewriteEngine on + RewriteRule ^$ webroot/ [L] + RewriteRule (.*) webroot/$1 [L] \ No newline at end of file diff --git a/app/webroot/.htaccess b/app/webroot/.htaccess index 1f19e4c06..1d499ba73 100644 --- a/app/webroot/.htaccess +++ b/app/webroot/.htaccess @@ -1,6 +1,6 @@ - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-d - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] diff --git a/lib/Cake/Console/Templates/skel/.htaccess b/lib/Cake/Console/Templates/skel/.htaccess index fc3aac4b2..128e7871b 100644 --- a/lib/Cake/Console/Templates/skel/.htaccess +++ b/lib/Cake/Console/Templates/skel/.htaccess @@ -1,5 +1,5 @@ - RewriteEngine on - RewriteRule ^$ webroot/ [L] - RewriteRule (.*) webroot/$1 [L] + RewriteEngine on + RewriteRule ^$ webroot/ [L] + RewriteRule (.*) webroot/$1 [L] \ No newline at end of file diff --git a/lib/Cake/Console/Templates/skel/webroot/.htaccess b/lib/Cake/Console/Templates/skel/webroot/.htaccess index 1f19e4c06..1d499ba73 100644 --- a/lib/Cake/Console/Templates/skel/webroot/.htaccess +++ b/lib/Cake/Console/Templates/skel/webroot/.htaccess @@ -1,6 +1,6 @@ - RewriteEngine On - RewriteCond %{REQUEST_FILENAME} !-d - RewriteCond %{REQUEST_FILENAME} !-f - RewriteRule ^ index.php [L] + RewriteEngine On + RewriteCond %{REQUEST_FILENAME} !-d + RewriteCond %{REQUEST_FILENAME} !-f + RewriteRule ^ index.php [L] From 3f15c8a1993c09db5abac9ff8c93e95e55e03c01 Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Wed, 5 Aug 2015 11:45:27 +0200 Subject: [PATCH 11/16] fix templates --- lib/Cake/Console/Templates/default/views/form.ctp | 2 +- lib/Cake/Console/Templates/default/views/view.ctp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Console/Templates/default/views/form.ctp b/lib/Cake/Console/Templates/default/views/form.ctp index b7dad3cee..4a21aabe3 100644 --- a/lib/Cake/Console/Templates/default/views/form.ctp +++ b/lib/Cake/Console/Templates/default/views/form.ctp @@ -44,7 +44,7 @@
    -
  • Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), array(), __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}'))); ?>"; ?>
  • +
  • Form->postLink(__('Delete'), array('action' => 'delete', \$this->Form->value('{$modelClass}.{$primaryKey}')), array('confirm' => __('Are you sure you want to delete # %s?', \$this->Form->value('{$modelClass}.{$primaryKey}')))); ?>"; ?>
  • Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?>"; ?>
  • Html->link(__('Edit " . $singularHumanName ."'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?> \n"; - echo "\t\t
  • Form->postLink(__('Delete " . $singularHumanName . "'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array(), __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>
  • \n"; + echo "\t\t
  • Form->postLink(__('Delete " . $singularHumanName . "'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}']))); ?>
  • \n"; echo "\t\t
  • Html->link(__('List " . $pluralHumanName . "'), array('action' => 'index')); ?>
  • \n"; echo "\t\t
  • Html->link(__('New " . $singularHumanName . "'), array('action' => 'add')); ?>
  • \n"; @@ -117,7 +117,7 @@ echo "\t\n"; echo "\t\t\t\tHtml->link(__('View'), array('controller' => '{$details['controller']}', 'action' => 'view', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; echo "\t\t\t\tHtml->link(__('Edit'), array('controller' => '{$details['controller']}', 'action' => 'edit', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; - echo "\t\t\t\tForm->postLink(__('Delete'), array('controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']), array(), __('Are you sure you want to delete # %s?', \${$otherSingularVar}['{$details['primaryKey']}'])); ?>\n"; + echo "\t\t\t\tForm->postLink(__('Delete'), array('controller' => '{$details['controller']}', 'action' => 'delete', \${$otherSingularVar}['{$details['primaryKey']}']), array('confirm' => __('Are you sure you want to delete # %s?', \${$otherSingularVar}['{$details['primaryKey']}']))); ?>\n"; echo "\t\t\t\n"; echo "\t\t\n"; From 9f20330d179cf759692537edb3e75fdd3adcbf7b Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 5 Aug 2015 22:12:13 -0400 Subject: [PATCH 12/16] Fix fatal error on null subject. Refs #7176 --- .../Controller/Component/EmailComponent.php | 3 ++- .../Component/EmailComponentTest.php | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Component/EmailComponent.php b/lib/Cake/Controller/Component/EmailComponent.php index 799baaca8..d89099f7e 100644 --- a/lib/Cake/Controller/Component/EmailComponent.php +++ b/lib/Cake/Controller/Component/EmailComponent.php @@ -309,7 +309,8 @@ class EmailComponent extends Component { $lib->readReceipt($this->_formatAddresses((array)$this->readReceipt)); } - $lib->subject($this->subject)->messageID($this->messageId); + $lib->subject($this->subject); + $lib->messageID($this->messageId); $lib->helpers($this->_controller->helpers); $headers = array('X-Mailer' => $this->xMailer); diff --git a/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php b/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php index 7be4282b3..aee72160d 100644 --- a/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/EmailComponentTest.php @@ -339,6 +339,32 @@ HTMLBLOC; $this->assertRegExp('/http\:\/\/example\.com/', $result); } +/** + * test send with null properties + * + * @return void + */ + public function testSendNullProperties() { + $this->Controller->EmailTest->to = 'test@example.com'; + $this->Controller->EmailTest->from = 'test@example.com'; + $this->Controller->EmailTest->subject = null; + $this->Controller->EmailTest->replyTo = null; + $this->Controller->EmailTest->messageId = null; + $this->Controller->EmailTest->template = null; + + $this->Controller->EmailTest->delivery = 'DebugComp'; + $this->assertTrue($this->Controller->EmailTest->send(null)); + $result = DebugCompTransport::$lastEmail; + + $this->assertRegExp('/To: test@example.com\n/', $result); + $this->assertRegExp('/Subject: \n/', $result); + $this->assertRegExp('/From: test@example.com\n/', $result); + $this->assertRegExp('/Date: ' . preg_quote(static::$sentDate) . '\n/', $result); + $this->assertRegExp('/X-Mailer: CakePHP Email Component\n/', $result); + $this->assertRegExp('/Content-Type: text\/plain; charset=UTF-8\n/', $result); + $this->assertRegExp('/Content-Transfer-Encoding: 8bitMessage:\n/', $result); + } + /** * testSendDebug method * From 056f24a77428ad35e23cab6840a72b7c25c4ccc0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 5 Aug 2015 23:05:30 -0400 Subject: [PATCH 13/16] Forbid direct prefix access with mixed casing. Changing the casing up should not allow prefix method access. --- lib/Cake/Controller/Controller.php | 4 ++-- .../Test/Case/Controller/ControllerTest.php | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index 8cd10fdf1..78381e90a 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -514,12 +514,12 @@ class Controller extends Object implements CakeEventListener { !$method->isPublic() || !in_array($method->name, $this->methods) ); - $prefixes = Router::prefixes(); + $prefixes = array_map('strtolower', Router::prefixes()); if (!$privateAction && !empty($prefixes)) { if (empty($request->params['prefix']) && strpos($request->params['action'], '_') > 0) { list($prefix) = explode('_', $request->params['action']); - $privateAction = in_array($prefix, $prefixes); + $privateAction = in_array(strtolower($prefix), $prefixes); } } return $privateAction; diff --git a/lib/Cake/Test/Case/Controller/ControllerTest.php b/lib/Cake/Test/Case/Controller/ControllerTest.php index 534825e37..f319bd167 100644 --- a/lib/Cake/Test/Case/Controller/ControllerTest.php +++ b/lib/Cake/Test/Case/Controller/ControllerTest.php @@ -1447,6 +1447,25 @@ class ControllerTest extends CakeTestCase { $Controller->invokeAction($url); } +/** + * test invoking controller methods. + * + * @expectedException PrivateActionException + * @expectedExceptionMessage Private Action TestController::Admin_add() is not directly accessible. + * @return void + */ + public function testInvokeActionPrefixProtectionCasing() { + Router::reload(); + Router::connect('/admin/:controller/:action/*', array('prefix' => 'admin')); + + $url = new CakeRequest('test/Admin_add/'); + $url->addParams(array('controller' => 'test_controller', 'action' => 'Admin_add')); + $response = $this->getMock('CakeResponse'); + + $Controller = new TestController($url, $response); + $Controller->invokeAction($url); + } + /** * test invoking controller methods. * From b7c9ac913d05f7530784af8fb34166d33cb10af4 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 6 Aug 2015 21:32:17 -0400 Subject: [PATCH 14/16] Backport fixes for comparison() and range() to 2.x These fixes were released as a security update for 3.x, they also belong in 2.x --- lib/Cake/Test/Case/Utility/ValidationTest.php | 35 +++++++++++++++++++ lib/Cake/Utility/Validation.php | 7 ++++ 2 files changed, 42 insertions(+) diff --git a/lib/Cake/Test/Case/Utility/ValidationTest.php b/lib/Cake/Test/Case/Utility/ValidationTest.php index a8f0e957f..f501e4f6b 100644 --- a/lib/Cake/Test/Case/Utility/ValidationTest.php +++ b/lib/Cake/Test/Case/Utility/ValidationTest.php @@ -930,6 +930,25 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::comparison(7, '==', 6)); $this->assertFalse(Validation::comparison(7, 'not equal', 7)); $this->assertFalse(Validation::comparison(7, '!=', 7)); + + $this->assertTrue(Validation::comparison('6.5', '!=', 6)); + $this->assertTrue(Validation::comparison('6.5', '<', 7)); + } + +/** + * Test comparison casting values before comparisons. + * + * @return void + */ + public function testComparisonTypeChecks() { + $this->assertFalse(Validation::comparison('\x028', '>=', 1), 'hexish encoding fails'); + $this->assertFalse(Validation::comparison('0b010', '>=', 1), 'binary string data fails'); + $this->assertFalse(Validation::comparison('0x01', '>=', 1), 'hex string data fails'); + $this->assertFalse(Validation::comparison('0x1', '>=', 1), 'hex string data fails'); + + $this->assertFalse(Validation::comparison('\x028', '>=', 1.5), 'hexish encoding fails'); + $this->assertFalse(Validation::comparison('0b010', '>=', 1.5), 'binary string data fails'); + $this->assertFalse(Validation::comparison('0x02', '>=', 1.5), 'hex string data fails'); } /** @@ -2004,6 +2023,22 @@ class ValidationTest extends CakeTestCase { $this->assertFalse(Validation::range('word')); } +/** + * Test range type checks + * + * @return void + */ + public function testRangeTypeChecks() { + $this->assertFalse(Validation::range('\x028', 1, 5), 'hexish encoding fails'); + $this->assertFalse(Validation::range('0b010', 1, 5), 'binary string data fails'); + $this->assertFalse(Validation::range('0x01', 1, 5), 'hex string data fails'); + $this->assertFalse(Validation::range('0x1', 1, 5), 'hex string data fails'); + + $this->assertFalse(Validation::range('\x028', 1, 5), 'hexish encoding fails'); + $this->assertFalse(Validation::range('0b010', 1, 5), 'binary string data fails'); + $this->assertFalse(Validation::range('0x02', 1, 5), 'hex string data fails'); + } + /** * testExtension method * diff --git a/lib/Cake/Utility/Validation.php b/lib/Cake/Utility/Validation.php index 6cdd745b0..40449ab0d 100644 --- a/lib/Cake/Utility/Validation.php +++ b/lib/Cake/Utility/Validation.php @@ -242,6 +242,10 @@ class Validation { if (is_array($check1)) { extract($check1, EXTR_OVERWRITE); } + + if ((float)$check1 != $check1) { + return false; + } $operator = str_replace(array(' ', "\t", "\n", "\r", "\0", "\x0B"), '', strtolower($operator)); switch ($operator) { @@ -757,6 +761,9 @@ class Validation { if (!is_numeric($check)) { return false; } + if ((float)$check != $check) { + return false; + } if (isset($lower) && isset($upper)) { return ($check > $lower && $check < $upper); } From f959b7601323065e74c6ec5dd0b63049ae939dac Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 6 Aug 2015 21:43:53 -0400 Subject: [PATCH 15/16] Update version number to 2.7.2 --- lib/Cake/VERSION.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/VERSION.txt b/lib/Cake/VERSION.txt index ea11fc97e..2f1076993 100644 --- a/lib/Cake/VERSION.txt +++ b/lib/Cake/VERSION.txt @@ -17,4 +17,4 @@ // @license http://www.opensource.org/licenses/mit-license.php MIT License // +--------------------------------------------------------------------------------------------+ // //////////////////////////////////////////////////////////////////////////////////////////////////// -2.7.1 +2.7.2 From a7b5f8c3af2398da3f6d0c35b4ac5bf77331468b Mon Sep 17 00:00:00 2001 From: paolo Date: Thu, 6 Aug 2015 16:05:16 +0200 Subject: [PATCH 16/16] DboSource now check the actual status of connection by executing a dumb query on DB This change makes it possible for developer to build reconnection logic on MySQL connections which frequently time out in long running CLI processes. Cherry picked onto 2.7 from #7190. --- lib/Cake/Model/Datasource/DboSource.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index 927a6e369..a41e88cef 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -857,6 +857,12 @@ class DboSource extends DataSource { * @return bool True if the database is connected, else false */ public function isConnected() { + try { + $connected = $this->_connection->query('SELECT 1'); + } catch (Exception $e) { + $connected = false; + } + $this->connected = ! empty($connected); return $this->connected; }