Merge branch '2.x' into 2.next

This commit is contained in:
mark_story 2016-12-13 22:48:44 -05:00
commit 837741db66
33 changed files with 575 additions and 56 deletions

View file

@ -6,6 +6,7 @@ php:
- 5.5 - 5.5
- 5.6 - 5.6
- 7.0 - 7.0
- 7.1
env: env:
- DB=mysql - DB=mysql
@ -22,7 +23,7 @@ matrix:
- php: 5.4 - php: 5.4
env: DB=sqlite env: DB=sqlite
- php: 5.4 - php: 7.0
env: PHPCS=1 env: PHPCS=1

View file

@ -41,8 +41,9 @@ class PagesController extends AppController {
* Displays a view * Displays a view
* *
* @return void * @return void
* @throws ForbiddenException When a directory traversal attempt.
* @throws NotFoundException When the view file could not be found * @throws NotFoundException When the view file could not be found
* or MissingViewException in debug mode. * or MissingViewException in debug mode.
*/ */
public function display() { public function display() {
$path = func_get_args(); $path = func_get_args();
@ -51,6 +52,9 @@ class PagesController extends AppController {
if (!$count) { if (!$count) {
return $this->redirect('/'); return $this->redirect('/');
} }
if (in_array('..', $path, true) || in_array('.', $path, true)) {
throw new ForbiddenException();
}
$page = $subpage = $title_for_layout = null; $page = $subpage = $title_for_layout = null;
if (!empty($path[0])) { if (!empty($path[0])) {

View file

@ -9,4 +9,4 @@ build.dir = build
dist.dir = dist dist.dir = dist
# Server # Server
pirum.dir = /home/cakephp/www-live/pear.cakephp.org pirum.dir = /var/lib/dokku/data/storage/pear

View file

@ -213,10 +213,10 @@
--> -->
<target name="distribute" depends="prepare" description="Upload pear packages to pear.cakephp.org"> <target name="distribute" depends="prepare" description="Upload pear packages to pear.cakephp.org">
<echo msg="Uploading tgz file to cakephp.org" /> <echo msg="Uploading tgz file to cakephp.org" />
<exec command="scp ${dist.dir}/${pear.package}.tgz cakephp@pear.cakephp.org:${pirum.dir}" dir="." checkreturn="true" /> <exec command="scp ${dist.dir}/${pear.package}.tgz root@new.cakephp.org:${pirum.dir}" dir="." checkreturn="true" />
<echo msg="Adding new release to pirum" /> <echo msg="Rebuilding pear.cakephp.org container" />
<exec command="ssh cakephp@pear.cakephp.org pirum add ${pirum.dir} ${pirum.dir}/${pear.package}.tgz" checkreturn="true" /> <exec command="ssh root@new.cakephp.org dokku ps:rebuild pear" checkreturn="true" />
</target> </target>
<target name="codestyle" description="Check codestyle (human readable format)"> <target name="codestyle" description="Check codestyle (human readable format)">

View file

@ -616,4 +616,18 @@ class Cache {
self::set(null, $config); self::set(null, $config);
return $success; return $success;
} }
/**
* Fetch the engine attached to a specific configuration name.
*
* @param string $config Optional string configuration name to get an engine for. Defaults to 'default'.
* @return null|CacheEngine Null if the engine has not been initialized or the engine.
*/
public static function engine($config = 'default') {
if (self::isInitialized($config)) {
return self::$_engines[$config];
}
return null;
}
} }

View file

@ -54,6 +54,7 @@ class CommandListShell extends AppShell {
$this->out(" -working: " . rtrim(APP, DS)); $this->out(" -working: " . rtrim(APP, DS));
$this->out(" -root: " . rtrim(ROOT, DS)); $this->out(" -root: " . rtrim(ROOT, DS));
$this->out(" -core: " . rtrim(CORE_PATH, DS)); $this->out(" -core: " . rtrim(CORE_PATH, DS));
$this->out(" -webroot: " . rtrim(WWW_ROOT, DS));
$this->out(""); $this->out("");
$this->out(__d('cake_console', "<info>Changing Paths:</info>"), 2); $this->out(__d('cake_console', "<info>Changing Paths:</info>"), 2);
$this->out(__d('cake_console', "Your working path should be the same as your application path. To change your path use the '-app' param.")); $this->out(__d('cake_console', "Your working path should be the same as your application path. To change your path use the '-app' param."));

View file

@ -129,12 +129,19 @@ class ShellDispatcher {
define('APP', $this->params['working'] . DS); define('APP', $this->params['working'] . DS);
} }
if (!defined('WWW_ROOT')) { if (!defined('WWW_ROOT')) {
define('WWW_ROOT', APP . $this->params['webroot'] . DS); if (!$this->_isAbsolutePath($this->params['webroot'])) {
$webroot = realpath(APP . $this->params['webroot']);
} else {
$webroot = $this->params['webroot'];
}
define('WWW_ROOT', $webroot . DS);
} }
if (!defined('TMP') && !is_dir(APP . 'tmp')) { if (!defined('TMP') && !is_dir(APP . 'tmp')) {
define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS); define('TMP', CAKE_CORE_INCLUDE_PATH . DS . 'Cake' . DS . 'Console' . DS . 'Templates' . DS . 'skel' . DS . 'tmp' . DS);
} }
// $boot is used by Cake/bootstrap.php file
$boot = file_exists(ROOT . DS . APP_DIR . DS . 'Config' . DS . 'bootstrap.php');
require CORE_PATH . 'Cake' . DS . 'bootstrap.php'; require CORE_PATH . 'Cake' . DS . 'bootstrap.php';
if (!file_exists(APP . 'Config' . DS . 'core.php')) { if (!file_exists(APP . 'Config' . DS . 'core.php')) {
@ -305,25 +312,45 @@ class ShellDispatcher {
} }
} }
if ($params['app'][0] === '/' || preg_match('/([a-z])(:)/i', $params['app'], $matches)) { if ($this->_isAbsolutePath($params['app'])) {
$params['root'] = dirname($params['app']); $params['root'] = dirname($params['app']);
} elseif (strpos($params['app'], '/')) { } elseif (strpos($params['app'], '/')) {
$params['root'] .= '/' . dirname($params['app']); $params['root'] .= '/' . dirname($params['app']);
} }
$isWindowsAppPath = $this->_isWindowsPath($params['app']);
$params['app'] = basename($params['app']); $params['app'] = basename($params['app']);
$params['working'] = rtrim($params['root'], '/'); $params['working'] = rtrim($params['root'], '/');
if (!$isWin || !preg_match('/^[A-Z]:$/i', $params['app'])) { if (!$isWin || !preg_match('/^[A-Z]:$/i', $params['app'])) {
$params['working'] .= '/' . $params['app']; $params['working'] .= '/' . $params['app'];
} }
if (!empty($matches[0]) || !empty($isWin)) { if ($isWindowsAppPath || !empty($isWin)) {
$params = str_replace('/', '\\', $params); $params = str_replace('/', '\\', $params);
} }
$this->params = $params + $this->params; $this->params = $params + $this->params;
} }
/**
* Checks whether the given path is absolute or relative.
*
* @param string $path absolute or relative path.
* @return bool
*/
protected function _isAbsolutePath($path) {
return $path[0] === '/' || $this->_isWindowsPath($path);
}
/**
* Checks whether the given path is Window OS path.
*
* @param string $path absolute path.
* @return bool
*/
protected function _isWindowsPath($path) {
return preg_match('/([a-z])(:)/i', $path) == 1;
}
/** /**
* Parses out the paths from from the argv * Parses out the paths from from the argv
* *
@ -332,7 +359,7 @@ class ShellDispatcher {
*/ */
protected function _parsePaths($args) { protected function _parsePaths($args) {
$parsed = array(); $parsed = array();
$keys = array('-working', '--working', '-app', '--app', '-root', '--root'); $keys = array('-working', '--working', '-app', '--app', '-root', '--root', '-webroot', '--webroot');
$args = (array)$args; $args = (array)$args;
foreach ($keys as $key) { foreach ($keys as $key) {
while (($index = array_search($key, $args)) !== false) { while (($index = array_search($key, $args)) !== false) {

View file

@ -32,6 +32,7 @@ class PagesController extends AppController {
* Displays a view * Displays a view
* *
* @return void * @return void
* @throws ForbiddenException When a directory traversal attempt.
* @throws NotFoundException When the view file could not be found * @throws NotFoundException When the view file could not be found
* or MissingViewException in debug mode. * or MissingViewException in debug mode.
*/ */
@ -42,6 +43,9 @@ class PagesController extends AppController {
if (!$count) { if (!$count) {
return $this->redirect('/'); return $this->redirect('/');
} }
if (in_array('..', $path, true) || in_array('.', $path, true)) {
throw new ForbiddenException();
}
$page = $subpage = $title_for_layout = null; $page = $subpage = $title_for_layout = null;
if (!empty($path[0])) { if (!empty($path[0])) {

View file

@ -741,7 +741,7 @@ class AuthComponent extends Component {
$this->Session->delete('Auth.redirect'); $this->Session->delete('Auth.redirect');
if (Router::normalize($redir) === Router::normalize($this->loginAction)) { if (Router::normalize($redir) === Router::normalize($this->loginAction)) {
$redir = $this->loginRedirect; $redir = $this->loginRedirect ?: '/';
} }
} elseif ($this->loginRedirect) { } elseif ($this->loginRedirect) {
$redir = $this->loginRedirect; $redir = $this->loginRedirect;

View file

@ -283,8 +283,11 @@ class CookieComponent extends Component {
return null; return null;
} }
if (!empty($names[1]) && is_array($this->_values[$this->name][$key])) { if (!empty($names[1])) {
return Hash::get($this->_values[$this->name][$key], $names[1]); if (is_array($this->_values[$this->name][$key])) {
return Hash::get($this->_values[$this->name][$key], $names[1]);
}
return null;
} }
return $this->_values[$this->name][$key]; return $this->_values[$this->name][$key];
} }
@ -336,7 +339,7 @@ class CookieComponent extends Component {
return; return;
} }
$names = explode('.', $key, 2); $names = explode('.', $key, 2);
if (isset($this->_values[$this->name][$names[0]])) { if (isset($this->_values[$this->name][$names[0]]) && is_array($this->_values[$this->name][$names[0]])) {
$this->_values[$this->name][$names[0]] = Hash::remove($this->_values[$this->name][$names[0]], $names[1]); $this->_values[$this->name][$names[0]] = Hash::remove($this->_values[$this->name][$names[0]], $names[1]);
} }
$this->_delete('[' . implode('][', $names) . ']'); $this->_delete('[' . implode('][', $names) . ']');

View file

@ -269,6 +269,7 @@ class L10n {
'hi' => array('language' => 'Hindi', 'locale' => 'hin', 'localeFallback' => 'hin', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hi' => array('language' => 'Hindi', 'locale' => 'hin', 'localeFallback' => 'hin', 'charset' => 'utf-8', 'direction' => 'ltr'),
'hr' => array('language' => 'Croatian', 'locale' => 'hrv', 'localeFallback' => 'hrv', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hr' => array('language' => 'Croatian', 'locale' => 'hrv', 'localeFallback' => 'hrv', 'charset' => 'utf-8', 'direction' => 'ltr'),
'hu' => array('language' => 'Hungarian', 'locale' => 'hun', 'localeFallback' => 'hun', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hu' => array('language' => 'Hungarian', 'locale' => 'hun', 'localeFallback' => 'hun', 'charset' => 'utf-8', 'direction' => 'ltr'),
'hu-hu' => array('language' => 'Hungarian (Hungary)', 'locale' => 'hun', 'localeFallback' => 'hun', 'charset' => 'utf-8', 'direction' => 'ltr'),
'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr'), 'hy' => array('language' => 'Armenian - Armenia', 'locale' => 'hye', 'localeFallback' => 'hye', 'charset' => 'utf-8', 'direction' => 'ltr'),
'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'), 'id' => array('language' => 'Indonesian', 'locale' => 'ind', 'localeFallback' => 'ind', 'charset' => 'utf-8', 'direction' => 'ltr'),
'is' => array('language' => 'Icelandic', 'locale' => 'isl', 'localeFallback' => 'isl', 'charset' => 'utf-8', 'direction' => 'ltr'), 'is' => array('language' => 'Icelandic', 'locale' => 'isl', 'localeFallback' => 'isl', 'charset' => 'utf-8', 'direction' => 'ltr'),
@ -286,6 +287,7 @@ class L10n {
'li' => array('language' => 'Limburgish', 'locale' => 'lim', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'), 'li' => array('language' => 'Limburgish', 'locale' => 'lim', 'localeFallback' => 'nld', 'charset' => 'utf-8', 'direction' => 'ltr'),
'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr'), 'lt' => array('language' => 'Lithuanian', 'locale' => 'lit', 'localeFallback' => 'lit', 'charset' => 'utf-8', 'direction' => 'ltr'),
'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'), 'lv' => array('language' => 'Latvian', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'),
'lv-lv' => array('language' => 'Latvian (Latvia)', 'locale' => 'lav', 'localeFallback' => 'lav', 'charset' => 'utf-8', 'direction' => 'ltr'),
'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mkd', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mk' => array('language' => 'FYRO Macedonian', 'locale' => 'mkd', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'),
'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'), 'mk-mk' => array('language' => 'Macedonian', 'locale' => 'mk_mk', 'localeFallback' => 'mkd', 'charset' => 'utf-8', 'direction' => 'ltr'),
'ms' => array('language' => 'Malaysian', 'locale' => 'msa', 'localeFallback' => 'msa', 'charset' => 'utf-8', 'direction' => 'ltr'), 'ms' => array('language' => 'Malaysian', 'locale' => 'msa', 'localeFallback' => 'msa', 'charset' => 'utf-8', 'direction' => 'ltr'),

View file

@ -39,13 +39,18 @@ class AclNode extends Model {
/** /**
* Constructor * Constructor
*
* @param bool|int|string|array $id Set this ID for this model on startup,
* can also be an array of options, see above.
* @param string $table Name of database table to use.
* @param string $ds DataSource connection name.
*/ */
public function __construct() { public function __construct($id = false, $table = null, $ds = null) {
$config = Configure::read('Acl.database'); $config = Configure::read('Acl.database');
if (isset($config)) { if (isset($config)) {
$this->useDbConfig = $config; $this->useDbConfig = $config;
} }
parent::__construct(); parent::__construct($id, $table, $ds);
} }
/** /**

View file

@ -112,11 +112,12 @@ class TreeBehavior extends ModelBehavior {
* @return void * @return void
*/ */
protected function _setChildrenLevel(Model $Model, $id) { protected function _setChildrenLevel(Model $Model, $id) {
$settings = $Model->Behaviors->Tree->settings[$Model->alias]; $settings = $this->settings[$Model->alias];
$primaryKey = $Model->primaryKey; $primaryKey = $Model->primaryKey;
$depths = array($id => (int)$Model->data[$Model->alias][$settings['level']]); $depths = array($id => (int)$Model->data[$Model->alias][$settings['level']]);
$children = $Model->children( $children = $this->children(
$Model,
$id, $id,
false, false,
array($primaryKey, $settings['parent'], $settings['level']), array($primaryKey, $settings['parent'], $settings['level']),

View file

@ -51,17 +51,19 @@ class DboSource extends DataSource {
public $alias = 'AS '; public $alias = 'AS ';
/** /**
* Caches result from query parsing operations. Cached results for both DboSource::name() and * Caches result from query parsing operations. Cached results for both DboSource::name() and DboSource::fields()
* DboSource::conditions() will be stored here. Method caching uses `md5()`. If you have * will be stored here.
* problems with collisions, set DboSource::$cacheMethods to false. *
* Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions,
* try a different hashing algorithm by overriding DboSource::cacheMethodHasher or set DboSource::$cacheMethods to false.
* *
* @var array * @var array
*/ */
public static $methodCache = array(); public static $methodCache = array();
/** /**
* Whether or not to cache the results of DboSource::name() and DboSource::conditions() * Whether or not to cache the results of DboSource::name() and DboSource::fields() into the memory cache.
* into the memory cache. Set to false to disable the use of the memory cache. * Set to false to disable the use of the memory cache.
* *
* @var bool * @var bool
*/ */
@ -786,10 +788,72 @@ class DboSource extends DataSource {
if ($value === null) { if ($value === null) {
return (isset(static::$methodCache[$method][$key])) ? static::$methodCache[$method][$key] : null; return (isset(static::$methodCache[$method][$key])) ? static::$methodCache[$method][$key] : null;
} }
if (!$this->cacheMethodFilter($method, $key, $value)) {
return $value;
}
$this->_methodCacheChange = true; $this->_methodCacheChange = true;
return static::$methodCache[$method][$key] = $value; return static::$methodCache[$method][$key] = $value;
} }
/**
* Filters to apply to the results of `name` and `fields`. When the filter for a given method does not return `true`
* then the result is not added to the memory cache.
*
* Some examples:
*
* ```
* // For method fields, do not cache values that contain floats
* if ($method === 'fields') {
* $hasFloat = preg_grep('/(\d+)?\.\d+/', $value);
*
* return count($hasFloat) === 0;
* }
*
* return true;
* ```
*
* ```
* // For method name, do not cache values that have the name created
* if ($method === 'name') {
* return preg_match('/^`created`$/', $value) !== 1;
* }
*
* return true;
* ```
*
* ```
* // For method name, do not cache values that have the key 472551d38e1f8bbc78d7dfd28106166f
* if ($key === '472551d38e1f8bbc78d7dfd28106166f') {
* return false;
* }
*
* return true;
* ```
*
* @param string $method Name of the method being cached.
* @param string $key The key name for the cache operation.
* @param mixed $value The value to cache into memory.
* @return bool Whether or not to cache
*/
public function cacheMethodFilter($method, $key, $value) {
return true;
}
/**
* Hashes a given value.
*
* Method caching uses `md5` (by default) to construct cache keys. If you have problems with collisions,
* try a different hashing algorithm or set DboSource::$cacheMethods to false.
*
* @param string $value Value to hash
* @return string Hashed value
* @see http://php.net/manual/en/function.hash-algos.php
* @see http://softwareengineering.stackexchange.com/questions/49550/which-hashing-algorithm-is-best-for-uniqueness-and-speed
*/
public function cacheMethodHasher($value) {
return md5($value);
}
/** /**
* Returns a quoted name of $data for use in an SQL statement. * Returns a quoted name of $data for use in an SQL statement.
* Strips fields out of SQL functions before quoting. * Strips fields out of SQL functions before quoting.
@ -815,7 +879,7 @@ class DboSource extends DataSource {
} }
return $data; return $data;
} }
$cacheKey = md5($this->startQuote . $data . $this->endQuote); $cacheKey = $this->cacheMethodHasher($this->startQuote . $data . $this->endQuote);
if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) {
return $return; return $return;
} }
@ -2533,7 +2597,7 @@ class DboSource extends DataSource {
$Model->schemaName, $Model->schemaName,
$Model->table $Model->table
); );
$cacheKey = md5(serialize($cacheKey)); $cacheKey = $this->cacheMethodHasher(serialize($cacheKey));
if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) { if ($return = $this->cacheMethod(__FUNCTION__, $cacheKey)) {
return $return; return $return;
} }

View file

@ -538,4 +538,65 @@ class CacheTest extends CakeTestCase {
$result = Cache::add('test_add_key', 'test data 2', 'default'); $result = Cache::add('test_add_key', 'test data 2', 'default');
$this->assertFalse($result); $this->assertFalse($result);
} }
/**
* Test engine method.
*
* Success, default engine.
*
* @return void
*/
public function testEngineSuccess() {
$actual = Cache::engine();
$this->assertInstanceOf('CacheEngine', $actual);
$actual = Cache::engine('default');
$this->assertInstanceOf('CacheEngine', $actual);
}
/**
* Test engine method.
*
* Success, memcached engine.
*
* @return void
*/
public function testEngineSuccessMemcached() {
$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_',
'duration' => 3600
));
$actual = Cache::engine('memcached');
$this->assertInstanceOf('MemcachedEngine', $actual);
$this->assertTrue($actual->add('test_add_key', 'test data', 10));
$this->assertFalse($actual->add('test_add_key', 'test data', 10));
$this->assertTrue($actual->delete('test_add_key'));
}
/**
* Test engine method.
*
* Failure.
*
* @return void
*/
public function testEngineFailure() {
$actual = Cache::engine('some_config_that_does_not_exist');
$this->assertNull($actual);
Configure::write('Cache.disable', true);
$actual = Cache::engine();
$this->assertNull($actual);
}
} }

View file

@ -137,9 +137,8 @@ class ShellDispatcherTest extends CakeTestCase {
* *
* @return void * @return void
*/ */
public function testParseParams() { public function testParseParamsAppWorkingAbsolute() {
$Dispatcher = new TestShellDispatcher(); $Dispatcher = new TestShellDispatcher();
$params = array( $params = array(
'/cake/1.2.x.x/cake/console/cake.php', '/cake/1.2.x.x/cake/console/cake.php',
'bake', 'bake',
@ -156,7 +155,15 @@ class ShellDispatcherTest extends CakeTestCase {
); );
$Dispatcher->parseParams($params); $Dispatcher->parseParams($params);
$this->assertEquals($expected, $Dispatcher->params); $this->assertEquals($expected, $Dispatcher->params);
}
/**
* testParseParams method
*
* @return void
*/
public function testParseParamsNone() {
$Dispatcher = new TestShellDispatcher();
$params = array('cake.php'); $params = array('cake.php');
$expected = array( $expected = array(
'app' => 'app', 'app' => 'app',
@ -167,7 +174,15 @@ class ShellDispatcherTest extends CakeTestCase {
$Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->params = $Dispatcher->args = array();
$Dispatcher->parseParams($params); $Dispatcher->parseParams($params);
$this->assertEquals($expected, $Dispatcher->params); $this->assertEquals($expected, $Dispatcher->params);
}
/**
* testParseParams method
*
* @return void
*/
public function testParseParamsApp() {
$Dispatcher = new TestShellDispatcher();
$params = array( $params = array(
'cake.php', 'cake.php',
'-app', '-app',
@ -182,7 +197,15 @@ class ShellDispatcherTest extends CakeTestCase {
$Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->params = $Dispatcher->args = array();
$Dispatcher->parseParams($params); $Dispatcher->parseParams($params);
$this->assertEquals($expected, $Dispatcher->params); $this->assertEquals($expected, $Dispatcher->params);
}
/**
* testParseParams method
*
* @return void
*/
public function testParseParamsAppWorkingRelative() {
$Dispatcher = new TestShellDispatcher();
$params = array( $params = array(
'./cake.php', './cake.php',
'bake', 'bake',
@ -191,17 +214,24 @@ class ShellDispatcherTest extends CakeTestCase {
'-working', '-working',
'/cake/1.2.x.x/cake/console' '/cake/1.2.x.x/cake/console'
); );
$expected = array( $expected = array(
'app' => 'new', 'app' => 'new',
'webroot' => 'webroot', 'webroot' => 'webroot',
'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'), 'working' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH) . DS . 'new'),
'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH)) 'root' => str_replace('\\', DS, dirname(CAKE_CORE_INCLUDE_PATH))
); );
$Dispatcher->params = $Dispatcher->args = array(); $Dispatcher->params = $Dispatcher->args = array();
$Dispatcher->parseParams($params); $Dispatcher->parseParams($params);
$this->assertEquals($expected, $Dispatcher->params); $this->assertEquals($expected, $Dispatcher->params);
}
/**
* testParseParams method
*
* @return void
*/
public function testParseParams() {
$Dispatcher = new TestShellDispatcher();
$params = array( $params = array(
'./console/cake.php', './console/cake.php',

View file

@ -48,14 +48,15 @@ class ControllerAuthorizeTest extends CakeTestCase {
* testControllerTypeError * testControllerTypeError
* *
* @expectedException PHPUnit_Framework_Error * @expectedException PHPUnit_Framework_Error
* @throws PHPUnit_Framework_Error
* @return void * @return void
* @throws PHPUnit_Framework_Error
*/ */
public function testControllerTypeError() { public function testControllerTypeError() {
try { try {
$this->auth->controller(new StdClass()); $this->auth->controller(new StdClass());
} catch (Throwable $t) { $this->fail('No exception thrown');
throw new PHPUnit_Framework_Error($t); } catch (TypeError $e) {
throw new PHPUnit_Framework_Error('Raised an error', 100, __FILE__, __LINE__);
} }
} }

View file

@ -1652,6 +1652,20 @@ class AuthComponentTest extends CakeTestCase {
Router::reload(); Router::reload();
} }
/**
* Test that redirectUrl() returns '/' if loginRedirect is empty
* and Auth.redirect is the login page.
*
* @return void
*/
public function testRedirectUrlWithoutLoginRedirect() {
$this->Auth->loginRedirect = null;
$this->Auth->Session->write('Auth.redirect', '/users/login');
$this->Auth->request->addParams(Router::parse('/users/login'));
$result = $this->Auth->redirectUrl();
$this->assertEquals('/', $result);
}
/** /**
* test password hashing * test password hashing
* *

View file

@ -153,6 +153,24 @@ class CookieComponentTest extends CakeTestCase {
$this->assertEquals($expected, $data); $this->assertEquals($expected, $data);
} }
/**
* test read operations on corrupted cookie data.
*
* @return void
*/
public function testReadCorruptedCookieData() {
$this->Cookie->type('aes');
$this->Cookie->key = sha1('some bad key');
$data = $this->_implode(array('name' => 'jill', 'age' => 24));
// Corrupt the cookie data by slicing some bytes off.
$_COOKIE['CakeTestCookie'] = array(
'BadData' => substr(Security::encrypt($data, $this->Cookie->key), 0, -5)
);
$this->assertFalse($this->Cookie->check('BadData.name'), 'Key does not exist');
$this->assertNull($this->Cookie->read('BadData.name'), 'Key does not exist');
}
/** /**
* testReadPlainCookieData * testReadPlainCookieData
* *
@ -169,6 +187,19 @@ class CookieComponentTest extends CakeTestCase {
$this->assertEquals($expected, $data); $this->assertEquals($expected, $data);
} }
/**
* test read array keys from string data.
*
* @return void
*/
public function testReadNestedDataFromStrings() {
$_COOKIE['CakeTestCookie'] = array(
'User' => 'bad data'
);
$this->assertFalse($this->Cookie->check('User.name'), 'No key');
$this->assertNull($this->Cookie->read('User.name'), 'No key');
}
/** /**
* test read() after switching the cookie name. * test read() after switching the cookie name.
* *
@ -207,6 +238,7 @@ class CookieComponentTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testWriteWithFalseyValue() { public function testWriteWithFalseyValue() {
$this->skipIf(!extension_loaded('mcrypt'), 'No Mcrypt, skipping.');
$this->Cookie->type('aes'); $this->Cookie->type('aes');
$this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^'; $this->Cookie->key = 'qSI232qs*&sXOw!adre@34SAv!@*(XSL#$%)asGb$@11~_+!@#HKis~#^';
@ -451,6 +483,25 @@ class CookieComponentTest extends CakeTestCase {
$this->assertNull($data); $this->assertNull($data);
} }
/**
* test delete() on corrupted/truncated cookie data.
*
* @return void
*/
public function testDeleteCorruptedCookieData() {
$this->Cookie->type('aes');
$this->Cookie->key = sha1('some bad key');
$data = $this->_implode(array('name' => 'jill', 'age' => 24));
// Corrupt the cookie data by slicing some bytes off.
$_COOKIE['CakeTestCookie'] = array(
'BadData' => substr(Security::encrypt($data, $this->Cookie->key), 0, -5)
);
$this->assertNull($this->Cookie->delete('BadData.name'));
$this->assertNull($this->Cookie->read('BadData.name'));
}
/** /**
* testReadingCookieArray * testReadingCookieArray
* *

View file

@ -75,4 +75,21 @@ class PagesControllerTest extends CakeTestCase {
$Pages = new PagesController(new CakeRequest(null, false), new CakeResponse()); $Pages = new PagesController(new CakeRequest(null, false), new CakeResponse());
$Pages->display('non_existing_page'); $Pages->display('non_existing_page');
} }
/**
* Test directory traversal protection
*
* @expectedException ForbiddenException
* @expectedExceptionCode 403
* @return void
*/
public function testDirectoryTraversalProtection() {
App::build(array(
'View' => array(
CAKE . 'Test' . DS . 'test_app' . DS . 'View' . DS
)
));
$Pages = new PagesController(new CakeRequest(null, false), new CakeResponse());
$Pages->display('..', 'Posts', 'index');
}
} }

View file

@ -450,16 +450,16 @@ class ConfigureTest extends CakeTestCase {
* test reader() throwing exceptions on missing interface. * test reader() throwing exceptions on missing interface.
* *
* @expectedException PHPUnit_Framework_Error * @expectedException PHPUnit_Framework_Error
* @throws PHPUnit_Framework_Error
* @return void * @return void
* @throws PHPUnit_Framework_Error
*/ */
public function testReaderExceptionOnIncorrectClass() { public function testReaderExceptionOnIncorrectClass() {
$reader = new StdClass(); $reader = new StdClass();
try { try {
Configure::config('test', $reader); Configure::config('test', $reader);
} catch (Throwable $t) { } catch (TypeError $e) {
throw new PHPUnit_Framework_Error($t); throw new PHPUnit_Framework_Error('Raised an error', 100, __FILE__, __LINE__);
} }
} }

View file

@ -2909,14 +2909,15 @@ SQL;
* testDropSchemaNoSchema method * testDropSchemaNoSchema method
* *
* @expectedException PHPUnit_Framework_Error * @expectedException PHPUnit_Framework_Error
* @throws PHPUnit_Framework_Error
* @return void * @return void
* @throws PHPUnit_Framework_Error
*/ */
public function testDropSchemaNoSchema() { public function testDropSchemaNoSchema() {
try { try {
$this->Dbo->dropSchema(null); $this->Dbo->dropSchema(null);
} catch (Throwable $t) { $this->fail('No exception');
throw new PHPUnit_Framework_Error($t); } catch (TypeError $e) {
throw new PHPUnit_Framework_Error('Raised an error', 100, __FILE__, __LINE__);
} }
} }

View file

@ -109,6 +109,52 @@ class DboSecondTestSource extends DboSource {
} }
/**
* DboThirdTestSource
*
* @package Cake.Test.Case.Model.Datasource
*/
class DboThirdTestSource extends DboSource {
public function connect($config = array()) {
$this->connected = true;
}
public function cacheMethodHasher($value) {
return hash('sha1', $value);
}
}
/**
* DboFourthTestSource
*
* @package Cake.Test.Case.Model.Datasource
*/
class DboFourthTestSource extends DboSource {
public function connect($config = array()) {
$this->connected = true;
}
public function cacheMethodFilter($method, $key, $value) {
if ($method === 'name') {
if ($value === '`menus`') {
return false;
} elseif ($key === '1fca740733997f1ebbedacfc7678592a') {
return false;
}
} elseif ($method === 'fields') {
$endsWithName = preg_grep('/`name`$/', $value);
return count($endsWithName) === 0;
}
return true;
}
}
/** /**
* DboSourceTest class * DboSourceTest class
* *
@ -737,6 +783,106 @@ class DboSourceTest extends CakeTestCase {
$this->assertNull($result); $this->assertNull($result);
} }
/**
* Test that cacheMethodFilter does not filter by default.
*
* @return void
*/
public function testCacheMethodFilter() {
$method = 'name';
$key = '49d9207adfce6df1dd3ee8c30c434414';
$value = '`menus`';
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'fields';
$key = '2b57253ab1fffb3e95fa4f95299220b1';
$value = array("`Menu`.`id`", "`Menu`.`name`");
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'non-existing';
$key = '';
$value = '``';
$actual = $this->testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
}
/**
* Test that cacheMethodFilter can be overridden to do actual filtering.
*
* @return void
*/
public function testCacheMethodFilterOverridden() {
$testDb = new DboFourthTestSource();
$method = 'name';
$key = '49d9207adfce6df1dd3ee8c30c434414';
$value = '`menus`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'name';
$key = '1fca740733997f1ebbedacfc7678592a';
$value = '`Menu`.`id`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'fields';
$key = '2b57253ab1fffb3e95fa4f95299220b1';
$value = array("`Menu`.`id`", "`Menu`.`name`");
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertFalse($actual);
$method = 'name';
$key = 'd2bc458620afb092c61ab4383b7475e0';
$value = '`Menu`';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
$method = 'non-existing';
$key = '';
$value = '``';
$actual = $testDb->cacheMethodFilter($method, $key, $value);
$this->assertTrue($actual);
}
/**
* Test that cacheMethodHasher uses md5 by default.
*
* @return void
*/
public function testCacheMethodHasher() {
$name = 'Model.fieldlbqndkezcoapfgirmjsh';
$actual = $this->testDb->cacheMethodHasher($name);
$expected = '4a45dc9ed52f98c393d04ac424ee5078';
$this->assertEquals($expected, $actual);
}
/**
* Test that cacheMethodHasher can be overridden to use a different hashing algorithm.
*
* @return void
*/
public function testCacheMethodHasherOverridden() {
$testDb = new DboThirdTestSource();
$name = 'Model.fieldlbqndkezcoapfgirmjsh';
$actual = $testDb->cacheMethodHasher($name);
$expected = 'beb8b6469359285b7c2865dce0ef743feb16cb71';
$this->assertEquals($expected, $actual);
}
/** /**
* Test that rare collisions do not happen with method caching * Test that rare collisions do not happen with method caching
* *

View file

@ -2224,14 +2224,15 @@ class ModelValidationTest extends BaseModelTest {
* Test that type hint exception is thrown * Test that type hint exception is thrown
* *
* @expectedException PHPUnit_Framework_Error * @expectedException PHPUnit_Framework_Error
* @throws PHPUnit_Framework_Error
* @return void * @return void
* @throws PHPUnit_Framework_Error
*/ */
public function testValidatorTypehintException() { public function testValidatorTypehintException() {
try { try {
new ModelValidator('asdasds'); new ModelValidator('asdasds');
} catch (Throwable $t) { $this->fail('No exeption raised');
throw new PHPUnit_Framework_Error($t); } catch (TypeError $e) {
throw new PHPUnit_Framework_Error('Raised an error', 100, __FILE__, __LINE__);
} }
} }

View file

@ -147,7 +147,7 @@ class ClassRegistryTest extends CakeTestCase {
$this->assertSame($Tag, $TagCopy); $this->assertSame($Tag, $TagCopy);
$NewTag = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag')); $NewTag = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag'));
$this->assertInstanceOf('RegisterArticleTag', $Tag); $this->assertInstanceOf('RegisterArticleTag', $NewTag);
$NewTagCopy = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag')); $NewTagCopy = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag'));
@ -182,6 +182,35 @@ class ClassRegistryTest extends CakeTestCase {
$this->assertEquals('ParentCategory', $ParentCategory->alias); $this->assertEquals('ParentCategory', $ParentCategory->alias);
} }
/**
* Test that init() can make models with alias set properly
*
* @return void
*/
public function testAddModelWithAlias() {
$tag = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'NewTag'));
$this->assertInstanceOf('RegisterArticleTag', $tag);
$this->assertSame('NewTag', $tag->alias);
$this->assertSame('RegisterArticleTag', $tag->name);
$newTag = ClassRegistry::init(array('class' => 'RegisterArticleTag', 'alias' => 'OtherTag'));
$this->assertInstanceOf('RegisterArticleTag', $tag);
$this->assertSame('OtherTag', $newTag->alias);
$this->assertSame('RegisterArticleTag', $newTag->name);
}
/**
* Test that init() can make the Aco models with alias set properly
*
* @return void
*/
public function testAddModelWithAliasAco() {
$aco = ClassRegistry::init(array('class' => 'Aco', 'alias' => 'CustomAco'));
$this->assertInstanceOf('Aco', $aco);
$this->assertSame('Aco', $aco->name);
$this->assertSame('CustomAco', $aco->alias);
}
/** /**
* testClassRegistryFlush method * testClassRegistryFlush method
* *

View file

@ -155,6 +155,24 @@ class DebuggerTest extends CakeTestCase {
$this->assertContains('$wrong = &#039;&#039;', $result[3], 'Context should be HTML escaped.'); $this->assertContains('$wrong = &#039;&#039;', $result[3], 'Context should be HTML escaped.');
} }
/**
* test encodes error messages
*
* @return void
*/
public function testOutputEncodeDescription() {
set_error_handler('Debugger::showError');
$this->_restoreError = true;
ob_start();
$a = array();
$b = $a['<script>alert(1)</script>'];
$result = ob_get_clean();
$this->assertNotContains('<script>alert(1)', $result);
$this->assertContains('&lt;script&gt;alert(1)', $result);
}
/** /**
* Tests that changes in output formats using Debugger::output() change the templates used. * Tests that changes in output formats using Debugger::output() change the templates used.
* *

View file

@ -328,6 +328,7 @@ class SecurityTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testEncryptDecrypt() { public function testEncryptDecrypt() {
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
$txt = 'The quick brown fox'; $txt = 'The quick brown fox';
$key = 'This key is longer than 32 bytes long.'; $key = 'This key is longer than 32 bytes long.';
$result = Security::encrypt($txt, $key); $result = Security::encrypt($txt, $key);
@ -342,6 +343,7 @@ class SecurityTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDecryptKeyFailure() { public function testDecryptKeyFailure() {
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
$txt = 'The quick brown fox'; $txt = 'The quick brown fox';
$key = 'This key is longer than 32 bytes long.'; $key = 'This key is longer than 32 bytes long.';
Security::encrypt($txt, $key); Security::encrypt($txt, $key);
@ -356,6 +358,7 @@ class SecurityTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDecryptHmacFailure() { public function testDecryptHmacFailure() {
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
$txt = 'The quick brown fox'; $txt = 'The quick brown fox';
$key = 'This key is quite long and works well.'; $key = 'This key is quite long and works well.';
$salt = 'this is a delicious salt!'; $salt = 'this is a delicious salt!';
@ -372,6 +375,7 @@ class SecurityTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testDecryptHmacSaltFailure() { public function testDecryptHmacSaltFailure() {
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
$txt = 'The quick brown fox'; $txt = 'The quick brown fox';
$key = 'This key is quite long and works well.'; $key = 'This key is quite long and works well.';
$salt = 'this is a delicious salt!'; $salt = 'this is a delicious salt!';
@ -400,6 +404,7 @@ class SecurityTest extends CakeTestCase {
* @return void * @return void
*/ */
public function testEncryptDecryptFalseyData() { public function testEncryptDecryptFalseyData() {
$this->skipIf(!extension_loaded('mcrypt'), 'This test requires mcrypt to be installed');
$key = 'This is a key that is long enough to be ok.'; $key = 'This is a key that is long enough to be ok.';
$result = Security::encrypt('', $key); $result = Security::encrypt('', $key);

View file

@ -395,7 +395,15 @@ XML;
$obj = Xml::fromArray($xml, 'attributes'); $obj = Xml::fromArray($xml, 'attributes');
$xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?><tags><tag id="1">defect</tag></tags>'; $xmlText = '<' . '?xml version="1.0" encoding="UTF-8"?><tags><tag id="1">defect</tag></tags>';
$this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
}
/**
* Test fromArray() with zero values.
*
* @return void
*/
public function testFromArrayZeroValue()
{
$xml = array( $xml = array(
'tag' => array( 'tag' => array(
'@' => 0, '@' => 0,
@ -406,6 +414,16 @@ XML;
$xmlText = <<<XML $xmlText = <<<XML
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<tag test="A test">0</tag> <tag test="A test">0</tag>
XML;
$this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
$xml = array(
'tag' => array('0')
);
$obj = Xml::fromArray($xml);
$xmlText = <<<XML
<?xml version="1.0" encoding="UTF-8"?>
<tag>0</tag>
XML; XML;
$this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML()); $this->assertXmlStringEqualsXmlString($xmlText, $obj->asXML());
} }

View file

@ -544,7 +544,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $result * @param mixed $result
* @param mixed $expected * @param mixed $expected
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertEqual($result, $expected, $message = '') { protected static function assertEqual($result, $expected, $message = '') {
@ -557,7 +557,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $result * @param mixed $result
* @param mixed $expected * @param mixed $expected
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertNotEqual($result, $expected, $message = '') { protected static function assertNotEqual($result, $expected, $message = '') {
@ -570,7 +570,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $pattern a regular expression * @param mixed $pattern a regular expression
* @param string $string the text to be matched * @param string $string the text to be matched
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertPattern($pattern, $string, $message = '') { protected static function assertPattern($pattern, $string, $message = '') {
@ -583,7 +583,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $actual * @param mixed $actual
* @param mixed $expected * @param mixed $expected
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertIdentical($actual, $expected, $message = '') { protected static function assertIdentical($actual, $expected, $message = '') {
@ -596,7 +596,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $actual * @param mixed $actual
* @param mixed $expected * @param mixed $expected
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertNotIdentical($actual, $expected, $message = '') { protected static function assertNotIdentical($actual, $expected, $message = '') {
@ -609,7 +609,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $pattern a regular expression * @param mixed $pattern a regular expression
* @param string $string the text to be matched * @param string $string the text to be matched
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertNoPattern($pattern, $string, $message = '') { protected static function assertNoPattern($pattern, $string, $message = '') {
@ -619,7 +619,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
/** /**
* assert no errors * assert no errors
* *
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected function assertNoErrors() { protected function assertNoErrors() {
@ -630,7 +630,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* *
* @param mixed $expected the name of the Exception or error * @param mixed $expected the name of the Exception or error
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected function expectError($expected = false, $message = '') { protected function expectError($expected = false, $message = '') {
@ -658,7 +658,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param mixed $first * @param mixed $first
* @param mixed $second * @param mixed $second
* @param string $message the text to display if the assertion is not correct * @param string $message the text to display if the assertion is not correct
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertReference(&$first, &$second, $message = '') { protected static function assertReference(&$first, &$second, $message = '') {
@ -671,7 +671,7 @@ abstract class CakeTestCase extends PHPUnit_Framework_TestCase {
* @param string $object * @param string $object
* @param string $type * @param string $type
* @param string $message * @param string $message
* @deprecated 3.0.0 This is a compatiblity wrapper for 1.x. It will be removed in 3.0 * @deprecated 3.0.0 This is a compatibility wrapper for 1.x. It will be removed in 3.0
* @return void * @return void
*/ */
protected static function assertIsA($object, $type, $message = '') { protected static function assertIsA($object, $type, $message = '') {

View file

@ -774,6 +774,7 @@ class Debugger {
if (!empty($tpl['escapeContext'])) { if (!empty($tpl['escapeContext'])) {
$context = h($context); $context = h($context);
$data['description'] = h($data['description']);
} }
$infoData = compact('code', 'context', 'trace'); $infoData = compact('code', 'context', 'trace');

View file

@ -171,7 +171,7 @@ class Security {
/** /**
* Get random bytes from a secure source. * Get random bytes from a secure source.
* *
* This method will fall back to an insecure source an trigger a warning * This method will fall back to an insecure source and trigger a warning,
* if it cannot find a secure source of random data. * if it cannot find a secure source of random data.
* *
* @param int $length The number of bytes you want. * @param int $length The number of bytes you want.

View file

@ -312,7 +312,7 @@ class Xml {
$childNS = $value['xmlns:']; $childNS = $value['xmlns:'];
unset($value['xmlns:']); unset($value['xmlns:']);
} }
} elseif (!empty($value) || $value === 0) { } elseif (!empty($value) || $value === 0 || $value === '0') {
$childValue = (string)$value; $childValue = (string)$value;
} }

View file

@ -564,7 +564,7 @@ class View extends CakeObject {
$type = $response->mapType($response->type()); $type = $response->mapType($response->type());
if (Configure::read('debug') > 0 && $type === 'html') { if (Configure::read('debug') > 0 && $type === 'html') {
echo "<!-- Cached Render Time: " . round(microtime(true) - $timeStart, 4) . "s -->"; echo "<!-- Cached Render Time: " . round(microtime(true) - (int)$timeStart, 4) . "s -->";
} }
$out = ob_get_clean(); $out = ob_get_clean();