From 66f3a7e487a624d6d108ea82cd1f65d21e465113 Mon Sep 17 00:00:00 2001 From: Seth Tanner Date: Thu, 14 Jan 2016 09:37:06 -0800 Subject: [PATCH 01/38] refs issue #7929 add support for Postgres native uuid datatype --- lib/Cake/Model/Datasource/Database/Postgres.php | 3 ++- lib/Cake/Model/Datasource/DboSource.php | 5 +++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 033527ae0..9d03bec7c 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -68,7 +68,8 @@ class Postgres extends DboSource { 'binary' => array('name' => 'bytea'), 'boolean' => array('name' => 'boolean'), 'number' => array('name' => 'numeric'), - 'inet' => array('name' => 'inet') + 'inet' => array('name' => 'inet'), + 'uuid' => array('name' => 'uuid') ); /** diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index dc1802d49..f8e827a20 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -345,6 +345,11 @@ class DboSource extends DataSource { case 'boolean': return $this->_connection->quote($this->boolean($data, true), PDO::PARAM_BOOL); case 'string': + if ($data === '') { + return 'NULL'; + } else { + return $this->_connection->quote($data, PDO::PARAM_STR); + } case 'text': return $this->_connection->quote($data, PDO::PARAM_STR); default: From 47bf98cae4887fa0edb120eace4cb8dbdcb8b2f9 Mon Sep 17 00:00:00 2001 From: Seth Tanner Date: Fri, 15 Jan 2016 11:43:01 -0800 Subject: [PATCH 02/38] refs # 7929 refactor uuid support to not break Backward Compatibility --- lib/Cake/Model/Datasource/Database/Postgres.php | 10 ++++++++-- lib/Cake/Model/Datasource/DboSource.php | 3 ++- lib/Cake/Model/Model.php | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 9d03bec7c..52e02cd8e 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -217,6 +217,7 @@ class Postgres extends DboSource { $length = null; $type = 'text'; } elseif ($c->type === 'uuid') { + $type = 'uuid'; $length = 36; } else { $length = (int)$c->oct_length; @@ -242,7 +243,10 @@ class Postgres extends DboSource { if ($model instanceof Model) { if ($c->name === $model->primaryKey) { $fields[$c->name]['key'] = 'primary'; - if ($fields[$c->name]['type'] !== 'string') { + if ( + $fields[$c->name]['type'] !== 'string' && + $fields[$c->name]['type'] !== 'uuid' + ) { $fields[$c->name]['length'] = 11; } } @@ -699,8 +703,10 @@ class Postgres extends DboSource { return 'biginteger'; case (strpos($col, 'int') !== false && $col !== 'interval'): return 'integer'; - case (strpos($col, 'char') !== false || $col === 'uuid'): + case (strpos($col, 'char') !== false): return 'string'; + case (strpos($col, 'uuid') !== false): + return 'uuid'; case (strpos($col, 'text') !== false): return 'text'; case (strpos($col, 'bytea') !== false): diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index f8e827a20..fd32882ea 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -344,12 +344,13 @@ class DboSource extends DataSource { return $this->_connection->quote($data, PDO::PARAM_LOB); case 'boolean': return $this->_connection->quote($this->boolean($data, true), PDO::PARAM_BOOL); - case 'string': + case 'uuid': if ($data === '') { return 'NULL'; } else { return $this->_connection->quote($data, PDO::PARAM_STR); } + case 'string': case 'text': return $this->_connection->quote($data, PDO::PARAM_STR); default: diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 4b4b83d47..bab919312 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -1982,7 +1982,7 @@ class Model extends Object implements CakeEventListener { */ protected function _isUUIDField($field) { $field = $this->schema($field); - return $field['length'] == 36 && in_array($field['type'], array('string', 'binary')); + return $field['length'] == 36 && in_array($field['type'], array('string', 'binary', 'uuid')); } /** From e75858d3428a32c76ccd6a5ebc9f13db496592dc Mon Sep 17 00:00:00 2001 From: Seth Tanner Date: Fri, 15 Jan 2016 12:15:59 -0800 Subject: [PATCH 03/38] refs #7929 update uuid test --- lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php index 20f96cd5c..e759c0f99 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php @@ -1150,7 +1150,7 @@ class PostgresTest extends CakeTestCase { $data = $db->describe('test_uuid_describe'); $expected = array( - 'type' => 'string', + 'type' => 'uuid', 'null' => false, 'default' => null, 'length' => 36, From 296f698db304e25ac3092750f0860b3a180ae468 Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 21 Jan 2016 19:01:48 +0000 Subject: [PATCH 04/38] Added test cases covering native uuid field usage for Postgres class --- .../Model/Datasource/Database/Postgres.php | 13 +++ lib/Cake/Model/Datasource/DboSource.php | 6 -- .../Datasource/Database/PostgresTest.php | 18 +++- lib/Cake/Test/Case/Model/ModelTestBase.php | 4 +- lib/Cake/Test/Case/Model/ModelWriteTest.php | 82 ++++++++++++++++ lib/Cake/Test/Case/Model/models.php | 93 +++++++++++++++++++ lib/Cake/Test/Fixture/UuidNativeFixture.php | 50 ++++++++++ .../Test/Fixture/UuidNativeTagFixture.php | 45 +++++++++ .../Test/Fixture/UuidNativeTreeFixture.php | 39 ++++++++ .../Test/Fixture/UuidnativeitemFixture.php | 50 ++++++++++ ...dnativeitemsUuidnativeportfolioFixture.php | 48 ++++++++++ ...emsUuidnativeportfolioNumericidFixture.php | 48 ++++++++++ .../Fixture/UuidnativeportfolioFixture.php | 45 +++++++++ 13 files changed, 532 insertions(+), 9 deletions(-) create mode 100644 lib/Cake/Test/Fixture/UuidNativeFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidNativeTagFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidNativeTreeFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidnativeitemFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioNumericidFixture.php create mode 100644 lib/Cake/Test/Fixture/UuidnativeportfolioFixture.php diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 52e02cd8e..993d7dd5a 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -929,6 +929,19 @@ class Postgres extends DboSource { return $join; } +/** + * {@inheritDoc} + */ + public function value($data, $column = null, $null = true) { + $value = parent::value($data, $column, $null); + if ($column == 'uuid' && is_scalar($data)) { + if ($data === '') { + return 'NULL'; + } + } + return $value; + } + /** * Overrides DboSource::renderStatement to handle schema generation with Postgres-style indexes * diff --git a/lib/Cake/Model/Datasource/DboSource.php b/lib/Cake/Model/Datasource/DboSource.php index fd32882ea..dc1802d49 100644 --- a/lib/Cake/Model/Datasource/DboSource.php +++ b/lib/Cake/Model/Datasource/DboSource.php @@ -344,12 +344,6 @@ class DboSource extends DataSource { return $this->_connection->quote($data, PDO::PARAM_LOB); case 'boolean': return $this->_connection->quote($this->boolean($data, true), PDO::PARAM_BOOL); - case 'uuid': - if ($data === '') { - return 'NULL'; - } else { - return $this->_connection->quote($data, PDO::PARAM_STR); - } case 'string': case 'text': return $this->_connection->quote($data, PDO::PARAM_STR); diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php index e759c0f99..9158efcd2 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/PostgresTest.php @@ -132,7 +132,8 @@ class PostgresTestModel extends Model { 'comments' => array('type' => 'text', 'null' => '1', 'default' => '', 'length' => ''), 'last_login' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => ''), 'created' => array('type' => 'date', 'null' => '1', 'default' => '', 'length' => ''), - 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null) + 'updated' => array('type' => 'datetime', 'null' => '1', 'default' => '', 'length' => null), + 'some_uuid' => array('type' => 'uuid', 'null' => '1', 'default' => null), ); } @@ -257,7 +258,8 @@ class PostgresTest extends CakeTestCase { '"PostgresTestModel"."comments" AS "PostgresTestModel__comments"', '"PostgresTestModel"."last_login" AS "PostgresTestModel__last_login"', '"PostgresTestModel"."created" AS "PostgresTestModel__created"', - '"PostgresTestModel"."updated" AS "PostgresTestModel__updated"' + '"PostgresTestModel"."updated" AS "PostgresTestModel__updated"', + '"PostgresTestModel"."some_uuid" AS "PostgresTestModel__some_uuid"' ); $result = $this->Dbo->fields($this->model); @@ -300,6 +302,7 @@ class PostgresTest extends CakeTestCase { $this->assertEquals('decimal', $this->Dbo2->column('numeric')); $this->assertEquals('float', $this->Dbo2->column('float')); $this->assertEquals('float', $this->Dbo2->column('double precision')); + $this->assertEquals('uuid', $this->Dbo2->column('uuid')); $result = $this->Dbo2->column('bigint'); $expected = 'biginteger'; @@ -336,6 +339,8 @@ class PostgresTest extends CakeTestCase { $this->assertEquals("'TRUE'", $this->Dbo->value('1', 'boolean')); $this->assertEquals("NULL", $this->Dbo->value(null, 'boolean')); $this->assertEquals("NULL", $this->Dbo->value(array())); + $this->assertEquals("'550e8400-e29b-41d4-a716-446655440000'", $this->Dbo->value('550e8400-e29b-41d4-a716-446655440000', 'uuid')); + $this->assertEquals("NULL", $this->Dbo->value(null, 'uuid')); } /** @@ -1204,4 +1209,13 @@ class PostgresTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * Test build column working for new uuid types + */ + public function testBuildColumnUuid() { + $column = array('name' => 'col1', 'type' => 'uuid'); + $result = $this->Dbo2->buildColumn($column); + + $this->assertEquals('"col1" uuid', $result); + } } diff --git a/lib/Cake/Test/Case/Model/ModelTestBase.php b/lib/Cake/Test/Case/Model/ModelTestBase.php index 84b7050a7..ce2c16a7b 100644 --- a/lib/Cake/Test/Case/Model/ModelTestBase.php +++ b/lib/Cake/Test/Case/Model/ModelTestBase.php @@ -59,7 +59,7 @@ abstract class BaseModelTest extends CakeTestCase { 'core.feature_set', 'core.exterior_type_category', 'core.document', 'core.device', 'core.document_directory', 'core.primary_model', 'core.secondary_model', 'core.something', 'core.something_else', 'core.join_thing', 'core.join_a', 'core.join_b', 'core.join_c', - 'core.join_a_b', 'core.join_a_c', 'core.uuid', 'core.data_test', 'core.posts_tag', + 'core.join_a_b', 'core.join_a_c', 'core.uuid', 'core.uuid_native', 'core.data_test', 'core.posts_tag', 'core.the_paper_monkies', 'core.person', 'core.underscore_field', 'core.node', 'core.dependency', 'core.story', 'core.stories_tag', 'core.cd', 'core.book', 'core.basket', 'core.overall_favorite', 'core.account', 'core.content', 'core.content_account', @@ -71,6 +71,8 @@ abstract class BaseModelTest extends CakeTestCase { 'core.fruits_uuid_tag', 'core.uuid_tag', 'core.product_update_all', 'core.group_update_all', 'core.player', 'core.guild', 'core.guilds_player', 'core.armor', 'core.armors_player', 'core.bidding', 'core.bidding_message', 'core.site', 'core.domain', 'core.domains_site', + 'core.uuidnativeitem', 'core.uuidnativeportfolio', 'core.uuidnativeitems_uuidnativeportfolio', + 'core.uuidnativeitems_uuidnativeportfolio_numericid', ); /** diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 70ca570e9..bf9a2c67d 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -270,6 +270,28 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(36, strlen($result['Uuid']['id'])); } + +/** + * testAutoSaveUuidNative method + * + * @return void + */ + public function testAutoSaveUuidNative() { + $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); + + $this->loadFixtures('UuidNative'); + $TestModel = new UuidNative(); + + $TestModel->save(array('title' => 'Test record')); + $result = $TestModel->findByTitle('Test record'); + $this->assertEquals( + array('id', 'title', 'count', 'created', 'updated'), + array_keys($result['UuidNative']) + ); + $this->assertEquals(36, strlen($result['UuidNative']['id'])); + } + + /** * Ensure that if the id key is null but present the save doesn't fail (with an * x sql error: "Column id specified twice") @@ -292,6 +314,27 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(36, strlen($result['Uuid']['id'])); } +/** + * Ensure that if the id key is null but present the save doesn't fail (with an + * x sql error: "Column id specified twice") + * + * @return void + */ + public function testSaveUuidNullNative() { + $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); + + $this->loadFixtures('UuidNative'); + $TestModel = new UuidNative(); + + $TestModel->save(array('title' => 'Test record', 'id' => null)); + $result = $TestModel->findByTitle('Test record'); + $this->assertEquals( + array('id', 'title', 'count', 'created', 'updated'), + array_keys($result['UuidNative']) + ); + $this->assertEquals(36, strlen($result['UuidNative']['id'])); + } + /** * testZeroDefaultFieldValue method * @@ -2938,6 +2981,26 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(36, strlen($result['Uuiditem'][0]['UuiditemsUuidportfolio']['id'])); } +/** + * testHabtmUuidWithUuidId method + * + * @return void + */ + public function testHabtmUuidWithUuidIdNative() { + $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); + $this->loadFixtures('Uuidnativeportfolio', 'Uuidnativeitem', 'UuidnativeitemsUuidnativeportfolio', 'UuidnativeitemsUuidnativeportfolioNumericid'); + $TestModel = new Uuidnativeportfolio(); + + $data = array('Uuidnativeportfolio' => array('name' => 'Portfolio 3')); + $data['Uuidnativeitem']['Uuidnativeitem'] = array('483798c8-c7cc-430e-8cf9-4fcc40cf8569'); + $TestModel->create($data); + $TestModel->save(); + $id = $TestModel->id; + $result = $TestModel->read(null, $id); + $this->assertEquals(1, count($result['Uuidnativeitem'])); + $this->assertEquals(36, strlen($result['Uuidnativeitem'][0]['UuidnativeitemsUuidnativeportfolio']['id'])); + } + /** * test HABTM saving when join table has no primary key and only 2 columns. * @@ -3007,6 +3070,25 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(1, count($result['Uuidportfolio'])); } +/** + * testHabtmUuidWithNumericId method + * + * @return void + */ + public function testHabtmUuidWithNumericIdNative() { + $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); + $this->loadFixtures('Uuidnativeportfolio', 'Uuidnativeitem', 'UuidnativeitemsUuidnativeportfolioNumericid'); + $TestModel = new Uuidnativeitem(); + + $data = array('Uuidnativeitem' => array('name' => 'Item 7', 'published' => 0)); + $data['Uuidnativeportfolio']['Uuidnativeportfolio'] = array('480af662-eb8c-47d3-886b-230540cf8569'); + $TestModel->create($data); + $TestModel->save(); + $id = $TestModel->id; + $result = $TestModel->read(null, $id); + $this->assertEquals(1, count($result['Uuidnativeportfolio'])); + } + /** * testSaveMultipleHabtm method * diff --git a/lib/Cake/Test/Case/Model/models.php b/lib/Cake/Test/Case/Model/models.php index ea8d36426..f49299444 100644 --- a/lib/Cake/Test/Case/Model/models.php +++ b/lib/Cake/Test/Case/Model/models.php @@ -2120,6 +2120,21 @@ class Uuid extends CakeTestModel { public $name = 'Uuid'; } +/** + * UuidNative class + * + * @package Cake.Test.Case.Model + */ +class UuidNative extends CakeTestModel { + +/** + * name property + * + * @var string + */ + public $name = 'UuidNative'; +} + /** * DataTest class * @@ -3055,6 +3070,84 @@ class UuiditemsUuidportfolioNumericid extends CakeTestModel { public $name = 'UuiditemsUuidportfolioNumericid'; } +/** + * Uuidnativeportfolio class + * + * @package Cake.Test.Case.Model + */ +class Uuidnativeportfolio extends CakeTestModel { + +/** + * name property + * + * @var string + */ + public $name = 'Uuidnativeportfolio'; + +/** + * hasAndBelongsToMany property + * + * @var array + */ + public $hasAndBelongsToMany = array('Uuidnativeitem'); +} + +/** + * Uuidnativeitem class + * + * @package Cake.Test.Case.Model + */ +class Uuidnativeitem extends CakeTestModel { + +/** + * name property + * + * @var string + */ + public $name = 'Uuidnativeitem'; + +/** + * hasAndBelongsToMany property + * + * @var array + */ + public $hasAndBelongsToMany = array( + 'Uuidnativeportfolio' => array( + 'with' => 'UuidnativeitemsUuidnativeportfolioNumericid' + )); + +} + +/** + * UuidnativeitemsUuidnativeportfolio class + * + * @package Cake.Test.Case.Model + */ +class UuidnativeitemsUuidnativeportfolio extends CakeTestModel { + +/** + * name property + * + * @var string + */ + public $name = 'UuidnativeitemsUuidnativeportfolio'; +} + +/** + * UuidnativeitemsPortfolioNumericid class + * + * @package Cake.Test.Case.Model + */ +class UuidnativeitemsUuidnativeportfolioNumericid extends CakeTestModel { + +/** + * name property + * + * @var string + */ + public $name = 'UuidnativeitemsUuidnativeportfolioNumericid'; +} + /** * TranslateTestModel class. * diff --git a/lib/Cake/Test/Fixture/UuidNativeFixture.php b/lib/Cake/Test/Fixture/UuidNativeFixture.php new file mode 100644 index 000000000..0e03fbab4 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidNativeFixture.php @@ -0,0 +1,50 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.6700 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuidNativeFixture. + * + * @package Cake.Test.Fixture + */ +class UuidNativeFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'title' => 'string', + 'count' => array('type' => 'integer', 'default' => 0), + 'created' => 'datetime', + 'updated' => 'datetime' + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('id' => '47c36f9c-bc00-4d17-9626-4e183ca6822b', 'title' => 'Unique record 1', 'count' => 2, 'created' => '2008-03-13 01:16:23', 'updated' => '2008-03-13 01:18:31'), + array('id' => '47c36f9c-f2b0-43f5-b3f7-4e183ca6822b', 'title' => 'Unique record 2', 'count' => 4, 'created' => '2008-03-13 01:18:24', 'updated' => '2008-03-13 01:20:32'), + array('id' => '47c36f9c-0ffc-4084-9b03-4e183ca6822b', 'title' => 'Unique record 3', 'count' => 5, 'created' => '2008-03-13 01:20:25', 'updated' => '2008-03-13 01:22:33'), + array('id' => '47c36f9c-2578-4c2e-aeab-4e183ca6822b', 'title' => 'Unique record 4', 'count' => 3, 'created' => '2008-03-13 01:22:26', 'updated' => '2008-03-13 01:24:34'), + ); +} diff --git a/lib/Cake/Test/Fixture/UuidNativeTagFixture.php b/lib/Cake/Test/Fixture/UuidNativeTagFixture.php new file mode 100644 index 000000000..0956ccda1 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidNativeTagFixture.php @@ -0,0 +1,45 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.7953 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuidNativeTagFixture + * + * @package Cake.Test.Fixture + */ +class UuidNativeTagFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'name' => array('type' => 'string', 'length' => 255), + 'created' => array('type' => 'datetime') + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('id' => '481fc6d0-b920-43e0-e50f-6d1740cf8569', 'name' => 'MyTag', 'created' => '2009-12-09 12:30:00') + ); +} diff --git a/lib/Cake/Test/Fixture/UuidNativeTreeFixture.php b/lib/Cake/Test/Fixture/UuidNativeTreeFixture.php new file mode 100644 index 000000000..2fdd866c3 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidNativeTreeFixture.php @@ -0,0 +1,39 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.7984 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * UuidNativeTreeFixture class + * + * @uses CakeTestFixture + * @package Cake.Test.Fixture + */ +class UuidNativeTreeFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'name' => array('type' => 'string', 'null' => false), + 'parent_id' => array('type' => 'string', 'length' => 36, 'null' => true), + 'lft' => array('type' => 'integer', 'null' => false), + 'rght' => array('type' => 'integer', 'null' => false) + ); +} diff --git a/lib/Cake/Test/Fixture/UuidnativeitemFixture.php b/lib/Cake/Test/Fixture/UuidnativeitemFixture.php new file mode 100644 index 000000000..e810e2af9 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidnativeitemFixture.php @@ -0,0 +1,50 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.4667 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuidnativeitemFixture + * + * @package Cake.Test.Fixture + */ +class UuidnativeitemFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'published' => array('type' => 'boolean', 'null' => false), + 'name' => array('type' => 'string', 'null' => false) + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('id' => '481fc6d0-b920-43e0-a40d-6d1740cf8569', 'published' => 0, 'name' => 'Item 1'), + array('id' => '48298a29-81c0-4c26-a7fb-413140cf8569', 'published' => 0, 'name' => 'Item 2'), + array('id' => '482b7756-8da0-419a-b21f-27da40cf8569', 'published' => 0, 'name' => 'Item 3'), + array('id' => '482cfd4b-0e7c-4ea3-9582-4cec40cf8569', 'published' => 0, 'name' => 'Item 4'), + array('id' => '4831181b-4020-4983-a29b-131440cf8569', 'published' => 0, 'name' => 'Item 5'), + array('id' => '483798c8-c7cc-430e-8cf9-4fcc40cf8569', 'published' => 0, 'name' => 'Item 6') + ); +} diff --git a/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioFixture.php b/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioFixture.php new file mode 100644 index 000000000..39d4535e2 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioFixture.php @@ -0,0 +1,48 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.4667 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuiditemsUuidportfolioFixture + * + * @package Cake.Test.Fixture + */ +class UuidnativeitemsUuidnativeportfolioFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'uuidnativeitem_id' => array('type' => 'uuid', 'null' => false), + 'uuidnativeportfolio_id' => array('type' => 'uuid', 'null' => false) + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('id' => '4850fd8f-cc5c-449f-bf34-0c5240cf8569', 'uuidnativeitem_id' => '481fc6d0-b920-43e0-a40d-6d1740cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569'), + array('id' => '4850fee5-d24c-4ea0-9759-0c2e40cf8569', 'uuidnativeitem_id' => '48298a29-81c0-4c26-a7fb-413140cf8569', 'uuidnativeportfolio_id' => '480af662-eb8c-47d3-886b-230540cf8569'), + array('id' => '4851af6e-fa18-403d-b57e-437d40cf8569', 'uuidnativeitem_id' => '482b7756-8da0-419a-b21f-27da40cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569'), + array('id' => '4851b94c-9790-42dc-b760-4f9240cf8569', 'uuidnativeitem_id' => '482cfd4b-0e7c-4ea3-9582-4cec40cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569') + ); +} diff --git a/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioNumericidFixture.php b/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioNumericidFixture.php new file mode 100644 index 000000000..6c304324e --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidnativeitemsUuidnativeportfolioNumericidFixture.php @@ -0,0 +1,48 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.4667 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuidnativeitemsUuidnativeportfolioNumericidFixture + * + * @package Cake.Test.Fixture + */ +class UuidnativeitemsUuidnativeportfolioNumericidFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'integer', 'length' => 10, 'key' => 'primary'), + 'uuidnativeitem_id' => array('type' => 'uuid', 'null' => false), + 'uuidnativeportfolio_id' => array('type' => 'uuid', 'null' => false) + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('uuidnativeitem_id' => '481fc6d0-b920-43e0-a40d-6d1740cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569'), + array('uuidnativeitem_id' => '48298a29-81c0-4c26-a7fb-413140cf8569', 'uuidnativeportfolio_id' => '480af662-eb8c-47d3-886b-230540cf8569'), + array('uuidnativeitem_id' => '482b7756-8da0-419a-b21f-27da40cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569'), + array('uuidnativeitem_id' => '482cfd4b-0e7c-4ea3-9582-4cec40cf8569', 'uuidnativeportfolio_id' => '4806e091-6940-4d2b-b227-303740cf8569') + ); +} diff --git a/lib/Cake/Test/Fixture/UuidnativeportfolioFixture.php b/lib/Cake/Test/Fixture/UuidnativeportfolioFixture.php new file mode 100644 index 000000000..058d79af8 --- /dev/null +++ b/lib/Cake/Test/Fixture/UuidnativeportfolioFixture.php @@ -0,0 +1,45 @@ + + * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * + * Licensed under The MIT License + * For full copyright and license information, please see the LICENSE.txt + * Redistributions of files must retain the above copyright notice + * + * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org) + * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests + * @package Cake.Test.Fixture + * @since CakePHP(tm) v 1.2.0.4667 + * @license http://www.opensource.org/licenses/mit-license.php MIT License + */ + +/** + * Class UuidnativeportfolioFixture + * + * @package Cake.Test.Fixture + */ +class UuidnativeportfolioFixture extends CakeTestFixture { + +/** + * fields property + * + * @var array + */ + public $fields = array( + 'id' => array('type' => 'uuid', 'key' => 'primary'), + 'name' => array('type' => 'string', 'null' => false) + ); + +/** + * records property + * + * @var array + */ + public $records = array( + array('id' => '4806e091-6940-4d2b-b227-303740cf8569', 'name' => 'Portfolio 1'), + array('id' => '480af662-eb8c-47d3-886b-230540cf8569', 'name' => 'Portfolio 2'), + ); +} From 209cdd71a9aa6e1cd34d0acce14271a5068ec79c Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 28 Jan 2016 21:54:49 +0300 Subject: [PATCH 05/38] code formatting fixes --- lib/Cake/Test/Case/Model/ModelWriteTest.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index bf9a2c67d..79a89fadd 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -270,7 +270,6 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(36, strlen($result['Uuid']['id'])); } - /** * testAutoSaveUuidNative method * @@ -291,7 +290,6 @@ class ModelWriteTest extends BaseModelTest { $this->assertEquals(36, strlen($result['UuidNative']['id'])); } - /** * Ensure that if the id key is null but present the save doesn't fail (with an * x sql error: "Column id specified twice") @@ -323,8 +321,8 @@ class ModelWriteTest extends BaseModelTest { public function testSaveUuidNullNative() { $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); - $this->loadFixtures('UuidNative'); - $TestModel = new UuidNative(); + $this->loadFixtures('UuidNative'); + $TestModel = new UuidNative(); $TestModel->save(array('title' => 'Test record', 'id' => null)); $result = $TestModel->findByTitle('Test record'); From e83a532af0910558cd64e428285a61e9a5732ccc Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 28 Jan 2016 22:12:24 +0300 Subject: [PATCH 06/38] Fixed array syntax. --- .../Test/Case/Controller/Component/SecurityComponentTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php index 112e5ec84..08d0a21f7 100644 --- a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php @@ -498,10 +498,10 @@ class SecurityComponentTest extends CakeTestCase { $fields = 'an-invalid-token'; $unlocked = ''; - $this->Controller->request->data = [ + $this->Controller->request->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('fields', 'unlocked') - ]; + ); $this->assertFalse($this->Controller->failed, 'Should not be failed yet'); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'Should fail because of validatePost.'); From 70c4e40532cd021df9e1749a68698ef82fd9137e Mon Sep 17 00:00:00 2001 From: Yevgeny Tomenko Date: Thu, 28 Jan 2016 23:36:07 +0300 Subject: [PATCH 07/38] Fix value check and formatting. --- lib/Cake/Model/Datasource/Database/Postgres.php | 2 +- .../Test/Case/Controller/Component/SecurityComponentTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 993d7dd5a..94d5d2f95 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -934,7 +934,7 @@ class Postgres extends DboSource { */ public function value($data, $column = null, $null = true) { $value = parent::value($data, $column, $null); - if ($column == 'uuid' && is_scalar($data)) { + if ($column === 'uuid' && is_scalar($data)) { if ($data === '') { return 'NULL'; } diff --git a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php index 08d0a21f7..e579b6c05 100644 --- a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php @@ -501,7 +501,7 @@ class SecurityComponentTest extends CakeTestCase { $this->Controller->request->data = array( 'Model' => array('username' => 'nate', 'password' => 'foo', 'valid' => '0'), '_Token' => compact('fields', 'unlocked') - ); + ); $this->assertFalse($this->Controller->failed, 'Should not be failed yet'); $this->Controller->Security->startup($this->Controller); $this->assertTrue($this->Controller->failed, 'Should fail because of validatePost.'); From 3ca3ffeeee0189b7e4ec6f3db1bfabf4c316a567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20M=2E=20Gonz=C3=A1lez=20Mart=C3=ADn?= Date: Fri, 29 Jan 2016 08:56:36 +0000 Subject: [PATCH 08/38] fix phpcs --- lib/Cake/Test/Case/Model/ModelWriteTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 79a89fadd..e41fcc43d 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -276,7 +276,7 @@ class ModelWriteTest extends BaseModelTest { * @return void */ public function testAutoSaveUuidNative() { - $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); + $this->skipIf(!($this->db instanceof Postgres), 'This test is compatible with Postgres only.'); $this->loadFixtures('UuidNative'); $TestModel = new UuidNative(); From f1bea77d74125dd40657771dda41ee6710d59c87 Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Tue, 9 Feb 2016 01:18:43 +0100 Subject: [PATCH 09/38] Fix bool check and also some doc blocks. --- lib/Cake/Model/Behavior/TreeBehavior.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/lib/Cake/Model/Behavior/TreeBehavior.php b/lib/Cake/Model/Behavior/TreeBehavior.php index a19d4a8fe..374721343 100644 --- a/lib/Cake/Model/Behavior/TreeBehavior.php +++ b/lib/Cake/Model/Behavior/TreeBehavior.php @@ -568,7 +568,7 @@ class TreeBehavior extends ModelBehavior { * @return array Options array */ protected function _getOptions($arg) { - return count(array_filter(array_keys($arg), 'is_string') > 0) ? + return count(array_filter(array_keys($arg), 'is_string')) > 0 ? $arg : array(); } @@ -577,9 +577,9 @@ class TreeBehavior extends ModelBehavior { * Get the path to the given node * * @param Model $Model Model using this behavior - * @param int|string $id The ID of the record to read - * @param string|array $fields Either a single string of a field name, or an array of field names - * @param int $recursive The number of levels deep to fetch associated records + * @param int|string|null $id The ID of the record to read + * @param string|array|null $fields Either a single string of a field name, or an array of field names + * @param int|null $recursive The number of levels deep to fetch associated records * @return array Array of nodes from top most parent to current node * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::getPath */ @@ -639,7 +639,7 @@ class TreeBehavior extends ModelBehavior { * If the node is the last child, or is a top level node with no subsequent node this method will return false * * @param Model $Model Model using this behavior - * @param int|string $id The ID of the record to move + * @param int|string|null $id The ID of the record to move * @param int|bool $number how many places to move the node or true to move to last position * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::moveDown @@ -693,7 +693,7 @@ class TreeBehavior extends ModelBehavior { * If the node is the first child, or is a top level node with no previous node this method will return false * * @param Model $Model Model using this behavior - * @param int|string $id The ID of the record to move + * @param int|string|null $id The ID of the record to move * @param int|bool $number how many places to move the node, or true to move to first position * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::moveUp @@ -751,7 +751,7 @@ class TreeBehavior extends ModelBehavior { * * @param Model $Model Model using this behavior * @param string $mode parent or tree - * @param string|int $missingParentAction 'return' to do nothing and return, 'delete' to + * @param string|int|null $missingParentAction 'return' to do nothing and return, 'delete' to * delete, or the id of the parent to set as the parent_id * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::recover @@ -811,7 +811,7 @@ class TreeBehavior extends ModelBehavior { * * @param Model $Model Model instance. * @param int $counter Counter - * @param mixed $parentId Parent record Id + * @param int|string|null $parentId Parent record Id * @return int counter */ protected function _recoverByParentId(Model $Model, $counter = 1, $parentId = null) { @@ -929,7 +929,7 @@ class TreeBehavior extends ModelBehavior { * after the children are reparented. * * @param Model $Model Model using this behavior - * @param int|string $id The ID of the record to remove + * @param int|string|null $id The ID of the record to remove * @param bool $delete whether to delete the node after reparenting children (if any) * @return bool true on success, false on failure * @link http://book.cakephp.org/2.0/en/core-libraries/behaviors/tree.html#TreeBehavior::removeFromTree @@ -1064,7 +1064,7 @@ class TreeBehavior extends ModelBehavior { * Returns the depth level of a node in the tree. * * @param Model $Model Model using this behavior - * @param int|string $id The primary key for record to get the level of. + * @param int|string|null $id The primary key for record to get the level of. * @return int|bool Integer of the level or false if the node does not exist. */ public function getLevel(Model $Model, $id = null) { @@ -1103,7 +1103,7 @@ class TreeBehavior extends ModelBehavior { * method could be private, since calling save with parent_id set also calls setParent * * @param Model $Model Model using this behavior - * @param int|string $parentId Parent record Id + * @param int|string|null $parentId Parent record Id * @param bool $created True if newly created record else false. * @return bool true on success, false on failure */ From e4b939bba0aad5bd9fa48e65f7a940f12008ddcc Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 8 Feb 2016 22:37:25 -0500 Subject: [PATCH 10/38] Backport fix for Validation::uploadedFile to 2.x Don't fail validation when the keys are not the expected order. Refs #8201 --- lib/Cake/Test/Case/Utility/ValidationTest.php | 16 ++++++++++++++++ lib/Cake/Utility/Validation.php | 3 ++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/Utility/ValidationTest.php b/lib/Cake/Test/Case/Utility/ValidationTest.php index 8b326f166..0e1c6293f 100644 --- a/lib/Cake/Test/Case/Utility/ValidationTest.php +++ b/lib/Cake/Test/Case/Utility/ValidationTest.php @@ -2505,4 +2505,20 @@ class ValidationTest extends CakeTestCase { ); $this->assertFalse(Validation::uploadedFile($file, $options), 'File is required.'); } +/** + * Test uploaded file validation. + * + * @return void + */ + public function testUploadedFileWithDifferentFileParametersOrder() { + $file = array( + 'name' => 'cake.power.gif', + 'error' => UPLOAD_ERR_OK, + 'tmp_name' => CORE_PATH . 'Cake' . DS . 'Test' . DS . 'test_app' . DS . 'webroot/img/cake.power.gif', + 'type' => 'text/plain', + 'size' => 201 + ); + $options = array(); + $this->assertTrue(Validation::uploadedFile($file, $options), 'Wrong order'); + } } diff --git a/lib/Cake/Utility/Validation.php b/lib/Cake/Utility/Validation.php index 2f20d2739..2700c0ac7 100644 --- a/lib/Cake/Utility/Validation.php +++ b/lib/Cake/Utility/Validation.php @@ -1016,7 +1016,8 @@ class Validation { if (!is_array($file)) { return false; } - $keys = array('name', 'tmp_name', 'error', 'type', 'size'); + $keys = array('error', 'name', 'size', 'tmp_name', 'type'); + ksort($file); if (array_keys($file) != $keys) { return false; } From 5b10e3cac2ddc690e115d77fccdc3fd8a4e7e031 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgaras=20Janu=C5=A1auskas?= Date: Thu, 28 Jan 2016 23:03:24 +0200 Subject: [PATCH 11/38] Use mixed return type for AuthComponent::user() --- lib/Cake/Controller/Component/AuthComponent.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Component/AuthComponent.php b/lib/Cake/Controller/Component/AuthComponent.php index c6ac17b9c..3381d68f1 100644 --- a/lib/Cake/Controller/Component/AuthComponent.php +++ b/lib/Cake/Controller/Component/AuthComponent.php @@ -655,7 +655,7 @@ class AuthComponent extends Component { * cookies + sessions will be used. * * @param string|null $key field to retrieve. Leave null to get entire User record - * @return array|null User record. or null if no user is logged in. + * @return mixed|null User record. or null if no user is logged in. * @link http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#accessing-the-logged-in-user */ public static function user($key = null) { From b5655d63ff554fc956abb07f8d3663f5373c399b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 10 Feb 2016 12:27:34 +0100 Subject: [PATCH 12/38] Remove lighthouse references --- lib/Cake/Network/CakeRequest.php | 1 - lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php | 2 -- .../Case/Controller/Component/RequestHandlerComponentTest.php | 1 - .../Test/Case/Controller/Component/SecurityComponentTest.php | 2 -- lib/Cake/Test/Case/Core/AppTest.php | 1 - lib/Cake/Test/Case/Model/ModelWriteTest.php | 3 --- lib/Cake/Test/Case/Network/CakeRequestTest.php | 1 - lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php | 1 - lib/Cake/Test/Case/View/ViewTest.php | 1 - 9 files changed, 13 deletions(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 05b0ad24a..cd9e893bd 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -288,7 +288,6 @@ class CakeRequest implements ArrayAccess { * the unnecessary part from $base to prevent issue #3318. * * @return string Base URL - * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 */ protected function _base() { $dir = $webroot = null; diff --git a/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php b/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php index 8faae470a..0ff514df6 100644 --- a/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/AuthComponentTest.php @@ -1621,8 +1621,6 @@ class AuthComponentTest extends CakeTestCase { /** * test that the returned URL doesn't contain the base URL. * - * @see https://cakephp.lighthouseapp.com/projects/42648/tickets/3922-authcomponentredirecturl-prepends-appbaseurl - * * @return void This test method doesn't return anything. */ public function testRedirectUrlWithBaseSet() { diff --git a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php index aa20baeff..1e9f8daaf 100644 --- a/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/RequestHandlerComponentTest.php @@ -870,7 +870,6 @@ class RequestHandlerComponentTest extends CakeTestCase { * array URLs into their correct string ones, and adds base => false so * the correct URLs are generated. * - * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp-1x/tickets/276 * @return void */ public function testBeforeRedirectCallbackWithArrayUrl() { diff --git a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php index e579b6c05..520b90098 100644 --- a/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/SecurityComponentTest.php @@ -1164,7 +1164,6 @@ class SecurityComponentTest extends CakeTestCase { * the params. * * @return void - * @see https://cakephp.lighthouseapp.com/projects/42648/tickets/68 */ public function testSettingTokenForRequestAction() { $this->Controller->Security->startup($this->Controller); @@ -1181,7 +1180,6 @@ class SecurityComponentTest extends CakeTestCase { * test that blackhole doesn't delete the _Token session key so repeat data submissions * stay blackholed. * - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/214 * @return void */ public function testBlackHoleNotDeletingSessionInformation() { diff --git a/lib/Cake/Test/Case/Core/AppTest.php b/lib/Cake/Test/Case/Core/AppTest.php index ecaa4bd92..9e771bdb6 100644 --- a/lib/Cake/Test/Case/Core/AppTest.php +++ b/lib/Cake/Test/Case/Core/AppTest.php @@ -576,7 +576,6 @@ class AppTest extends CakeTestCase { * test that building helper paths actually works. * * @return void - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/410 */ public function testImportingHelpersFromAlternatePaths() { $this->assertFalse(class_exists('BananaHelper', false), 'BananaHelper exists, cannot test importing it.'); diff --git a/lib/Cake/Test/Case/Model/ModelWriteTest.php b/lib/Cake/Test/Case/Model/ModelWriteTest.php index 70ca570e9..92c1f4a08 100644 --- a/lib/Cake/Test/Case/Model/ModelWriteTest.php +++ b/lib/Cake/Test/Case/Model/ModelWriteTest.php @@ -5313,7 +5313,6 @@ class ModelWriteTest extends BaseModelTest { /** * test that saveAll behaves like plain save() when supplied empty data * - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveAllEmptyData() { @@ -6781,7 +6780,6 @@ class ModelWriteTest extends BaseModelTest { /** * test that saveMany behaves like plain save() when suplied empty data * - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveManyEmptyData() { @@ -6800,7 +6798,6 @@ class ModelWriteTest extends BaseModelTest { /** * test that saveAssociated behaves like plain save() when supplied empty data * - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/277-test-saveall-with-validation-returns-incorrect-boolean-when-saving-empty-data * @return void */ public function testSaveAssociatedEmptyData() { diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 7d1d0706c..684f4286b 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -1362,7 +1362,6 @@ class CakeRequestTest extends CakeTestCase { * - index.php/apples/ * - index.php/bananas/eat/tasty_banana * - * @link https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/3318 * @return void */ public function testBaseUrlWithModRewriteAndIndexPhp() { diff --git a/lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php b/lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php index efd8878d8..41e158ed8 100644 --- a/lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php +++ b/lib/Cake/Test/Case/TestSuite/ControllerTestCaseTest.php @@ -596,7 +596,6 @@ class ControllerTestCaseTest extends CakeTestCase { * will always have a fresh reference to those object available * * @return void - * @see https://cakephp.lighthouseapp.com/projects/42648-cakephp/tickets/2705-requesthandler-weird-behavior */ public function testComponentsSameRequestAndResponse() { $this->Case->generate('TestsApps'); diff --git a/lib/Cake/Test/Case/View/ViewTest.php b/lib/Cake/Test/Case/View/ViewTest.php index 4973c688f..fc229464f 100644 --- a/lib/Cake/Test/Case/View/ViewTest.php +++ b/lib/Cake/Test/Case/View/ViewTest.php @@ -1460,7 +1460,6 @@ class ViewTest extends CakeTestCase { * Test setting a block's content to null * * @return void - * @link https://cakephp.lighthouseapp.com/projects/42648/tickets/3938-this-redirectthis-auth-redirecturl-broken */ public function testBlockSetNull() { $this->View->assign('testWithNull', null); From 780b836d5753a814989ea7ae847958de10894c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Wed, 10 Feb 2016 13:37:10 +0100 Subject: [PATCH 13/38] Deprecate SecurityComponent::requireAuth & SecurityComponent::requireAuth() Backport of https://github.com/cakephp/cakephp/pull/8191 --- lib/Cake/Controller/Component/SecurityComponent.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Cake/Controller/Component/SecurityComponent.php b/lib/Cake/Controller/Component/SecurityComponent.php index 31a14ef5c..1ed1c0eb1 100644 --- a/lib/Cake/Controller/Component/SecurityComponent.php +++ b/lib/Cake/Controller/Component/SecurityComponent.php @@ -92,6 +92,7 @@ class SecurityComponent extends Component { * * @var array * @see SecurityComponent::requireAuth() + * @deprecated 2.8.1 This feature is confusing and not useful. */ public $requireAuth = array(); @@ -400,6 +401,7 @@ class SecurityComponent extends Component { * * @param Controller $controller Instantiating controller * @return bool|null True if authentication required + * @deprecated 2.8.1 This feature is confusing and not useful. */ protected function _authRequired(Controller $controller) { if (is_array($this->requireAuth) && !empty($this->requireAuth) && !empty($this->request->data)) { From c05835d85d475e5cca0d29b74d8a491df4ee8708 Mon Sep 17 00:00:00 2001 From: Seth Tanner Date: Thu, 11 Feb 2016 01:49:34 +0000 Subject: [PATCH 14/38] refs #8027 combine if statements --- lib/Cake/Model/Datasource/Database/Postgres.php | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index 94d5d2f95..dfe5272ec 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -934,10 +934,8 @@ class Postgres extends DboSource { */ public function value($data, $column = null, $null = true) { $value = parent::value($data, $column, $null); - if ($column === 'uuid' && is_scalar($data)) { - if ($data === '') { - return 'NULL'; - } + if ($column === 'uuid' && is_scalar($data) && $data === '') { + return 'NULL'; } return $value; } From 0c183b9b8ead9105a546bc360d1a038eb93d634d Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Mon, 15 Feb 2016 19:31:24 -0600 Subject: [PATCH 15/38] Read content type in a more compatible way. Not all webservers set CONTENT_TYPE. The built-in PHP webserver for example sets HTTP_CONTENT_TYPE instead. Add a public method to the request object to smooth over this difference. Refs #6051, #8267 --- lib/Cake/Network/CakeRequest.php | 15 ++++++++++++++- lib/Cake/Test/Case/Network/CakeRequestTest.php | 15 +++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index cd9e893bd..3a5e1eb5a 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -165,7 +165,7 @@ class CakeRequest implements ArrayAccess { if ($_POST) { $this->data = $_POST; } elseif (($this->is('put') || $this->is('delete')) && - strpos(env('CONTENT_TYPE'), 'application/x-www-form-urlencoded') === 0 + strpos($this->contentType(), 'application/x-www-form-urlencoded') === 0 ) { $data = $this->_readInput(); parse_str($data, $this->data); @@ -393,6 +393,19 @@ class CakeRequest implements ArrayAccess { } } } + +/** + * Get the content type used in this request. + * + * @return string + */ + public function contentType() { + $type = env('CONTENT_TYPE'); + if ($type) { + return $type; + } + return env('HTTP_CONTENT_TYPE'); + } /** * Get the IP the client is using, or says they are using. diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 684f4286b..03bf3aa3f 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -145,6 +145,21 @@ class CakeRequestTest extends CakeTestCase { $request = new CakeRequest(null, false); $this->assertFalse(isset($request->query['one'])); } + +/** + * Test the content type method. + * + * @return void + */ + public function testContentType() { + $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; + $request = Request::createFromGlobals(); + $this->assertEquals('application/json', $request->contentType()); + + $_SERVER['CONTENT_TYPE'] = 'application/xml'; + $request = Request::createFromGlobals(); + $this->assertEquals('application/xml', $request->contentType(), 'prefer non http header.'); + } /** * Test construction From 849abab6a4d44bde04b6ae491f190e7f2cd6cc61 Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Mon, 15 Feb 2016 19:34:05 -0600 Subject: [PATCH 16/38] Fixing test case --- lib/Cake/Test/Case/Network/CakeRequestTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 03bf3aa3f..307245d21 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -153,11 +153,11 @@ class CakeRequestTest extends CakeTestCase { */ public function testContentType() { $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; - $request = Request::createFromGlobals(); + $request = new CakeRequest('/', false); $this->assertEquals('application/json', $request->contentType()); $_SERVER['CONTENT_TYPE'] = 'application/xml'; - $request = Request::createFromGlobals(); + $request = new CakeRequest('/', false); $this->assertEquals('application/xml', $request->contentType(), 'prefer non http header.'); } From bf22e84d6538b33d437b0bbf138c087944056e15 Mon Sep 17 00:00:00 2001 From: Chris Hallgren Date: Mon, 15 Feb 2016 20:44:27 -0600 Subject: [PATCH 17/38] CS fixes --- lib/Cake/Network/CakeRequest.php | 16 ++++++++-------- lib/Cake/Test/Case/Network/CakeRequestTest.php | 18 +++++++++--------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 3a5e1eb5a..4ea520280 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -393,19 +393,19 @@ class CakeRequest implements ArrayAccess { } } } - + /** * Get the content type used in this request. * * @return string */ - public function contentType() { - $type = env('CONTENT_TYPE'); - if ($type) { - return $type; - } - return env('HTTP_CONTENT_TYPE'); - } + public function contentType() { + $type = env('CONTENT_TYPE'); + if ($type) { + return $type; + } + return env('HTTP_CONTENT_TYPE'); + } /** * Get the IP the client is using, or says they are using. diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 307245d21..e1c1d3598 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -145,21 +145,21 @@ class CakeRequestTest extends CakeTestCase { $request = new CakeRequest(null, false); $this->assertFalse(isset($request->query['one'])); } - + /** * Test the content type method. * * @return void */ - public function testContentType() { - $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; - $request = new CakeRequest('/', false); - $this->assertEquals('application/json', $request->contentType()); + public function testContentType() { + $_SERVER['HTTP_CONTENT_TYPE'] = 'application/json'; + $request = new CakeRequest('/', false); + $this->assertEquals('application/json', $request->contentType()); - $_SERVER['CONTENT_TYPE'] = 'application/xml'; - $request = new CakeRequest('/', false); - $this->assertEquals('application/xml', $request->contentType(), 'prefer non http header.'); - } + $_SERVER['CONTENT_TYPE'] = 'application/xml'; + $request = new CakeRequest('/', false); + $this->assertEquals('application/xml', $request->contentType(), 'prefer non http header.'); + } /** * Test construction From b2509ea13d0e8743626b0fc13b4c8b3463762779 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 16 Feb 2016 22:21:06 -0500 Subject: [PATCH 18/38] Fix inherited permissions when checking the '*' permission. When checking inherited permissions for '*' also copy inherited permissions onto the inherited list. By copying the inherited values, we get the union of explit allow and inherited permissions, which if all things go well will match the permission key list. Refs #8114 --- lib/Cake/Model/Permission.php | 6 ++-- .../Controller/Component/Acl/DbAclTest.php | 31 +++++++++++++++++-- 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Model/Permission.php b/lib/Cake/Model/Permission.php index 39c64ca57..f03fa30e8 100644 --- a/lib/Cake/Model/Permission.php +++ b/lib/Cake/Model/Permission.php @@ -107,10 +107,10 @@ class Permission extends AppModel { return false; } - $inherited = array(); $acoIDs = Hash::extract($acoPath, '{n}.' . $this->Aco->alias . '.id'); $count = count($aroPath); + $inherited = array(); for ($i = 0; $i < $count; $i++) { $permAlias = $this->alias; @@ -134,8 +134,8 @@ class Permission extends AppModel { if (!empty($perm)) { if ($perm[$key] == -1) { return false; - } elseif ($perm[$key] == 1) { - $inherited[$key] = 1; + } elseif ($perm[$key] == 1 || $perm[$key] == 0) { + $inherited[$key] = $perm[$key]; } } } diff --git a/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php b/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php index b1f927a58..99eccfe03 100644 --- a/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php +++ b/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php @@ -429,17 +429,44 @@ class DbAclTest extends CakeTestCase { * @return void */ public function testInherit() { - //parent doesn't have access inherit should still deny + // parent doesn't have access inherit should still deny $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete')); $this->Acl->inherit('Milton', 'smash', 'delete'); $this->assertFalse($this->Acl->check('Milton', 'smash', 'delete')); - //inherit parent + // inherit parent $this->assertFalse($this->Acl->check('Milton', 'smash', 'read')); $this->Acl->inherit('Milton', 'smash', 'read'); $this->assertTrue($this->Acl->check('Milton', 'smash', 'read')); } +/** + * test inherit from deny method + * + * @return void + */ + public function testInheritParentDeny() { + $this->Acl->Aco->create(array('parent_id' => null, 'alias' => 'world')); + $this->Acl->Aco->save(); + + $this->Acl->Aco->create(array('parent_id' => $this->Acl->Aco->id, 'alias' => 'town')); + $this->Acl->Aco->save(); + + $this->Acl->Aro->create(array('parent_id' => null, 'alias' => 'Jane')); + $this->Acl->Aro->save(); + + // Setup deny on create for parent + $this->Acl->allow('Jane', 'world', '*'); + $this->Acl->deny('Jane', 'world', 'create'); + + // Setup inherit and specify allow for create on child. + $this->Acl->inherit('Jane', 'town', '*'); + $this->Acl->allow('Jane', 'town', 'create'); + + $this->assertTrue($this->Acl->check('Jane', 'town', 'create'), 'Should have access due to override'); + $this->assertTrue($this->Acl->check('Jane', 'town', '*'), 'Should have access due to inherit'); + } + /** * testDbGrant method * From 7a5907057abf94732817938e00fdddc7725ad93f Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 18 Feb 2016 21:03:57 -0500 Subject: [PATCH 19/38] Ensure keys are strings before accessing them. Some userland datasources (namely an oracle driver) manage to get arrays into $stack. Refs #8281 --- lib/Cake/Model/Datasource/DataSource.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/DataSource.php b/lib/Cake/Model/Datasource/DataSource.php index e77df4f8e..37e1e0f14 100644 --- a/lib/Cake/Model/Datasource/DataSource.php +++ b/lib/Cake/Model/Datasource/DataSource.php @@ -368,7 +368,7 @@ class DataSource extends Object { } else { $found = false; foreach (array_reverse($stack) as $assocData) { - if (isset($data[$assocData]) && isset($data[$assocData][$insertKey])) { + if (is_string($assocData) && isset($data[$assocData]) && isset($data[$assocData][$insertKey])) { $val = $data[$assocData][$insertKey]; $found = true; break; From 8f3df8b13e151a67c8b7919896ce486bd36aeb35 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 18 Feb 2016 21:14:55 -0500 Subject: [PATCH 20/38] Make tests not fail when extensions are installed If the extensions are installed but memcached/redis are not running errors should not be emitted. --- lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php | 6 ++++++ lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php | 7 +++++++ 2 files changed, 13 insertions(+) diff --git a/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php b/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php index 867422b55..2e915c4ef 100644 --- a/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php +++ b/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php @@ -64,6 +64,12 @@ class MemcachedEngineTest extends CakeTestCase { parent::setUp(); $this->skipIf(!class_exists('Memcached'), 'Memcached is not installed or configured properly.'); + // @codingStandardsIgnoreStart + $socket = @fsockopen('127.0.0.1', 11211, $errno, $errstr, 1); + // @codingStandardsIgnoreEnd + $this->skipIf(!$socket, 'Memcached is not running.'); + fclose($socket); + Cache::config('memcached', array( 'engine' => 'Memcached', 'prefix' => 'cake_', diff --git a/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php b/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php index bbc7228d4..aec71a3ba 100644 --- a/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php +++ b/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php @@ -37,6 +37,13 @@ class RedisEngineTest extends CakeTestCase { $this->_cacheDisable = Configure::read('Cache.disable'); Configure::write('Cache.disable', false); + + // @codingStandardsIgnoreStart + $socket = @fsockopen('127.0.0.1', 6379, $errno, $errstr, 1); + // @codingStandardsIgnoreEnd + $this->skipIf(!$socket, 'Redis is not running.'); + fclose($socket); + Cache::config('redis', array( 'engine' => 'Redis', 'prefix' => 'cake_', From 4389c7944287e421759c8c7fa98b0e676cd47cab Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 18 Feb 2016 21:24:52 -0500 Subject: [PATCH 21/38] Update tests. The old tests were relying on the fixed inherit bug. Instead check a specific permission which will result in a deny. Refs #8114 --- lib/Cake/Model/Permission.php | 1 - lib/Cake/Test/Case/Console/Command/AclShellTest.php | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/Cake/Model/Permission.php b/lib/Cake/Model/Permission.php index f03fa30e8..303124b03 100644 --- a/lib/Cake/Model/Permission.php +++ b/lib/Cake/Model/Permission.php @@ -129,7 +129,6 @@ class Permission extends AppModel { $perms = Hash::extract($perms, '{n}.' . $this->alias); foreach ($perms as $perm) { if ($action === '*') { - foreach ($permKeys as $key) { if (!empty($perm)) { if ($perm[$key] == -1) { diff --git a/lib/Cake/Test/Case/Console/Command/AclShellTest.php b/lib/Cake/Test/Case/Console/Command/AclShellTest.php index 1d79c90e5..702b7a57f 100644 --- a/lib/Cake/Test/Case/Console/Command/AclShellTest.php +++ b/lib/Cake/Test/Case/Console/Command/AclShellTest.php @@ -253,7 +253,7 @@ class AclShellTest extends CakeTestCase { $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'create'); $this->Task->check(); - $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', '*'); + $this->Task->args = array('AuthUser.2', 'ROOT/Controller1', 'delete'); $this->Task->check(); } From ee2d222b85efe5c8de4c49a44b34661ff0bcb357 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 21 Feb 2016 22:42:24 -0500 Subject: [PATCH 22/38] Correct API docs for find(). Fixes #8308 --- lib/Cake/Model/Model.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index bab919312..579581427 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -2937,7 +2937,7 @@ class Model extends Object implements CakeEventListener { * 'conditions' => array('name' => 'Thomas Anderson'), * 'fields' => array('name', 'email'), * 'order' => 'field3 DESC', - * 'recursive' => 2, + * 'recursive' => 1, * 'group' => 'type', * 'callbacks' => false, * )); From 7df99fff1fc4f94fc37940d1375db99f7bd5867c Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 22 Feb 2016 00:14:44 -0500 Subject: [PATCH 23/38] Backport Security::randomBytes() to 2.x I decided to leave the warning in. People who can't upgrade their applications should at least be aware of the risks they are taking. I'm flexible if people are strongly opposed to a warning, but I feel that these kinds of warnings can be supressed in production if they really are in a jam and don't care. Refs #8282 --- .../Component/SecurityComponent.php | 2 +- lib/Cake/Test/Case/Utility/SecurityTest.php | 12 ++++++++ lib/Cake/Utility/Security.php | 29 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Component/SecurityComponent.php b/lib/Cake/Controller/Component/SecurityComponent.php index 1ed1c0eb1..31a61f20d 100644 --- a/lib/Cake/Controller/Component/SecurityComponent.php +++ b/lib/Cake/Controller/Component/SecurityComponent.php @@ -534,7 +534,7 @@ class SecurityComponent extends Component { } return false; } - $authKey = Security::generateAuthKey(); + $authKey = hash('sha512', Security::randomBytes(16), false); $token = array( 'key' => $authKey, 'allowedControllers' => $this->allowedControllers, diff --git a/lib/Cake/Test/Case/Utility/SecurityTest.php b/lib/Cake/Test/Case/Utility/SecurityTest.php index 90ea96c86..18378725a 100644 --- a/lib/Cake/Test/Case/Utility/SecurityTest.php +++ b/lib/Cake/Test/Case/Utility/SecurityTest.php @@ -424,4 +424,16 @@ class SecurityTest extends CakeTestCase { Security::decrypt($txt, $key); } +/** + * Test the random method. + * + * @return void + */ + public function testRandomBytes() { + $value = Security::randomBytes(16); + $this->assertSame(16, strlen($value)); + + $value = Security::randomBytes(64); + $this->assertSame(64, strlen($value)); + } } diff --git a/lib/Cake/Utility/Security.php b/lib/Cake/Utility/Security.php index 511cf5efc..fda43a21a 100644 --- a/lib/Cake/Utility/Security.php +++ b/lib/Cake/Utility/Security.php @@ -166,6 +166,35 @@ class Security { static::$hashCost = $cost; } +/** + * Get random bytes from a secure source. + * + * This method will fall back to an insecure source an trigger a warning + * if it cannot find a secure source of random data. + * + * @param int $length The number of bytes you want. + * @return string Random bytes in binary. + */ + public static function randomBytes($length) { + if (function_exists('random_bytes')) { + return random_bytes($length); + } + if (function_exists('openssl_random_pseudo_bytes')) { + return openssl_random_pseudo_bytes($length); + } + trigger_error( + 'You do not have a safe source of random data available. ' . + 'Install either the openssl extension, or paragonie/random_compat. ' . + 'Falling back to an insecure random source.', + E_USER_WARNING + ); + $bytes = ''; + while ($bytes < $length) { + $bytes .= static::hash(CakeText::uuid() . uniqid(mt_rand(), true), 'sha512', true); + } + return substr($bytes, 0, $length); + } + /** * Runs $text through a XOR cipher. * From 7e5f56362fbf2c9cb047fa3a9165af40d8d11213 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 22 Feb 2016 00:16:15 -0500 Subject: [PATCH 24/38] Deprecate bad methods. These methods are bad and should feel bad. --- lib/Cake/Utility/Security.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Utility/Security.php b/lib/Cake/Utility/Security.php index fda43a21a..d7fcb00eb 100644 --- a/lib/Cake/Utility/Security.php +++ b/lib/Cake/Utility/Security.php @@ -61,6 +61,7 @@ class Security { * Generate authorization hash. * * @return string Hash + * @deprecated 2.8.1 This method was removed in 3.0.0 */ public static function generateAuthKey() { return Security::hash(CakeText::uuid()); @@ -71,6 +72,7 @@ class Security { * * @param string $authKey Authorization hash * @return bool Success + * @deprecated 2.8.1 This method was removed in 3.0.0 */ public static function validateAuthKey($authKey) { return true; @@ -92,7 +94,7 @@ class Security { * Creating a blowfish/bcrypt hash: * * ``` - * $hash = Security::hash($password, 'blowfish'); + * $hash = Security::hash($password, 'blowfish'); * ``` * * @param string $string String to hash From 125873941185f1583b7df817d7a5177d8b3217ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=BCrth?= Date: Tue, 23 Feb 2016 13:09:03 +0100 Subject: [PATCH 25/38] Replace Set by Hash References to the deprecated Set class don't make much sense. --- lib/Cake/Utility/Hash.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Utility/Hash.php b/lib/Cake/Utility/Hash.php index 2c9dd5f0b..3669e1a64 100644 --- a/lib/Cake/Utility/Hash.php +++ b/lib/Cake/Utility/Hash.php @@ -824,7 +824,7 @@ class Hash { } /** - * Sorts an array by any value, determined by a Set-compatible path + * Sorts an array by any value, determined by a Hash-compatible path * * ### Sort directions * @@ -849,7 +849,7 @@ class Hash { * defaults to `false`. * * @param array $data An array of data to sort - * @param string $path A Set-compatible path to the array value + * @param string $path A Hash-compatible path to the array value * @param string $dir See directions above. Defaults to 'asc'. * @param array|string $type See direction types above. Defaults to 'regular'. * @return array Sorted array of data From 9c0da4185805a527371c03a415cc17fa0a6b5ed0 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 23 Feb 2016 20:54:16 -0500 Subject: [PATCH 26/38] Skip test on PHP7 as the warning is not consistent. --- lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php b/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php index 2e915c4ef..babdf9779 100644 --- a/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php +++ b/lib/Cake/Test/Case/Cache/Engine/MemcachedEngineTest.php @@ -346,6 +346,7 @@ class MemcachedEngineTest extends CakeTestCase { * @return void */ public function testSaslAuthException() { + $this->skipIf(version_compare(PHP_VERSION, '7.0.0', '>=')); $Memcached = new TestMemcachedEngine(); $settings = array( 'engine' => 'Memcached', From 1a170e1eecade23091efd0e994342ed250cfa068 Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 24 Feb 2016 22:25:58 -0500 Subject: [PATCH 27/38] Fix parsing empty header values. Replace the complex and somewhat unfixable regexp based parser for a parser that handles each line individually. Normalize multi-line headers to replace multiple spaces with a single one. Section 4.2 of the HTTP1.1 standard states > Any LWS that occurs between field-content MAY be replaced with > a single SP before interpreting the field value or forwarding the > message downstream. This makes me somewhat confident that we can safely normalize multi-line HTTP header values. Refs #8330 --- lib/Cake/Network/Http/HttpSocketResponse.php | 26 +++++++++++++------ .../Case/Network/Http/HttpResponseTest.php | 13 ++++++++-- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/Cake/Network/Http/HttpSocketResponse.php b/lib/Cake/Network/Http/HttpSocketResponse.php index 99d875c31..ceaaf3074 100644 --- a/lib/Cake/Network/Http/HttpSocketResponse.php +++ b/lib/Cake/Network/Http/HttpSocketResponse.php @@ -268,18 +268,28 @@ class HttpSocketResponse implements ArrayAccess { return false; } - preg_match_all("/(.+):(.+)(?:(?_unescapeToken($field); + } $value = trim($value); - $value = preg_replace("/[\t ]\r\n/", "\r\n", $value); - - $field = $this->_unescapeToken($field); - - if (!isset($header[$field])) { + if (!isset($header[$field]) || $continuation) { $header[$field] = $value; } else { $header[$field] = array_merge((array)$header[$field], (array)$value); diff --git a/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php b/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php index 502340094..2fde8eb5e 100644 --- a/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php +++ b/lib/Cake/Test/Case/Network/Http/HttpResponseTest.php @@ -267,10 +267,19 @@ class HttpResponseTest extends CakeTestCase { ); $this->assertEquals($expected, $r); - $header = "Multi-Line: I am a \r\nmulti line\t\r\nfield value.\r\nSingle-Line: I am not\r\n"; + $header = "Date:Sat, 07 Apr 2007 10:10:25 GMT\r\nLink: \r\nX-Total-Count: 19\r\n"; $r = $this->HttpResponse->parseHeader($header); $expected = array( - 'Multi-Line' => "I am a\r\nmulti line\r\nfield value.", + 'Date' => 'Sat, 07 Apr 2007 10:10:25 GMT', + 'Link' => '', + 'X-Total-Count' => '19', + ); + $this->assertEquals($expected, $r); + + $header = "Multi-Line: I am a\r\n multi line \r\n\tfield value.\r\nSingle-Line: I am not\r\n"; + $r = $this->HttpResponse->parseHeader($header); + $expected = array( + 'Multi-Line' => "I am a multi line field value.", 'Single-Line' => 'I am not' ); $this->assertEquals($expected, $r); From 1709f54e381b4404fe9d2e49e6c7863da09dfafa Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 26 Feb 2016 12:39:29 -0500 Subject: [PATCH 28/38] Update documentation for Model::_readDataSource() Update sample code to generate unique keys based on association conditions as well. Because association conditions are not part of the 'query' they need to be handled separately. Refs #8346 --- lib/Cake/Model/Model.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/Cake/Model/Model.php b/lib/Cake/Model/Model.php index 579581427..ccbae1789 100644 --- a/lib/Cake/Model/Model.php +++ b/lib/Cake/Model/Model.php @@ -3011,15 +3011,15 @@ class Model extends Object implements CakeEventListener { * * ``` * protected function _readDataSource($type, $query) { - * $cacheName = md5(json_encode($query)); - * $cache = Cache::read($cacheName, 'cache-config-name'); - * if ($cache !== false) { - * return $cache; - * } + * $cacheName = md5(json_encode($query) . json_encode($this->hasOne) . json_encode($this->belongsTo)); + * $cache = Cache::read($cacheName, 'cache-config-name'); + * if ($cache !== false) { + * return $cache; + * } * - * $results = parent::_readDataSource($type, $query); - * Cache::write($cacheName, $results, 'cache-config-name'); - * return $results; + * $results = parent::_readDataSource($type, $query); + * Cache::write($cacheName, $results, 'cache-config-name'); + * return $results; * } * ``` * From 7b9ff1c11b0b4abd4000f62d24ca9ccadacabab8 Mon Sep 17 00:00:00 2001 From: phlyper Date: Fri, 26 Feb 2016 22:39:48 +0100 Subject: [PATCH 29/38] verify exists index 0 in $ref exemple i have to get the referrer url from any page if exists ``` class AppController extends Controller { ...... public function beforeRender() { parent::beforeRender(); $this->params['referer'] = $this->referer(null, true); } .......... } ``` --- lib/Cake/Network/CakeRequest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 4ea520280..8933822e4 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -448,7 +448,7 @@ class CakeRequest implements ArrayAccess { if (!empty($ref) && !empty($base)) { if ($local && strpos($ref, $base) === 0) { $ref = substr($ref, strlen($base)); - if ($ref[0] !== '/') { + if (isset($ref[0]) && $ref[0] !== '/') { $ref = '/' . $ref; } return $ref; From 3ed321dff433546070e6269740a25e8ba1769044 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Feb 2016 00:07:58 -0500 Subject: [PATCH 30/38] Handle negative numbers in Redis correctly. Update number sniff to handle negative numbers. We need to do number sniffing so we can maintain compatbility between write() and increment()/decrement(). Refs #8364 --- lib/Cake/Cache/Engine/RedisEngine.php | 6 +++--- .../Test/Case/Cache/Engine/RedisEngineTest.php | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Cache/Engine/RedisEngine.php b/lib/Cake/Cache/Engine/RedisEngine.php index 8dd98fb99..00c84261d 100644 --- a/lib/Cake/Cache/Engine/RedisEngine.php +++ b/lib/Cake/Cache/Engine/RedisEngine.php @@ -133,11 +133,11 @@ class RedisEngine extends CacheEngine { */ public function read($key) { $value = $this->_Redis->get($key); - if (ctype_digit($value)) { - $value = (int)$value; + if (preg_match('/^[-]?\d+$/', $value)) { + return (int)$value; } if ($value !== false && is_string($value)) { - $value = unserialize($value); + return unserialize($value); } return $value; } diff --git a/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php b/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php index aec71a3ba..23c5fa8ec 100644 --- a/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php +++ b/lib/Cake/Test/Case/Cache/Engine/RedisEngineTest.php @@ -144,6 +144,22 @@ class RedisEngineTest extends CakeTestCase { Cache::drop('redisdb1'); } +/** + * test write numbers method + * + * @return void + */ + public function testWriteNumbers() { + $result = Cache::write('test-counter', 1, 'redis'); + $this->assertSame(1, Cache::read('test-counter', 'redis')); + + $result = Cache::write('test-counter', 0, 'redis'); + $this->assertSame(0, Cache::read('test-counter', 'redis')); + + $result = Cache::write('test-counter', -1, 'redis'); + $this->assertSame(-1, Cache::read('test-counter', 'redis')); + } + /** * testReadAndWriteCache method * From 78f199f8a05ef4e5b3b7f665e37918da4a3bd6e8 Mon Sep 17 00:00:00 2001 From: mark_story Date: Sat, 27 Feb 2016 22:31:18 -0500 Subject: [PATCH 31/38] Update version number to 2.8.1 --- 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 d1eb33bc6..b3d9b643f 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.8.0 +2.8.1 From e5e4317217b4ccb2c78a3a7dc29327f0dad9ab25 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 1 Mar 2016 12:17:39 -0800 Subject: [PATCH 32/38] Updated deprecated doc for flash method --- lib/Cake/Controller/Controller.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index 4dead1942..b97ab5b42 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -534,7 +534,7 @@ class Controller extends Object implements CakeEventListener { */ protected function _getScaffold(CakeRequest $request) { return new Scaffold($this, $request); - } + }f /** * Merge components, helpers, and uses vars from @@ -1006,7 +1006,7 @@ class Controller extends Object implements CakeEventListener { * @param string $layout Layout you want to use, defaults to 'flash' * @return void * @link http://book.cakephp.org/2.0/en/controllers.html#Controller::flash - * @deprecated 3.0.0 Will be removed in 3.0. Use Session::setFlash(). + * @deprecated 3.0.0 Will be removed in 3.0. Use Flash::set() with version 2.7+ or Session::setFlash() prior to 2.7. */ public function flash($message, $url, $pause = 1, $layout = 'flash') { $this->autoRender = false; From 2386a86adcad9057749a8501caaac9d0ed085f25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgaras=20Janu=C5=A1auskas?= Date: Tue, 1 Mar 2016 22:21:14 +0200 Subject: [PATCH 33/38] Include Subject and To in email log when using MailTransport --- lib/Cake/Network/Email/CakeEmail.php | 2 +- lib/Cake/Network/Email/MailTransport.php | 3 +++ lib/Cake/Test/Case/Network/Email/MailTransportTest.php | 5 ++++- 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/Cake/Network/Email/CakeEmail.php b/lib/Cake/Network/Email/CakeEmail.php index bb55333f1..bf62be85a 100644 --- a/lib/Cake/Network/Email/CakeEmail.php +++ b/lib/Cake/Network/Email/CakeEmail.php @@ -1184,7 +1184,7 @@ class CakeEmail { } CakeLog::write( $config['level'], - PHP_EOL . $contents['headers'] . PHP_EOL . $contents['message'], + PHP_EOL . $contents['headers'] . PHP_EOL . PHP_EOL . $contents['message'], $config['scope'] ); } diff --git a/lib/Cake/Network/Email/MailTransport.php b/lib/Cake/Network/Email/MailTransport.php index 692ca06fe..9e27899d3 100644 --- a/lib/Cake/Network/Email/MailTransport.php +++ b/lib/Cake/Network/Email/MailTransport.php @@ -49,6 +49,9 @@ class MailTransport extends AbstractTransport { $params = isset($this->_config['additionalParameters']) ? $this->_config['additionalParameters'] : null; $this->_mail($to, $subject, $message, $headers, $params); + + $headers .= $eol . 'Subject: ' . $subject; + $headers .= $eol . 'To: ' . $to; return array('headers' => $headers, 'message' => $message); } diff --git a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php index dde5eaa90..73871e781 100644 --- a/lib/Cake/Test/Case/Network/Email/MailTransportTest.php +++ b/lib/Cake/Test/Case/Network/Email/MailTransportTest.php @@ -84,7 +84,10 @@ class MailTransportTest extends CakeTestCase { '-f' ); - $this->MailTransport->send($email); + $result = $this->MailTransport->send($email); + + $this->assertContains('Subject: ', $result['headers']); + $this->assertContains('To: ', $result['headers']); } } From 862397325df9262dd7b2ca75489618908042314f Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 1 Mar 2016 12:41:29 -0800 Subject: [PATCH 34/38] fixed typo --- lib/Cake/Controller/Controller.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index b97ab5b42..369cc2e83 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -534,7 +534,7 @@ class Controller extends Object implements CakeEventListener { */ protected function _getScaffold(CakeRequest $request) { return new Scaffold($this, $request); - }f + } /** * Merge components, helpers, and uses vars from From 3ad68db5ebb71de3ed97950977ed6b452cca359a Mon Sep 17 00:00:00 2001 From: mark_story Date: Wed, 2 Mar 2016 12:30:48 -0500 Subject: [PATCH 35/38] Tweak fix from #8359 This fixes a regression introduced in that change that we didn't previously have tests for. The issue fixed in #8359 was related to PHP7.0, whereas PHP5 didn't have an issue. Now both versions will work the same. --- lib/Cake/Network/CakeRequest.php | 5 ++++- lib/Cake/Test/Case/Network/CakeRequestTest.php | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index 8933822e4..eb9cebd84 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -448,7 +448,10 @@ class CakeRequest implements ArrayAccess { if (!empty($ref) && !empty($base)) { if ($local && strpos($ref, $base) === 0) { $ref = substr($ref, strlen($base)); - if (isset($ref[0]) && $ref[0] !== '/') { + if (empty($ref)) { + $ref = '/'; + } + if ($ref[0] !== '/') { $ref = '/' . $ref; } return $ref; diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index e1c1d3598..90f92c7bf 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -742,6 +742,10 @@ class CakeRequestTest extends CakeTestCase { $result = $request->referer(); $this->assertSame($result, '/'); + $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/'; + $result = $request->referer(true); + $this->assertSame($result, '/'); + $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/some/path'; $result = $request->referer(true); $this->assertSame($result, '/some/path'); From 48af49ddde16c8b99edb701f1c31283455b2b0b6 Mon Sep 17 00:00:00 2001 From: mark_story Date: Thu, 10 Mar 2016 22:02:34 -0500 Subject: [PATCH 36/38] Don't trust CLIENT_IP The client_ip header can easily be forged. In 'safe' modes we should only trust the remote_addr which comes from the sapi. Remove support for http_clientaddress as I can't seem to find where this ever came from in PHP on the http specs. --- lib/Cake/Network/CakeRequest.php | 16 +++------------- lib/Cake/Test/Case/Network/CakeRequestTest.php | 14 +++++++------- 2 files changed, 10 insertions(+), 20 deletions(-) diff --git a/lib/Cake/Network/CakeRequest.php b/lib/Cake/Network/CakeRequest.php index eb9cebd84..8bd2b3c50 100644 --- a/lib/Cake/Network/CakeRequest.php +++ b/lib/Cake/Network/CakeRequest.php @@ -417,20 +417,10 @@ class CakeRequest implements ArrayAccess { public function clientIp($safe = true) { if (!$safe && env('HTTP_X_FORWARDED_FOR')) { $ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR')); + } elseif (!$safe && env('HTTP_CLIENT_IP')) { + $ipaddr = env('HTTP_CLIENT_IP'); } else { - if (env('HTTP_CLIENT_IP')) { - $ipaddr = env('HTTP_CLIENT_IP'); - } else { - $ipaddr = env('REMOTE_ADDR'); - } - } - - if (env('HTTP_CLIENTADDRESS')) { - $tmpipaddr = env('HTTP_CLIENTADDRESS'); - - if (!empty($tmpipaddr)) { - $ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr); - } + $ipaddr = env('REMOTE_ADDR'); } return trim($ipaddr); } diff --git a/lib/Cake/Test/Case/Network/CakeRequestTest.php b/lib/Cake/Test/Case/Network/CakeRequestTest.php index 90f92c7bf..418ef6355 100644 --- a/lib/Cake/Test/Case/Network/CakeRequestTest.php +++ b/lib/Cake/Test/Case/Network/CakeRequestTest.php @@ -711,18 +711,18 @@ class CakeRequestTest extends CakeTestCase { $_SERVER['HTTP_X_FORWARDED_FOR'] = '192.168.1.5, 10.0.1.1, proxy.com'; $_SERVER['HTTP_CLIENT_IP'] = '192.168.1.2'; $_SERVER['REMOTE_ADDR'] = '192.168.1.3'; + $request = new CakeRequest('some/path'); - $this->assertEquals('192.168.1.5', $request->clientIp(false)); - $this->assertEquals('192.168.1.2', $request->clientIp()); + $this->assertEquals('192.168.1.3', $request->clientIp(), 'Use remote_addr in safe mode'); + $this->assertEquals('192.168.1.5', $request->clientIp(false), 'Use x-forwarded'); unset($_SERVER['HTTP_X_FORWARDED_FOR']); - $this->assertEquals('192.168.1.2', $request->clientIp()); + $this->assertEquals('192.168.1.3', $request->clientIp(), 'safe uses remote_addr'); + $this->assertEquals('192.168.1.2', $request->clientIp(false), 'unsafe reads from client_ip'); unset($_SERVER['HTTP_CLIENT_IP']); - $this->assertEquals('192.168.1.3', $request->clientIp()); - - $_SERVER['HTTP_CLIENTADDRESS'] = '10.0.1.2, 10.0.1.1'; - $this->assertEquals('10.0.1.2', $request->clientIp()); + $this->assertEquals('192.168.1.3', $request->clientIp(), 'use remote_addr'); + $this->assertEquals('192.168.1.3', $request->clientIp(false), 'use remote_addr'); } /** From fef3090717df8e033236bd1bb05b87f337e50a19 Mon Sep 17 00:00:00 2001 From: mark_story Date: Fri, 11 Mar 2016 23:18:08 -0500 Subject: [PATCH 37/38] Fix incorrectly inheriting permissions. When child inherits from a deny parent the '*' permission should reflect permissions on all nodes not just the leaf node. Previously once a node with all permissions set to inherit was found, the check would pass. Instead it should cascade to the parent nodes and look for explicit allow/deny. Refs #8450 --- lib/Cake/Model/Permission.php | 25 +++++++++++-------- .../Controller/Component/Acl/DbAclTest.php | 16 ++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lib/Cake/Model/Permission.php b/lib/Cake/Model/Permission.php index 303124b03..2883348e0 100644 --- a/lib/Cake/Model/Permission.php +++ b/lib/Cake/Model/Permission.php @@ -129,18 +129,17 @@ class Permission extends AppModel { $perms = Hash::extract($perms, '{n}.' . $this->alias); foreach ($perms as $perm) { if ($action === '*') { - foreach ($permKeys as $key) { - if (!empty($perm)) { - if ($perm[$key] == -1) { - return false; - } elseif ($perm[$key] == 1 || $perm[$key] == 0) { - $inherited[$key] = $perm[$key]; - } - } + if (empty($perm)) { + continue; } - - if (count($inherited) === count($permKeys)) { - return true; + foreach ($permKeys as $key) { + if ($perm[$key] == -1 && !(isset($inherited[$key]) && $inherited[$key] == 1)) { + // Deny, but only if a child node didnt't explicitly allow + return false; + } elseif ($perm[$key] == 1) { + // Allow & inherit from parent nodes + $inherited[$key] = $perm[$key]; + } } } else { switch ($perm['_' . $action]) { @@ -153,6 +152,10 @@ class Permission extends AppModel { } } } + + if ($action === '*' && count($inherited) === count($permKeys)) { + return true; + } } return false; } diff --git a/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php b/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php index 99eccfe03..03a431508 100644 --- a/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php +++ b/lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php @@ -452,6 +452,12 @@ class DbAclTest extends CakeTestCase { $this->Acl->Aco->create(array('parent_id' => $this->Acl->Aco->id, 'alias' => 'town')); $this->Acl->Aco->save(); + $this->Acl->Aco->create(array('parent_id' => null, 'alias' => 'bizzaro_world')); + $this->Acl->Aco->save(); + + $this->Acl->Aco->create(array('parent_id' => $this->Acl->Aco->id, 'alias' => 'bizzaro_town')); + $this->Acl->Aco->save(); + $this->Acl->Aro->create(array('parent_id' => null, 'alias' => 'Jane')); $this->Acl->Aro->save(); @@ -463,8 +469,18 @@ class DbAclTest extends CakeTestCase { $this->Acl->inherit('Jane', 'town', '*'); $this->Acl->allow('Jane', 'town', 'create'); + // Setup deny on create for parent + $this->Acl->deny('Jane', 'bizzaro_world', '*'); + $this->Acl->allow('Jane', 'bizzaro_world', 'create'); + + // Setup inherit. + $this->Acl->inherit('Jane', 'bizzaro_town', '*'); + $this->assertTrue($this->Acl->check('Jane', 'town', 'create'), 'Should have access due to override'); $this->assertTrue($this->Acl->check('Jane', 'town', '*'), 'Should have access due to inherit'); + + $this->assertTrue($this->Acl->check('Jane', 'bizzaro_town', 'create'), 'Should have access due explicit allow'); + $this->assertFalse($this->Acl->check('Jane', 'bizzaro_town', '*'), 'Should not have access due to inherit'); } /** From 22a2e93c4be27c28be41856dcb837cb5dd64dbce Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 13 Mar 2016 23:01:17 -0400 Subject: [PATCH 38/38] Update version number to 2.8.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 b3d9b643f..2eb940aac 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.8.1 +2.8.2