diff --git a/lib/Cake/Controller/Component/PaginatorComponent.php b/lib/Cake/Controller/Component/PaginatorComponent.php index dcefbe703..c7a0201dc 100644 --- a/lib/Cake/Controller/Component/PaginatorComponent.php +++ b/lib/Cake/Controller/Component/PaginatorComponent.php @@ -121,7 +121,8 @@ class PaginatorComponent extends Component { * @param Model|string $object Model to paginate (e.g: model instance, or 'Model', or 'Model.InnerModel') * @param string|array $scope Additional find conditions to use while paginating * @param array $whitelist List of allowed fields for ordering. This allows you to prevent ordering - * on non-indexed, or undesirable columns. + * on non-indexed, or undesirable columns. See PaginatorComponent::validateSort() for additional details + * on how the whitelisting and sort field validation works. * @return array Model query results * @throws MissingModelException * @throws NotFoundException @@ -351,6 +352,9 @@ class PaginatorComponent extends Component { * You can use the whitelist parameter to control which columns/fields are available for sorting. * This helps prevent users from ordering large result sets on un-indexed values. * + * Any columns listed in the sort whitelist will be implicitly trusted. You can use this to sort + * on synthetic columns, or columns added in custom find operations that may not exist in the schema. + * * @param Model $object The model being paginated. * @param array $options The pagination options being used for this request. * @param array $whitelist The list of columns that can be used for sorting. If empty all keys are allowed. @@ -370,10 +374,14 @@ class PaginatorComponent extends Component { if (!empty($whitelist) && isset($options['order']) && is_array($options['order'])) { $field = key($options['order']); - if (!in_array($field, $whitelist)) { + $inWhitelist = in_array($field, $whitelist, true); + if (!$inWhitelist) { $options['order'] = null; return $options; } + if ($inWhitelist) { + return $options; + } } if (!empty($options['order']) && is_array($options['order'])) { diff --git a/lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php b/lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php index 42778a494..df0cc9b21 100644 --- a/lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php +++ b/lib/Cake/Test/Case/Controller/Component/PaginatorComponentTest.php @@ -933,6 +933,23 @@ class PaginatorComponentTest extends CakeTestCase { $this->assertNull($result['order']); } +/** + * test that fields in the whitelist are not validated + * + * @return void + */ + public function testValidateSortWhitelistTrusted() { + $model = $this->getMock('Model'); + $model->alias = 'model'; + $model->expects($this->never())->method('hasField'); + + $options = array('sort' => 'body', 'direction' => 'asc'); + $result = $this->Paginator->validateSort($model, $options, array('body')); + + $expected = array('body' => 'asc'); + $this->assertEquals($expected, $result['order']); + } + /** * test that virtual fields work. *