Merge branch '1.3' into merger

Conflicts:
	app/config/core.php
	cake/console/templates/skel/config/core.php
	cake/dispatcher.php
	cake/libs/controller/components/auth.php
	cake/libs/view/helpers/form.php
	cake/tests/cases/libs/cake_test_case.test.php
	cake/tests/cases/libs/controller/components/security.test.php
	cake/tests/cases/libs/model/models.php
	cake/tests/cases/libs/router.test.php
	cake/tests/cases/libs/view/helpers/paginator.test.php
	cake/tests/lib/cake_test_case.php
This commit is contained in:
mark_story 2010-11-16 21:48:13 -05:00
commit d12c232d8a
18 changed files with 184 additions and 27 deletions

View file

@ -18,7 +18,8 @@
// @license MIT License (http://www.opensource.org/licenses/mit-license.php)
// +--------------------------------------------------------------------------------------------+ //
////////////////////////////////////////////////////////////////////////////////////////////////////
1.3.5
1.3.6

View file

@ -17,4 +17,4 @@
* @since CakePHP(tm) v 1.1.11.4062
* @license MIT License (http://www.opensource.org/licenses/mit-license.php)
*/
return $config['Cake.version'] = '1.3.5';
return $config['Cake.version'] = '1.3.6';

View file

@ -520,7 +520,6 @@ class AuthComponent extends Component {
$valid = $this->Acl->check($user, $this->action());
break;
case 'crud':
$this->mapActions();
if (!isset($this->actionMap[$this->request['action']])) {
trigger_error(
sprintf(__('Auth::startup() - Attempted access of un-mapped action "%1$s" in controller "%2$s"'), $this->request['action'], $this->request['controller']),
@ -535,7 +534,6 @@ class AuthComponent extends Component {
}
break;
case 'model':
$this->mapActions();
$action = $this->request['action'];
if (isset($this->actionMap[$action])) {
$action = $this->actionMap[$action];

View file

@ -618,10 +618,15 @@ class SecurityComponent extends Component {
}
unset($check['_Token']);
$locked = str_rot13($locked);
if (preg_match('/(\A|;|{|})O\:[0-9]+/', $locked)) {
return false;
}
$lockedFields = array();
$fields = Set::flatten($check);
$fieldList = array_keys($fields);
$locked = unserialize(str_rot13($locked));
$locked = unserialize($locked);
$multi = array();
foreach ($fieldList as $i => $key) {

View file

@ -139,11 +139,11 @@ class I18n {
$_this->domain = $domain . '_' . $_this->l10n->lang;
if (empty($_this->__domains[$domain][$_this->__lang])) {
if (!isset($_this->__domains[$domain][$_this->__lang])) {
$_this->__domains[$domain][$_this->__lang] = Cache::read($_this->domain, '_cake_core_');
}
if (empty($_this->__domains[$domain][$_this->__lang][$_this->category])) {
if (!isset($_this->__domains[$domain][$_this->__lang][$_this->category])) {
$_this->__bindTextDomain($domain);
Cache::write($_this->domain, $_this->__domains[$domain][$_this->__lang], '_cake_core_');
}

View file

@ -1636,7 +1636,7 @@ class Model extends Object {
}
if ($options['atomic'] && $options['validate'] !== 'only') {
$db->begin($this);
$transactionBegun = $db->begin($this);
}
if (Set::numeric(array_keys($data))) {
@ -1676,8 +1676,12 @@ class Model extends Object {
break;
default:
if ($options['atomic']) {
if ($validates && ($db->commit($this) !== false)) {
return true;
if ($validates) {
if ($transactionBegun) {
return $db->commit($this) !== false;
} else {
return true;
}
}
$db->rollback($this);
return false;
@ -1787,7 +1791,11 @@ class Model extends Object {
default:
if ($options['atomic']) {
if ($validates) {
return ($db->commit($this) !== false);
if ($transactionBegun) {
return $db->commit($this) !== false;
} else {
return true;
}
} else {
$db->rollback($this);
}
@ -1870,7 +1878,7 @@ class Model extends Object {
));
}
if ($db->delete($this)) {
if ($db->delete($this, array($this->alias . '.' . $this->primaryKey => $id))) {
if (!empty($this->belongsTo)) {
$this->updateCounterCache($keys[$this->alias]);
}

View file

@ -218,7 +218,8 @@ class FormHelper extends AppHelper {
$data = $this->fieldset[$modelEntity];
$recordExists = (
isset($this->request->data[$model]) &&
!empty($this->request->data[$model][$data['key']])
!empty($this->request->data[$model][$data['key']]) &&
!is_array($this->request->data[$model][$data['key']])
);
if ($recordExists) {

View file

@ -48,7 +48,7 @@ class NumberHelper extends AppHelper {
'decimals' => '.', 'negative' => '()','escape' => false
),
'EUR' => array(
'before'=>'€', 'after' => 'c', 'zero' => 0, 'places' => 2, 'thousands' => '.',
'before'=>'€', 'after' => false, 'zero' => 0, 'places' => 2, 'thousands' => '.',
'decimals' => ',', 'negative' => '()', 'escape' => false
)
);

View file

@ -21,7 +21,7 @@ if (Configure::read() == 0):
endif;
?>
<h2><?php echo sprintf(__('Release Notes for CakePHP %s.', true), Configure::version()); ?></h2>
<a href="http://cakephp.lighthouseapp.com/projects/42648/changelog-1-3-5"><?php __('Read the changelog'); ?> </a>
<a href="http://cakephp.org/changelogs/1.3.6"><?php __('Read the changelog'); ?> </a>
<?php
if (Configure::read() > 0):
Debugger::checkSecurityKeys();

View file

@ -60,7 +60,6 @@ class CakeTestCaseTest extends CakeTestCase {
*/
function tearDown() {
Configure::write('debug', $this->_debug);
unset($this->Case);
unset($this->Result);
unset($this->Reporter);
}
@ -77,6 +76,30 @@ class CakeTestCaseTest extends CakeTestCase {
$this->assertEquals(0, $result->errorCount());
$this->assertTrue($result->wasSuccessful());
$this->assertEquals(0, $result->failureCount());
$input = '<a href="/test.html" class="active">My link</a>';
$pattern = array(
'a' => array('href' => '/test.html', 'class' => 'active'),
'My link',
'/a'
);
$this->assertTrue($test->assertTags($input, $pattern), 'Double quoted attributes %s');
$input = "<a href='/test.html' class='active'>My link</a>";
$pattern = array(
'a' => array('href' => '/test.html', 'class' => 'active'),
'My link',
'/a'
);
$this->assertTrue($test->assertTags($input, $pattern), 'Single quoted attributes %s');
$input = "<a href='/test.html' class='active'>My link</a>";
$pattern = array(
'a' => array('href' => 'preg:/.*\.html/', 'class' => 'active'),
'My link',
'/a'
);
$this->assertTrue($test->assertTags($input, $pattern), 'Single quoted attributes %s');
}
/**
@ -181,6 +204,7 @@ class CakeTestCaseTest extends CakeTestCase {
$manager->expects($this->once())->method('unload');
$result = $test->run();
$this->assertEquals(1, $result->errorCount());
}
/**
* testSkipIf

View file

@ -608,6 +608,29 @@ DIGEST;
$this->assertFalse($result, 'validatePost passed when fields were missing. %s');
}
/**
* Test that objects can't be passed into the serialized string. This was a vector for RFI and LFI
* attacks. Thanks to Felix Wilhelm
*
* @return void
*/
function testValidatePostObjectDeserialize() {
$this->Controller->Security->startup($this->Controller);
$key = $this->Controller->request->params['_Token']['key'];
$fields = 'a5475372b40f6e3ccbf9f8af191f20e1642fd877';
// a corrupted serialized object, so we can see if it ever gets to deserialize
$attack = 'O:3:"App":1:{s:5:"__map";a:1:{s:3:"foo";s:7:"Hacked!";s:1:"fail"}}';
$fields .= urlencode(':' . str_rot13($attack));
$this->Controller->request->data = array(
'Model' => array('username' => 'mark', 'password' => 'foo', 'valid' => '0'),
'_Token' => compact('key', 'fields')
);
$result = $this->Controller->Security->validatePost($this->Controller);
$this->assertFalse($result, 'validatePost passed when key was missing. %s');
}
/**
* Tests validation of checkbox arrays
*

View file

@ -799,7 +799,7 @@ class DboMysqlTest extends CakeTestCase {
$this->db->virtualFieldSeparator = '_$_';
$result = $this->db->fields($model, null, array('data', 'other__field'));
$expected = array('`BinaryTest`.`data`', '(SUM(id)) AS BinaryTest_$_other__field');
$expected = array('`BinaryTest`.`data`', '(SUM(id)) AS `BinaryTest_$_other__field`');
$this->assertEqual($result, $expected);
}

View file

@ -3059,6 +3059,22 @@ class ModelWriteTest extends BaseModelTest {
$Post->saveAll($data);
}
/**
* test saveAll with nested saveAll call.
*
* @return void
*/
function testSaveAllNestedSaveAll() {
$this->loadFixtures('Sample');
$TransactionTestModel =& new TransactionTestModel();
$data = array(
array('apple_id' => 1, 'name' => 'sample5'),
);
$this->assertTrue($TransactionTestModel->saveAll($data, array('atomic' => true)));
}
/**
* testSaveAllTransaction method
*

View file

@ -3559,6 +3559,7 @@ class FruitNoWith extends CakeTestModel {
)
);
}
class UuidTagNoWith extends CakeTestModel {
public $name = 'UuidTag';
public $useTable = 'uuid_tags';
@ -3581,5 +3582,16 @@ class ProductUpdateAll extends CakeTestModel {
class GroupUpdateAll extends CakeTestModel {
public $name = 'GroupUpdateAll';
public $useTable = 'group_update_all';
}
class TransactionTestModel extends CakeTestModel {
var $name = 'TransactionTestModel';
var $useTable = 'samples';
function afterSave($created) {
$data = array(
array('apple_id' => 1, 'name' => 'sample6'),
);
$this->saveAll($data, array('atomic' => true, 'callbacks' => false));
}
}

View file

@ -56,6 +56,8 @@ class RouterTest extends CakeTestCase {
}
$this->assertPattern('/^http(s)?:\/\//', Router::url('/', true));
$this->assertPattern('/^http(s)?:\/\//', Router::url(null, true));
$this->assertPattern('/^http(s)?:\/\//', Router::url(array('full_base' => true)));
$this->assertIdentical(FULL_BASE_URL . '/', Router::url(array('full_base' => true)));
}
/**
@ -2265,6 +2267,31 @@ class RouterTest extends CakeTestCase {
$this->assertEqual($url, Router::url($url));
}
/**
* Testing that patterns on the :action param work properly.
*
* @return void
*/
function testPatternOnAction() {
$route =& new CakeRoute(
'/blog/:action/*',
array('controller' => 'blog_posts'),
array('action' => 'other|actions')
);
$result = $route->match(array('controller' => 'blog_posts', 'action' => 'foo'));
$this->assertFalse($result);
$result = $route->match(array('controller' => 'blog_posts', 'action' => 'actions'));
$this->assertEquals('/blog/actions/', $result);
$result = $route->parse('/blog/other');
$expected = array('controller' => 'blog_posts', 'action' => 'other', 'pass' => array(), 'named' => array());
$this->assertEqual($expected, $result);
$result = $route->parse('/blog/foobar');
$this->assertFalse($result);
}
/**
* test setting redirect routes
*

View file

@ -5679,6 +5679,31 @@ class FormHelperTest extends CakeTestCase {
$this->assertTags($result, $expected, true);
}
/**
* test that create() doesn't cause errors by multiple id's being in the primary key
* as could happen with multiple select or checkboxes.
*
* @return void
*/
function testCreateWithMultipleIdInData() {
$encoding = strtolower(Configure::read('App.encoding'));
$this->Form->request->data['Contact']['id'] = array(1, 2);
$result = $this->Form->create('Contact');
$expected = array(
'form' => array(
'id' => 'ContactAddForm',
'method' => 'post',
'action' => '/contacts/add',
'accept-charset' => $encoding
),
'div' => array('style' => 'display:none;'),
'input' => array('type' => 'hidden', 'name' => '_method', 'value' => 'POST'),
'/div'
);
$this->assertTags($result, $expected);
}
/**
* test that create() doesn't add in extra passed params.
*

View file

@ -237,7 +237,7 @@ class NumberHelperTest extends CakeTestCase {
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '99c';
$expected = '&#8364;0,99';
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'GBP');
@ -259,7 +259,7 @@ class NumberHelperTest extends CakeTestCase {
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'EUR');
$expected = '(99c)';
$expected = '(&#8364;0,99)';
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'GBP');
@ -271,7 +271,7 @@ class NumberHelperTest extends CakeTestCase {
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'EUR', array('negative'=>'-'));
$expected = '-99c';
$expected = '-&#8364;0,99';
$this->assertEqual($expected, $result);
$result = $this->Number->currency($value, 'GBP', array('negative'=>'-'));
@ -337,6 +337,10 @@ class NumberHelperTest extends CakeTestCase {
$result = $this->Number->currency('0.35', 'GBP');
$expected = '35p';
$this->assertEqual($expected, $result);
$result = $this->Number->currency('0.35', 'EUR');
$expected = '&#8364;0,35';
$this->assertEqual($expected, $result);
}
/**

View file

@ -20,6 +20,10 @@
App::import('Core', 'View');
App::import('Helper', array('Html', 'Paginator', 'Form', 'Js'));
if (!defined('FULL_BASE_URL')) {
define('FULL_BASE_URL', 'http://cakephp.org');
}
/**
* PaginatorHelperTest class
*
@ -1777,6 +1781,15 @@ class PaginatorHelperTest extends CakeTestCase {
'/span',
);
$this->assertTags($result, $expected);
$this->Paginator->options(array('url' => array('full_base' => true)));
$result = $this->Paginator->first();
$expected = array(
'<span',
array('a' => array('href' => FULL_BASE_URL . '/index/page:1/sort:Client.name/direction:DESC')), '&lt;&lt; first', '/a',
'/span',
);
$this->assertTags($result, $expected);
}
/**