Merge pull request #5 from cakephp/2.x

sync 2.x
This commit is contained in:
Val Bancer 2017-12-28 09:51:36 +01:00 committed by GitHub
commit 92caf71db5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 169 additions and 7 deletions

View file

@ -198,6 +198,7 @@
* *
* - `Session.cookie` - The name of the cookie to use. Defaults to 'CAKEPHP' * - `Session.cookie` - The name of the cookie to use. Defaults to 'CAKEPHP'
* - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP * - `Session.timeout` - The number of minutes you want sessions to live for. This timeout is handled by CakePHP
* - `Session.useForwardsCompatibleTimeout` - Whether or not to make timeout 3.x compatible.
* - `Session.cookieTimeout` - The number of minutes you want session cookies to live for. * - `Session.cookieTimeout` - The number of minutes you want session cookies to live for.
* - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the * - `Session.checkAgent` - Do you want the user agent to be checked when starting sessions? You might want to set the
* value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX * value to false, when dealing with older versions of IE, Chrome Frame or certain web-browsing devices and AJAX

View file

@ -298,6 +298,7 @@ class AuthComponent extends Component {
} }
if ($this->_isAllowed($controller)) { if ($this->_isAllowed($controller)) {
$this->_getUser();
return true; return true;
} }

View file

@ -1018,7 +1018,12 @@ class Controller extends CakeObject implements CakeEventListener {
} }
/** /**
* Converts POST'ed form data to a model conditions array, suitable for use in a Model::find() call. * Converts POST'ed form data to a model conditions array.
*
* If combined with SecurityComponent these conditions could be suitable
* for use in a Model::find() call. Without SecurityComponent this method
* is vulnerable creating conditions containing SQL injection. While we
* attempt to raise exceptions.
* *
* @param array $data POST'ed data organized by model and field * @param array $data POST'ed data organized by model and field
* @param string|array $op A string containing an SQL comparison operator, or an array matching operators * @param string|array $op A string containing an SQL comparison operator, or an array matching operators
@ -1028,6 +1033,7 @@ class Controller extends CakeObject implements CakeEventListener {
* included in the returned conditions * included in the returned conditions
* @return array|null An array of model conditions * @return array|null An array of model conditions
* @deprecated 3.0.0 Will be removed in 3.0. * @deprecated 3.0.0 Will be removed in 3.0.
* @throws RuntimeException when unsafe operators are found.
*/ */
public function postConditions($data = array(), $op = null, $bool = 'AND', $exclusive = false) { public function postConditions($data = array(), $op = null, $bool = 'AND', $exclusive = false) {
if (!is_array($data) || empty($data)) { if (!is_array($data) || empty($data)) {
@ -1043,9 +1049,16 @@ class Controller extends CakeObject implements CakeEventListener {
$op = ''; $op = '';
} }
$allowedChars = '#[^a-zA-Z0-9_ ]#';
$arrayOp = is_array($op); $arrayOp = is_array($op);
foreach ($data as $model => $fields) { foreach ($data as $model => $fields) {
if (preg_match($allowedChars, $model)) {
throw new RuntimeException("Unsafe operator found in {$model}");
}
foreach ($fields as $field => $value) { foreach ($fields as $field => $value) {
if (preg_match($allowedChars, $field)) {
throw new RuntimeException("Unsafe operator found in {$model}.{$field}");
}
$key = $model . '.' . $field; $key = $model . '.' . $field;
$fieldOp = $op; $fieldOp = $op;
if ($arrayOp) { if ($arrayOp) {

View file

@ -148,7 +148,7 @@ class CakeObject {
* Convenience method to write a message to CakeLog. See CakeLog::write() * Convenience method to write a message to CakeLog. See CakeLog::write()
* for more information on writing to logs. * for more information on writing to logs.
* *
* @param string $msg Log message * @param mixed $msg Log message
* @param int $type Error type constant. Defined in app/Config/core.php. * @param int $type Error type constant. Defined in app/Config/core.php.
* @param null|string|array $scope The scope(s) a log message is being created in. * @param null|string|array $scope The scope(s) a log message is being created in.
* See CakeLog::config() for more information on logging scopes. * See CakeLog::config() for more information on logging scopes.

View file

@ -134,6 +134,13 @@ class CakeSession {
*/ */
protected static $_cookieName = null; protected static $_cookieName = null;
/**
* Whether or not to make `_validAgentAndTime` 3.x compatible.
*
* @var bool
*/
protected static $_useForwardsCompatibleTimeout = false;
/** /**
* Whether this session is running under a CLI environment * Whether this session is running under a CLI environment
* *
@ -360,6 +367,9 @@ class CakeSession {
protected static function _validAgentAndTime() { protected static function _validAgentAndTime() {
$userAgent = static::read('Config.userAgent'); $userAgent = static::read('Config.userAgent');
$time = static::read('Config.time'); $time = static::read('Config.time');
if (static::$_useForwardsCompatibleTimeout) {
$time += (Configure::read('Session.timeout') * 60);
}
$validAgent = ( $validAgent = (
Configure::read('Session.checkAgent') === false || Configure::read('Session.checkAgent') === false ||
isset($userAgent) && static::$_userAgent === $userAgent isset($userAgent) && static::$_userAgent === $userAgent
@ -527,6 +537,10 @@ class CakeSession {
if (isset($sessionConfig['timeout']) && !isset($sessionConfig['cookieTimeout'])) { if (isset($sessionConfig['timeout']) && !isset($sessionConfig['cookieTimeout'])) {
$sessionConfig['cookieTimeout'] = $sessionConfig['timeout']; $sessionConfig['cookieTimeout'] = $sessionConfig['timeout'];
} }
if (isset($sessionConfig['useForwardsCompatibleTimeout']) && $sessionConfig['useForwardsCompatibleTimeout']) {
static::$_useForwardsCompatibleTimeout = true;
}
if (!isset($sessionConfig['ini']['session.cookie_lifetime'])) { if (!isset($sessionConfig['ini']['session.cookie_lifetime'])) {
$sessionConfig['ini']['session.cookie_lifetime'] = $sessionConfig['cookieTimeout'] * 60; $sessionConfig['ini']['session.cookie_lifetime'] = $sessionConfig['cookieTimeout'] * 60;
} }
@ -579,7 +593,10 @@ class CakeSession {
); );
} }
Configure::write('Session', $sessionConfig); Configure::write('Session', $sessionConfig);
static::$sessionTime = static::$time + ($sessionConfig['timeout'] * 60); static::$sessionTime = static::$time;
if (!static::$_useForwardsCompatibleTimeout) {
static::$sessionTime += ($sessionConfig['timeout'] * 60);
}
} }
/** /**

View file

@ -1695,6 +1695,8 @@ class Model extends CakeObject implements CakeEventListener {
* If an array, allows control of 'validate', 'callbacks' and 'counterCache' options. * If an array, allows control of 'validate', 'callbacks' and 'counterCache' options.
* See Model::save() for details of each options. * See Model::save() for details of each options.
* @return bool|array See Model::save() False on failure or an array of model data on success. * @return bool|array See Model::save() False on failure or an array of model data on success.
* @deprecated 3.0.0 To ease migration to the new major, do not use this method anymore.
* Stateful model usage will be removed. Use the existing save() methods instead.
* @see Model::save() * @see Model::save()
* @link https://book.cakephp.org/2.0/en/models/saving-your-data.html#model-savefield-string-fieldname-string-fieldvalue-validate-false * @link https://book.cakephp.org/2.0/en/models/saving-your-data.html#model-savefield-string-fieldname-string-fieldvalue-validate-false
*/ */
@ -3083,7 +3085,11 @@ class Model extends CakeObject implements CakeEventListener {
$query['order'] = $this->order; $query['order'] = $this->order;
} }
if (is_object($query['order'])) {
$query['order'] = array($query['order']);
} else {
$query['order'] = (array)$query['order']; $query['order'] = (array)$query['order'];
}
if ($query['callbacks'] === true || $query['callbacks'] === 'before') { if ($query['callbacks'] === true || $query['callbacks'] === 'before') {
$event = new CakeEvent('Model.beforeFind', $this, array($query)); $event = new CakeEvent('Model.beforeFind', $this, array($query));

View file

@ -439,7 +439,7 @@ class CakeRequest implements ArrayAccess {
if (!empty($ref) && !empty($base)) { if (!empty($ref) && !empty($base)) {
if ($local && strpos($ref, $base) === 0) { if ($local && strpos($ref, $base) === 0) {
$ref = substr($ref, strlen($base)); $ref = substr($ref, strlen($base));
if (empty($ref)) { if (!strlen($ref) || strpos($ref, '//') === 0) {
$ref = '/'; $ref = '/';
} }
if ($ref[0] !== '/') { if ($ref[0] !== '/') {

View file

@ -1818,4 +1818,38 @@ class AuthComponentTest extends CakeTestCase {
$this->assertEquals('/users/login', $this->Controller->testUrl); $this->assertEquals('/users/login', $this->Controller->testUrl);
} }
/**
* testStatelessAuthAllowedActionsRetrieveUser method
*
* @return void
*/
public function testStatelessAuthAllowedActionsRetrieveUser() {
if (CakeSession::id()) {
session_destroy();
CakeSession::$id = null;
}
$_SESSION = null;
$_SERVER['PHP_AUTH_USER'] = 'mariano';
$_SERVER['PHP_AUTH_PW'] = 'cake';
AuthComponent::$sessionKey = false;
$this->Controller->Auth->authenticate = array(
'Basic' => array('userModel' => 'AuthUser')
);
$this->Controller->request['action'] = 'add';
$this->Controller->Auth->initialize($this->Controller);
$this->Controller->Auth->allow();
$this->Controller->Auth->startup($this->Controller);
$expectedUser = array(
'id' => '1',
'username' => 'mariano',
'created' => '2007-03-17 01:16:23',
'updated' => '2007-03-17 01:18:31',
);
$this->assertEquals($expectedUser, $this->Controller->Auth->user());
}
} }

View file

@ -1177,6 +1177,48 @@ class ControllerTest extends CakeTestCase {
$this->assertSame($expected, $result); $this->assertSame($expected, $result);
} }
/**
* data provider for dangerous post conditions.
*
* @return array
*/
public function dangerousPostConditionsProvider() {
return array(
array(
array('Model' => array('field !=' => 1))
),
array(
array('Model' => array('field AND 1=1 OR' => 'thing'))
),
array(
array('Model' => array('field >' => 1))
),
array(
array('Model' => array('field OR RAND()' => 1))
),
array(
array('Posts' => array('id IS NULL union all select posts.* from posts where id; --' => 1))
),
array(
array('Post.id IS NULL; --' => array('id' => 1))
),
);
}
/**
* test postConditions raising an exception on unsafe keys.
*
* @expectedException RuntimeException
* @dataProvider dangerousPostConditionsProvider
* @return void
*/
public function testPostConditionsDangerous($data) {
$request = new CakeRequest('controller_posts/index');
$Controller = new Controller($request);
$Controller->postConditions($data);
}
/** /**
* testControllerHttpCodes method * testControllerHttpCodes method
* *

View file

@ -7423,7 +7423,7 @@ class ModelReadTest extends BaseModelTest {
} }
/** /**
* Test find(count) with Db::expression * Test find(count) with DboSource::expression
* *
* @return void * @return void
*/ */
@ -7445,6 +7445,38 @@ class ModelReadTest extends BaseModelTest {
$this->assertEquals(1, $result); $this->assertEquals(1, $result);
} }
/**
* Test 'order' with DboSource::expression
*/
public function testOrderWithDbExpressions() {
$this->loadFixtures('User');
$User = new User();
$results = $User->find('all', array(
'fields' => array('id'),
'recursive' => -1,
'order' => $this->db->expression('CASE id WHEN 4 THEN 0 ELSE id END'),
));
$expected = array(
array(
'User' => array('id' => 4),
),
array(
'User' => array('id' => 1),
),
array(
'User' => array('id' => 2),
),
array(
'User' => array('id' => 3),
),
);
$this->assertEquals($expected, $results);
}
/** /**
* testFindMagic method * testFindMagic method
* *

View file

@ -739,6 +739,9 @@ class CakeRequestTest extends CakeTestCase {
$result = $request->referer(); $result = $request->referer();
$this->assertSame($result, 'https://cakephp.org'); $this->assertSame($result, 'https://cakephp.org');
$result = $request->referer(true);
$this->assertSame('/', $result);
$_SERVER['HTTP_REFERER'] = ''; $_SERVER['HTTP_REFERER'] = '';
$result = $request->referer(); $result = $request->referer();
$this->assertSame($result, '/'); $this->assertSame($result, '/');
@ -751,6 +754,18 @@ class CakeRequestTest extends CakeTestCase {
$result = $request->referer(true); $result = $request->referer(true);
$this->assertSame($result, '/some/path'); $this->assertSame($result, '/some/path');
$_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '///cakephp.org/';
$result = $request->referer(true);
$this->assertSame('/', $result); // Avoid returning scheme-relative URLs.
$_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/0';
$result = $request->referer(true);
$this->assertSame('/0', $result);
$_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/';
$result = $request->referer(true);
$this->assertSame('/', $result);
$_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/some/path'; $_SERVER['HTTP_REFERER'] = Configure::read('App.fullBaseUrl') . '/some/path';
$result = $request->referer(false); $result = $request->referer(false);
$this->assertSame($result, Configure::read('App.fullBaseUrl') . '/some/path'); $this->assertSame($result, Configure::read('App.fullBaseUrl') . '/some/path');

View file

@ -38,6 +38,7 @@ class CakeHtmlReporter extends CakeBaseReporter {
$this->paintDocumentStart(); $this->paintDocumentStart();
$this->paintTestMenu(); $this->paintTestMenu();
echo "<ul class='tests'>\n"; echo "<ul class='tests'>\n";
ob_end_flush();
} }
/** /**

View file

@ -17,4 +17,4 @@
// @license https://opensource.org/licenses/mit-license.php MIT License // @license https://opensource.org/licenses/mit-license.php MIT License
// +--------------------------------------------------------------------------------------------+ // // +--------------------------------------------------------------------------------------------+ //
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
2.10.5 2.10.6