From aae0f762dd19c5bc2d171d7c8b06d63bebebe381 Mon Sep 17 00:00:00 2001 From: euromark Date: Wed, 4 Dec 2013 01:30:57 +0100 Subject: [PATCH 01/13] Collision free approach to resolve the DOM ID issue in a clean way. Fix to generation of ids for multiple checkboxes. Resolves ticket 4064. --- .../Test/Case/View/Helper/FormHelperTest.php | 126 +++++++++++++++++- lib/Cake/Test/Case/View/HelperTest.php | 10 ++ lib/Cake/View/Helper.php | 1 + lib/Cake/View/Helper/FormHelper.php | 39 +++++- 4 files changed, 173 insertions(+), 3 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index 5427dbdfd..bd90387e8 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -3222,8 +3222,8 @@ class FormHelperTest extends CakeTestCase { $expected = array( 'input' => array('type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField'), array('div' => array('class' => 'checkbox')), - array('input' => array('type' => 'checkbox', 'name' => 'data[Model][multi_field][]', 'value' => '1/2', 'id' => 'ModelMultiField12')), - array('label' => array('for' => 'ModelMultiField12')), + array('input' => array('type' => 'checkbox', 'name' => 'data[Model][multi_field][]', 'value' => '1/2', 'id' => 'ModelMultiField1/2')), + array('label' => array('for' => 'ModelMultiField1/2')), 'half', '/label', '/div', @@ -4150,6 +4150,50 @@ class FormHelperTest extends CakeTestCase { ); } +/** + * testDomIdSuffix method + * + * @return void + */ + public function testDomIdSuffix() { + $result = $this->Form->domIdSuffix('1 string with 1$-dollar signs'); + $this->assertEquals('1StringWith1$-dollarSigns', $result); + + $result = $this->Form->domIdSuffix(''); + $this->assertEquals('AbcX=FooY=Bar', $result); + + $result = $this->Form->domIdSuffix('1 string with 1$-dollar signs', 'xhtml'); + $this->assertEquals('1StringWith1-dollarSigns', $result); + + $result = $this->Form->domIdSuffix('', 'xhtml'); + $this->assertEquals('AbcXFooYBar', $result); + } + +/** + * testDomIdSuffixCollisionResolvement() + * + * @return void + */ + public function testDomIdSuffixCollisionResolvement() { + $result = $this->Form->domIdSuffix('a>b'); + $this->assertEquals('AB', $result); + + $result = $this->Form->domIdSuffix('aassertEquals('AB1', $result); + + $result = $this->Form->domIdSuffix('a\'b'); + $this->assertEquals('AB2', $result); + + $result = $this->Form->domIdSuffix('1 string with 1$-dollar', 'xhtml'); + $this->assertEquals('1StringWith1-dollar', $result); + + $result = $this->Form->domIdSuffix('1 string with 1€-dollar', 'xhtml'); + $this->assertEquals('1StringWith1-dollar1', $result); + + $result = $this->Form->domIdSuffix('1 string with 1$-dollar', 'xhtml'); + $this->assertEquals('1StringWith1-dollar2', $result); + } + /** * testSelect method * @@ -4998,6 +5042,84 @@ class FormHelperTest extends CakeTestCase { '/div' ); $this->assertTags($result, $expected); + + $result = $this->Form->select( + 'Model.multi_field', + array('a+' => 'first', 'a++' => 'second', 'a+++' => 'third'), + array('multiple' => 'checkbox') + ); + $expected = array( + 'input' => array( + 'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField' + ), + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a+', 'id' => 'ModelMultiFieldA+' + )), + array('label' => array('for' => 'ModelMultiFieldA+')), + 'first', + '/label', + '/div', + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a++', 'id' => 'ModelMultiFieldA++' + )), + array('label' => array('for' => 'ModelMultiFieldA++')), + 'second', + '/label', + '/div', + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a+++', 'id' => 'ModelMultiFieldA+++' + )), + array('label' => array('for' => 'ModelMultiFieldA+++')), + 'third', + '/label', + '/div' + ); + $this->assertTags($result, $expected); + + $result = $this->Form->select( + 'Model.multi_field', + array('a>b' => 'first', 'a 'second', 'a"b' => 'third'), + array('multiple' => 'checkbox') + ); + $expected = array( + 'input' => array( + 'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', 'id' => 'ModelMultiField' + ), + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a>b', 'id' => 'ModelMultiFieldAB2' + )), + array('label' => array('for' => 'ModelMultiFieldAB2')), + 'first', + '/label', + '/div', + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a<b', 'id' => 'ModelMultiFieldAB1' + )), + array('label' => array('for' => 'ModelMultiFieldAB1')), + 'second', + '/label', + '/div', + array('div' => array('class' => 'checkbox')), + array('input' => array( + 'type' => 'checkbox', 'name' => 'data[Model][multi_field][]', + 'value' => 'a"b', 'id' => 'ModelMultiFieldAB' + )), + array('label' => array('for' => 'ModelMultiFieldAB')), + 'third', + '/label', + '/div' + ); + $this->assertTags($result, $expected); } /** diff --git a/lib/Cake/Test/Case/View/HelperTest.php b/lib/Cake/Test/Case/View/HelperTest.php index a23ba83c3..2d5bbaa62 100644 --- a/lib/Cake/Test/Case/View/HelperTest.php +++ b/lib/Cake/Test/Case/View/HelperTest.php @@ -851,6 +851,16 @@ class HelperTest extends CakeTestCase { $this->assertEquals('&lt;script&gt;alert(document.cookie)&lt;/script&gt;', $result); } +/** + * testDomId method + * + * @return void + */ + public function testDomId() { + $result = $this->Helper->domId('Foo.bar'); + $this->assertEquals('FooBar', $result); + } + /** * testMultiDimensionalField method * diff --git a/lib/Cake/View/Helper.php b/lib/Cake/View/Helper.php index 5d38d9aa4..55fc2d12b 100644 --- a/lib/Cake/View/Helper.php +++ b/lib/Cake/View/Helper.php @@ -16,6 +16,7 @@ App::uses('Router', 'Routing'); App::uses('Hash', 'Utility'); +App::uses('Inflector', 'Utility'); /** * Abstract base class for all other Helpers in CakePHP. diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index db4b4cf79..4278aa1d1 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -17,6 +17,7 @@ App::uses('ClassRegistry', 'Utility'); App::uses('AppHelper', 'View/Helper'); App::uses('Hash', 'Utility'); +App::uses('Inflector', 'Utility'); /** * Form helper library. @@ -109,6 +110,13 @@ class FormHelper extends AppHelper { */ public $validationErrors = array(); +/** + * Holds already used DOM ID suffixes to avoid collisions with multiple form field elements. + * + * @var array + */ + protected $_domIdSuffixes = array(); + /** * Copies the validationErrors variable from the View object into this instance * @@ -2065,6 +2073,34 @@ class FormHelper extends AppHelper { return implode("\n", $select); } +/** + * Generates a valid DOM ID suffix from a string. + * Also avoids collisions when multiple values are coverted to the same suffix by + * appending a numeric value. + * + * For pre-HTML5 IDs only characters like a-z 0-9 - _ are valid. HTML5 doesn't have that + * limitation, but to avoid layout issues it still filters out some sensitive chars. + * + * @param string $value The value that should be transferred into a DOM ID suffix. + * @param string $type Doctype to use. Defaults to html5. Anything else will use limited chars. + * @return string DOM ID + */ + public function domIdSuffix($value, $type = 'html5') { + if ($type === 'html5') { + $value = str_replace(array('<', '>', ' ', '"', '\''), '_', $value); + } else { + $value = preg_replace('~[^\\pL\d-_]+~u', '_', $value); + } + $value = Inflector::camelize($value); + $count = 1; + $suffix = $value; + while (in_array($suffix, $this->_domIdSuffixes)) { + $suffix = $value . $count++; + } + $this->_domIdSuffixes[] = $suffix; + return $suffix; + } + /** * Returns a SELECT element for days. * @@ -2609,6 +2645,7 @@ class FormHelper extends AppHelper { $selectedIsEmpty = ($attributes['value'] === '' || $attributes['value'] === null); $selectedIsArray = is_array($attributes['value']); + $this->_domIdSuffixes = array(); foreach ($elements as $name => $title) { $htmlOptions = array(); if (is_array($title) && (!isset($title['name']) || !isset($title['value']))) { @@ -2677,7 +2714,7 @@ class FormHelper extends AppHelper { if ($attributes['style'] === 'checkbox') { $htmlOptions['value'] = $name; - $tagName = $attributes['id'] . Inflector::camelize(Inflector::slug($name)); + $tagName = $attributes['id'] . $this->domIdSuffix($name); $htmlOptions['id'] = $tagName; $label = array('for' => $tagName); From 587a04ab84f2ffeb5bff7ab06a7790bc201581ed Mon Sep 17 00:00:00 2001 From: euromark Date: Wed, 4 Dec 2013 01:51:39 +0100 Subject: [PATCH 02/13] prevent possible XSS attack via form helper selects and unescaped output. --- .../Test/Case/View/Helper/FormHelperTest.php | 28 +++++++++++++++++++ lib/Cake/View/Helper/FormHelper.php | 3 ++ 2 files changed, 31 insertions(+) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index bd90387e8..edc27ead4 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -4634,6 +4634,34 @@ class FormHelperTest extends CakeTestCase { '/select' ); $this->assertTags($result, $expected); + + $result = $this->Form->select( + 'Model.multi_field', + array('a>b' => 'first', 'a 'second', 'a"b' => 'third'), + array('multiple' => true) + ); + $expected = array( + 'input' => array( + 'type' => 'hidden', 'name' => 'data[Model][multi_field]', 'value' => '', + 'id' => 'ModelMultiField_' + ), + array('select' => array('name' => 'data[Model][multi_field][]', + 'multiple' => 'multiple', 'id' => 'ModelMultiField' + )), + array('option' => array('value' => 'a>b')), + 'first', + '/option', + array('option' => array('value' => 'a<b')), + 'second', + '/option', + array('option' => array( + 'value' => 'a"b' + )), + 'third', + '/option', + '/select' + ); + $this->assertTags($result, $expected); } /** diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 4278aa1d1..791f9a6e2 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -2733,6 +2733,9 @@ class FormHelper extends AppHelper { $item = $this->Html->useTag('checkboxmultiple', $name, $htmlOptions); $select[] = $this->Html->div($attributes['class'], $item . $label); } else { + if ($attributes['escape']) { + $name = h($name); + } $select[] = $this->Html->useTag('selectoption', $name, $htmlOptions, $title); } } From 8ebf004450778023924a70502c0537ba34ba6029 Mon Sep 17 00:00:00 2001 From: euromark Date: Wed, 4 Dec 2013 02:14:08 +0100 Subject: [PATCH 03/13] Also make DOM ids for radio element values unique. --- .../Test/Case/View/Helper/FormHelperTest.php | 36 +++++++++++++++++-- lib/Cake/View/Helper/FormHelper.php | 5 ++- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index edc27ead4..c323fd5d2 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -3503,8 +3503,8 @@ class FormHelperTest extends CakeTestCase { $result = $this->Form->radio('Model.field', array('1/2' => 'half')); $expected = array( 'input' => array('type' => 'hidden', 'name' => 'data[Model][field]', 'value' => '', 'id' => 'ModelField_'), - array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1/2', 'id' => 'ModelField12')), - 'label' => array('for' => 'ModelField12'), + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'value' => '1/2', 'id' => 'ModelField1/2')), + 'label' => array('for' => 'ModelField1/2'), 'half', '/label' ); @@ -3631,6 +3631,38 @@ class FormHelperTest extends CakeTestCase { '/fieldset' ); $this->assertTags($result, $expected); + + $result = $this->Form->radio( + 'Model.field', + array('a>b' => 'first', 'a 'second', 'a"b' => 'third') + ); + $expected = array( + 'fieldset' => array(), + 'legend' => array(), + 'Field', + '/legend', + 'input' => array( + 'type' => 'hidden', 'name' => 'data[Model][field]', + 'id' => 'ModelField_', 'value' => '', + ), + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', + 'id' => 'ModelFieldAB', 'value' => 'a>b')), + array('label' => array('for' => 'ModelFieldAB')), + 'first', + '/label', + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', + 'id' => 'ModelFieldAB1', 'value' => 'a<b')), + array('label' => array('for' => 'ModelFieldAB1')), + 'second', + '/label', + array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', + 'id' => 'ModelFieldAB2', 'value' => 'a"b')), + array('label' => array('for' => 'ModelFieldAB2')), + 'third', + '/label', + '/fieldset' + ); + $this->assertTags($result, $expected); } /** diff --git a/lib/Cake/View/Helper/FormHelper.php b/lib/Cake/View/Helper/FormHelper.php index 791f9a6e2..3592e40f7 100644 --- a/lib/Cake/View/Helper/FormHelper.php +++ b/lib/Cake/View/Helper/FormHelper.php @@ -1514,6 +1514,7 @@ class FormHelper extends AppHelper { $value = $value ? 1 : 0; } + $this->_domIdSuffixes = array(); foreach ($options as $optValue => $optTitle) { $optionsHere = array('value' => $optValue, 'disabled' => false); @@ -1524,9 +1525,7 @@ class FormHelper extends AppHelper { if ($disabled && (!is_array($disabled) || in_array((string)$optValue, $disabled, !$isNumeric))) { $optionsHere['disabled'] = true; } - $tagName = Inflector::camelize( - $attributes['id'] . '_' . Inflector::slug($optValue) - ); + $tagName = $attributes['id'] . $this->domIdSuffix($optValue); if ($label) { $labelOpts = is_array($label) ? $label : array(); From af9611d46067d6c8b5c98d4ac35ffbd56f191441 Mon Sep 17 00:00:00 2001 From: mark_story Date: Mon, 23 Dec 2013 21:44:46 -0500 Subject: [PATCH 04/13] Update version number to 2.4.4 --- 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 1a42d26e4..42fdb77b2 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.4.3 +2.4.4 From b392254c9211aa521f44f4a4b61bb5b11e4b2b81 Mon Sep 17 00:00:00 2001 From: euromark Date: Tue, 24 Dec 2013 15:20:32 +0100 Subject: [PATCH 05/13] fix cs --- lib/Cake/Test/Case/View/Helper/FormHelperTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php index c323fd5d2..212605a47 100644 --- a/lib/Cake/Test/Case/View/Helper/FormHelperTest.php +++ b/lib/Cake/Test/Case/View/Helper/FormHelperTest.php @@ -3643,7 +3643,7 @@ class FormHelperTest extends CakeTestCase { '/legend', 'input' => array( 'type' => 'hidden', 'name' => 'data[Model][field]', - 'id' => 'ModelField_', 'value' => '', + 'id' => 'ModelField_', 'value' => '', ), array('input' => array('type' => 'radio', 'name' => 'data[Model][field]', 'id' => 'ModelFieldAB', 'value' => 'a>b')), From 1daa27c0d7fb7b13bc178c189aac43240ea8d2a3 Mon Sep 17 00:00:00 2001 From: mark_story Date: Tue, 24 Dec 2013 13:12:39 -0500 Subject: [PATCH 06/13] Add tests for uncovered case of :0 replacements. There were previously no tests for the :0, :1 style replacement markers in DboSource. In fact I didn't even know it was a 'feature'. --- .../Model/Datasource/Database/MysqlTest.php | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php index 5f88c03f0..106ace594 100644 --- a/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php +++ b/lib/Cake/Test/Case/Model/Datasource/Database/MysqlTest.php @@ -2506,6 +2506,25 @@ class MysqlTest extends CakeTestCase { $this->assertEquals($expected, $result); } +/** + * test conditions() with replacements. + * + * @return void + */ + public function testConditionsWithReplacements() { + $result = $this->Dbo->conditions(array( + 'score BETWEEN :0 AND :1' => array(90.1, 95.7) + )); + $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; + $this->assertEquals($expected, $result); + + $result = $this->Dbo->conditions(array( + 'score BETWEEN ? AND ?' => array(90.1, 95.7) + )); + $expected = " WHERE `score` BETWEEN 90.1 AND 95.7"; + $this->assertEquals($expected, $result); + } + /** * Test that array conditions with only one element work. * From c48afae2dc8a3db3cdf5e600222e9ee39254ef61 Mon Sep 17 00:00:00 2001 From: Rachman Chavik Date: Fri, 27 Dec 2013 12:35:28 +0700 Subject: [PATCH 07/13] Add test to prove issue when saving invalid tree data --- .../Model/Behavior/TreeBehaviorScopedTest.php | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php b/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php index c7ea1fba2..5cf3e4cbf 100644 --- a/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php +++ b/lib/Cake/Test/Case/Model/Behavior/TreeBehaviorScopedTest.php @@ -130,6 +130,29 @@ class TreeBehaviorScopedTest extends CakeTestCase { $this->assertEquals(11, $this->Tree->find('count')); } +/** + * testSaveWithParentAndInvalidScope method + * + * Attempting to save an invalid data should not trigger an `Undefined offset` + * error + * + * @return void + */ + public function testSaveWithParentAndInvalidScope() { + $this->Tree = new FlagTree(); + $this->Tree->order = null; + $data = $this->Tree->create(array( + 'name' => 'Flag', + )); + $tree = $this->Tree->save($data); + $this->Tree->Behaviors->load('Tree', array( + 'scope' => array('FlagTree.flag' => 100) + )); + $tree['FlagTree']['parent_id'] = 1; + $result = $this->Tree->save($tree); + $this->assertFalse($result); + } + /** * testMoveUpWithScope method * From c4f8289b539143b3d112596eb26a8ac6f0086324 Mon Sep 17 00:00:00 2001 From: Rachman Chavik Date: Fri, 27 Dec 2013 12:37:39 +0700 Subject: [PATCH 08/13] Fix test by checking against an empty array instead of `false` --- lib/Cake/Model/Behavior/TreeBehavior.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Behavior/TreeBehavior.php b/lib/Cake/Model/Behavior/TreeBehavior.php index 9c09e0f91..ce64d6c0c 100644 --- a/lib/Cake/Model/Behavior/TreeBehavior.php +++ b/lib/Cake/Model/Behavior/TreeBehavior.php @@ -212,7 +212,7 @@ class TreeBehavior extends ModelBehavior { 'fields' => array($Model->primaryKey, $parent, $left, $right), 'recursive' => $recursive) ); - if ($values === false) { + if (empty($values)) { return false; } list($node) = array_values($values); From c86f9ab3e5f214b8cfbdcd0e03721b34720c3934 Mon Sep 17 00:00:00 2001 From: Jose Diaz-Gonzalez Date: Sat, 28 Dec 2013 18:24:22 -0500 Subject: [PATCH 09/13] Added composer.json for CakePHP 2.x --- composer.json | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 composer.json diff --git a/composer.json b/composer.json new file mode 100644 index 000000000..b0e05dc98 --- /dev/null +++ b/composer.json @@ -0,0 +1,32 @@ +{ + "name": "cakephp/cakephp", + "description": "The CakePHP framework", + "type": "library", + "keywords": ["framework"], + "homepage": "http://cakephp.org", + "license": "MIT", + "authors": [ + { + "name": "CakePHP Community", + "homepage": "https://github.com/cakephp/cakephp/graphs/contributors" + } + ], + "support": { + "issues": "https://github.com/cakephp/cakephp/issues", + "forum": "http://stackoverflow.com/tags/cakephp", + "irc": "irc://irc.freenode.org/cakephp", + "source": "https://github.com/cakephp/cakephp" + }, + "require": { + "php": ">=5.2.8", + "ext-mcrypt": "*", + "ext-mbstring": "*" + }, + "require-dev": { + "phpunit/phpunit": "3.7.*", + "cakephp/debug_kit" : "2.2.*" + }, + "bin": [ + "lib/Cake/Console/cake" + ] +} From 2f02d0c755fd35130924d2f2d460c4f63095e194 Mon Sep 17 00:00:00 2001 From: euromark Date: Mon, 30 Dec 2013 01:19:09 +0100 Subject: [PATCH 10/13] Add missing pkpass mimetype --- lib/Cake/Network/CakeResponse.php | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/Cake/Network/CakeResponse.php b/lib/Cake/Network/CakeResponse.php index e8b14fb8a..3ed93bcbd 100644 --- a/lib/Cake/Network/CakeResponse.php +++ b/lib/Cake/Network/CakeResponse.php @@ -299,6 +299,7 @@ class CakeResponse { 'vcf' => 'text/x-vcard', 'vtt' => 'text/vtt', 'mkv' => 'video/x-matroska', + 'pkpass' => 'application/vnd.apple.pkpass' ); /** From ed749fdc97788d4f0b7e8b6b457a61d8ef495cae Mon Sep 17 00:00:00 2001 From: Stephen Cuppett Date: Sun, 29 Dec 2013 21:43:56 -0500 Subject: [PATCH 11/13] Must double quote the schema name in query Schema names with reserved words such as "create" will fail this query without double quotes. Attempted prepared statement with ? placeholder. This failed with the following CakePHP error: Error: A Database connection using "Postgres" was missing or unable to connect. The database server returned this error: SQLSTATE[42601]: Syntax error: 7 ERROR: syntax error at or near "$1" LINE 1: SET search_path TO $1 ^ --- lib/Cake/Model/Datasource/Database/Postgres.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Cake/Model/Datasource/Database/Postgres.php b/lib/Cake/Model/Datasource/Database/Postgres.php index a71eeba28..9d299a133 100644 --- a/lib/Cake/Model/Datasource/Database/Postgres.php +++ b/lib/Cake/Model/Datasource/Database/Postgres.php @@ -127,7 +127,7 @@ class Postgres extends DboSource { $this->setEncoding($config['encoding']); } if (!empty($config['schema'])) { - $this->_execute('SET search_path TO ' . $config['schema']); + $this->_execute('SET search_path TO "' . $config['schema'] . '"'); } if (!empty($config['settings'])) { foreach ($config['settings'] as $key => $value) { From 85d72443b6aba2f353ccc3510573e80864671daf Mon Sep 17 00:00:00 2001 From: mark_story Date: Sun, 29 Dec 2013 23:49:17 -0500 Subject: [PATCH 12/13] Remove ext-mbstring dependency. mbstring is not a hard dependency for 2.x. The Multibyte class can shim up the missing extension. Refs #2564 --- composer.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/composer.json b/composer.json index b0e05dc98..59646d5e4 100644 --- a/composer.json +++ b/composer.json @@ -19,8 +19,7 @@ }, "require": { "php": ">=5.2.8", - "ext-mcrypt": "*", - "ext-mbstring": "*" + "ext-mcrypt": "*" }, "require-dev": { "phpunit/phpunit": "3.7.*", From 49bb441cefa648f2f20587fe6dd854ac66ac21e1 Mon Sep 17 00:00:00 2001 From: Bryan Crowe Date: Mon, 30 Dec 2013 00:13:26 -0500 Subject: [PATCH 13/13] Update some grammar in Controller --- lib/Cake/Controller/Controller.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Cake/Controller/Controller.php b/lib/Cake/Controller/Controller.php index b0e4e0b54..63f0396ac 100644 --- a/lib/Cake/Controller/Controller.php +++ b/lib/Cake/Controller/Controller.php @@ -29,7 +29,7 @@ App::uses('CakeEventManager', 'Event'); * * Controllers should provide a number of 'action' methods. These are public methods on the controller * that are not prefixed with a '_' and not part of Controller. Each action serves as an endpoint for - * performing a specific action on a resource or collection of resources. For example adding or editing a new + * performing a specific action on a resource or collection of resources. For example: adding or editing a new * object, or listing a set of objects. * * You can access request parameters, using `$this->request`. The request object contains all the POST, GET and FILES @@ -259,7 +259,7 @@ class Controller extends Object implements CakeEventListener { /** * Holds current methods of the controller. This is a list of all the methods reachable - * via URL. Modifying this array, will allow you to change which methods can be reached. + * via URL. Modifying this array will allow you to change which methods can be reached. * * @var array */ @@ -285,7 +285,7 @@ class Controller extends Object implements CakeEventListener { public $modelKey = null; /** - * Holds any validation errors produced by the last call of the validateErrors() method/ + * Holds any validation errors produced by the last call of the validateErrors() method. * * @var array Validation errors, or false if none */ @@ -610,7 +610,7 @@ class Controller extends Object implements CakeEventListener { } /** - * Returns a list of all events that will fire in the controller during it's lifecycle. + * Returns a list of all events that will fire in the controller during its lifecycle. * You can override this function to add you own listener callbacks * * @return array