Skip to content

Commit

Permalink
Merge branch '2.5' into 3.0
Browse files Browse the repository at this point in the history
Conflicts:
	build.xml
	lib/Cake/Model/Behavior/TranslateBehavior.php
	lib/Cake/Model/Permission.php
	lib/Cake/Network/Http/HttpSocket.php
	lib/Cake/Test/Case/Controller/Component/Acl/DbAclTest.php
	lib/Cake/Test/Case/Model/Behavior/TranslateBehaviorTest.php
	lib/Cake/Test/Case/Model/models.php
	src/Console/Command/Task/ExtractTask.php
  • Loading branch information
markstory committed Jan 30, 2014
2 parents b6b3287 + c1ab6fa commit fc1ffd6
Show file tree
Hide file tree
Showing 5 changed files with 194 additions and 0 deletions.
45 changes: 45 additions & 0 deletions lib/Cake/Test/test_app/Model/Extract.php
@@ -0,0 +1,45 @@
<?php
/**
* Test App Extract Model
*
* CakePHP : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* For full copyright and license information, please see the LICENSE.txt
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP Project
* @package Cake.Test.TestApp.Model
* @since CakePHP v 2.4
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/

/**
* Class Extract
*
* For testing Console i18n validation message extraction with quotes
*
* @package Cake.Test.TestApp.Model
*/
class Extract extends AppModel {

public $useTable = false;

public $validate = array(
'title' => array(
'custom' => array(
'rule' => array('custom', '.*'),
'allowEmpty' => true,
'required' => false,
'message' => 'double "quoted" validation'
),
'between' => array(
'rule' => array('between', 5, 15),
'message' => "single 'quoted' validation"
)
),
);

}
1 change: 1 addition & 0 deletions src/Console/Command/Task/ExtractTask.php
Expand Up @@ -527,6 +527,7 @@ protected function _processValidationRules($field, $rules, $file, $domain, $cate
$msgid = $rule;
}
if ($msgid) {
$msgid = $this->_formatString(sprintf("'%s'", $msgid));
$details = [
'file' => $file,
'line' => 'validation for field ' . $field
Expand Down
69 changes: 69 additions & 0 deletions src/Network/Response.php
Expand Up @@ -1241,6 +1241,75 @@ public function cookie($options = null) {
$this->_cookies[$options['name']] = $options;
}

/**
* Setup access for origin and methods on cross origin requests
*
* This method allow multiple ways to setup the domains, see the examples
*
* ### Full URI
* e.g `cors($request, 'http://www.cakephp.org');`
*
* ### URI with wildcard
* e.g `cors($request, 'http://*.cakephp.org');`
*
* ### Ignoring the requested protocol
* e.g `cors($request, 'www.cakephp.org');`
*
* ### Any URI
* e.g `cors($request, '*');`
*
* ### Whitelist of URIs
* e.g `cors($request, array('http://www.cakephp.org', '*.google.com', 'https://myproject.github.io'));`
*
* @param CakeRequest $request Request object
* @param string|array $allowedDomains List of allowed domains, see method description for more details
* @param string|array $allowedMethods List of HTTP verbs allowed
* @param string|array $allowedHeaders List of HTTP headers allowed
* @return void
*/
public function cors(CakeRequest $request, $allowedDomains, $allowedMethods = array(), $allowedHeaders = array()) {
$origin = $request->header('Origin');
if (!$origin) {
return;
}

$allowedDomains = $this->_normalizeCorsDomains((array)$allowedDomains, $request->is('ssl'));
foreach ($allowedDomains as $domain) {
if (!preg_match($domain['preg'], $origin)) {
continue;
}
$this->header('Access-Control-Allow-Origin', $domain['original'] === '*' ? '*' : $origin);
$allowedMethods && $this->header('Access-Control-Allow-Methods', implode(', ', (array)$allowedMethods));
$allowedHeaders && $this->header('Access-Control-Allow-Headers', implode(', ', (array)$allowedHeaders));
break;
}
}

/**
* Normalize the origin to regular expressions and put in an array format
*
* @param array $domains
* @param boolean $requestIsSSL
* @return array
*/
protected function _normalizeCorsDomains($domains, $requestIsSSL = false) {
$result = array();
foreach ($domains as $domain) {
if ($domain === '*') {
$result[] = array('preg' => '@.@', 'original' => '*');
continue;
}

$original = $preg = $domain;
if (strpos($domain, '://') === false) {
$preg = ($requestIsSSL ? 'https://' : 'http://') . $domain;
}
$preg = '@' . str_replace('*', '.*', $domain) . '@';
$result[] = compact('original', 'preg');
}
return $result;
}

/**
* Setup for display or download the given file.
*
Expand Down
3 changes: 3 additions & 0 deletions tests/TestCase/Console/Command/Task/ExtractTaskTest.php
Expand Up @@ -298,6 +298,9 @@ public function testExtractModelValidation() {

$pattern = '#msgid "Post body is super required"#';
$this->assertRegExp($pattern, $result);

$this->assertContains('msgid "double \\"quoted\\" validation"', $result, 'Strings with quotes not handled correctly');
$this->assertContains("msgid \"single 'quoted' validation\"", $result, 'Strings with quotes not handled correctly');
}

/**
Expand Down
76 changes: 76 additions & 0 deletions tests/TestCase/Network/ResponseTest.php
Expand Up @@ -1061,6 +1061,82 @@ public function testCookieSettings() {
$this->assertEquals($expected, $result);
}

/**
* Test CORS
*
* @dataProvider corsData
* @param CakeRequest $request
* @param string $origin
* @param string|array $domains
* @param string|array $methods
* @param string|array $headers
* @param string|boolean $expectedOrigin
* @param string|boolean $expectedMethods
* @param string|boolean $expectedHeaders
* @return void
*/
public function testCors($request, $origin, $domains, $methods, $headers, $expectedOrigin, $expectedMethods = false, $expectedHeaders = false) {
$_SERVER['HTTP_ORIGIN'] = $origin;

$response = $this->getMock('CakeResponse', array('header'));

$method = $response->expects(!$expectedOrigin ? $this->never() : $this->at(0))->method('header');
$expectedOrigin && $method->with('Access-Control-Allow-Origin', $expectedOrigin ? $expectedOrigin : $this->anything());

$i = 1;
if ($expectedMethods) {
$response->expects($this->at($i++))
->method('header')
->with('Access-Control-Allow-Methods', $expectedMethods ? $expectedMethods : $this->anything());
}
if ($expectedHeaders) {
$response->expects($this->at($i++))
->method('header')
->with('Access-Control-Allow-Headers', $expectedHeaders ? $expectedHeaders : $this->anything());
}

$response->cors($request, $domains, $methods, $headers);
unset($_SERVER['HTTP_ORIGIN']);
}

/**
* Feed for testCors
*
* @return array
*/
public function corsData() {
$fooRequest = new CakeRequest();

$secureRequest = $this->getMock('CakeRequest', array('is'));
$secureRequest->expects($this->any())
->method('is')
->with('ssl')
->will($this->returnValue(true));

return array(
array($fooRequest, null, '*', '', '', false, false),
array($fooRequest, 'http://www.foo.com', '*', '', '', '*', false),
array($fooRequest, 'http://www.foo.com', 'www.foo.com', '', '', 'http://www.foo.com', false),
array($fooRequest, 'http://www.foo.com', '*.foo.com', '', '', 'http://www.foo.com', false),
array($fooRequest, 'http://www.foo.com', 'http://*.foo.com', '', '', 'http://www.foo.com', false),
array($fooRequest, 'http://www.foo.com', 'https://www.foo.com', '', '', false, false),
array($fooRequest, 'http://www.foo.com', 'https://*.foo.com', '', '', false, false),
array($fooRequest, 'http://www.foo.com', array('*.bar.com', '*.foo.com'), '', '', 'http://www.foo.com', false),

array($secureRequest, 'https://www.bar.com', 'www.bar.com', '', '', 'https://www.bar.com', false),
array($secureRequest, 'https://www.bar.com', 'http://www.bar.com', '', '', false, false),
array($secureRequest, 'https://www.bar.com', '*.bar.com', '', '', 'https://www.bar.com', false),

array($fooRequest, 'http://www.foo.com', '*', 'GET', '', '*', 'GET'),
array($fooRequest, 'http://www.foo.com', '*.foo.com', 'GET', '', 'http://www.foo.com', 'GET'),
array($fooRequest, 'http://www.foo.com', '*.foo.com', array('GET', 'POST'), '', 'http://www.foo.com', 'GET, POST'),

array($fooRequest, 'http://www.foo.com', '*', '', 'X-CakePHP', '*', false, 'X-CakePHP'),
array($fooRequest, 'http://www.foo.com', '*', '', array('X-CakePHP', 'X-MyApp'), '*', false, 'X-CakePHP, X-MyApp'),
array($fooRequest, 'http://www.foo.com', '*', array('GET', 'OPTIONS'), array('X-CakePHP', 'X-MyApp'), '*', 'GET, OPTIONS', 'X-CakePHP, X-MyApp'),
);
}

/**
* testFileNotFound
*
Expand Down

0 comments on commit fc1ffd6

Please sign in to comment.