Commit 046b56ce by Qiang Xue

Fixes #5423: `yii\behaviors\Cors` causes "undefined index" error when its `cors` is configured

parent 12a7c38e
...@@ -8,7 +8,8 @@ Yii Framework 2 Change Log ...@@ -8,7 +8,8 @@ Yii Framework 2 Change Log
- Bug #5260: `yii\i18n\Formatter::decimalSeparator` and `yii\i18n\Formatter::thousandSeparator` where not configurable when intl is not installed (execut, cebe) - Bug #5260: `yii\i18n\Formatter::decimalSeparator` and `yii\i18n\Formatter::thousandSeparator` where not configurable when intl is not installed (execut, cebe)
- Bug #5314: Fixed typo in the implementation of `yii\web\Session::getHasSessionId()` (qiangxue) - Bug #5314: Fixed typo in the implementation of `yii\web\Session::getHasSessionId()` (qiangxue)
- Bug #5323: Nested dropdown does not work for `yii\bootstrap\DropDown` (aryraditya) - Bug #5323: Nested dropdown does not work for `yii\bootstrap\DropDown` (aryraditya)
- Bug #5336: `yii\bootstrap\DropDown` should register bootstrap plugin asset (zelenin) - Bug #5336: `yii\bootstrap\DropDown` should register bootstrap plugin asset (zelenin)
- Bug #5423: `yii\behaviors\Cors` causes "undefined index" error when its `cors` is configured (qiangxue)
- Bug: Date and time formatting now assumes UTC as the timezone for input dates unless a timezone is explicitly given (cebe) - Bug: Date and time formatting now assumes UTC as the timezone for input dates unless a timezone is explicitly given (cebe)
- Enh #4040: Added `$viewFile` and `$params` to the `EVENT_BEFORE_RENDER` and `EVENT_AFTER_RENDER` events for `View` (qiangxue) - Enh #4040: Added `$viewFile` and `$params` to the `EVENT_BEFORE_RENDER` and `EVENT_AFTER_RENDER` events for `View` (qiangxue)
- Enh #4275: Added `removeChildren()` to `yii\rbac\ManagerInterface` and implementations (samdark) - Enh #4275: Added `removeChildren()` to `yii\rbac\ManagerInterface` and implementations (samdark)
......
...@@ -15,7 +15,7 @@ use yii\web\Response; ...@@ -15,7 +15,7 @@ use yii\web\Response;
/** /**
* Cors filter implements [Cross Origin Resource Sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing). * Cors filter implements [Cross Origin Resource Sharing](http://en.wikipedia.org/wiki/Cross-origin_resource_sharing).
* Make sure to read carefully what CORS does and does not. CORS do not secure your API, * Make sure to read carefully what CORS does and does not. CORS do not secure your API,
* but allow the developper to grant access to third party code (ajax calls from external domain) * but allow the developer to grant access to third party code (ajax calls from external domain)
* *
* You may use CORS filter by attaching it as a behavior to a controller or module, like the following, * You may use CORS filter by attaching it as a behavior to a controller or module, like the following,
* *
...@@ -90,8 +90,8 @@ class Cors extends ActionFilter ...@@ -90,8 +90,8 @@ class Cors extends ActionFilter
*/ */
public function beforeAction($action) public function beforeAction($action)
{ {
$this->request = $this->request ? : Yii::$app->getRequest(); $this->request = $this->request ?: Yii::$app->getRequest();
$this->response = $this->response ? : Yii::$app->getResponse(); $this->response = $this->response ?: Yii::$app->getResponse();
$this->overrideDefaultSettings($action); $this->overrideDefaultSettings($action);
...@@ -129,7 +129,7 @@ class Cors extends ActionFilter ...@@ -129,7 +129,7 @@ class Cors extends ActionFilter
$requestHeaders = array_keys($this->cors); $requestHeaders = array_keys($this->cors);
foreach ($requestHeaders as $headerField) { foreach ($requestHeaders as $headerField) {
$serverField = $this->headerizeToPhp($headerField); $serverField = $this->headerizeToPhp($headerField);
$headerData = isset($_SERVER[$serverField])?$_SERVER[$serverField]:null; $headerData = isset($_SERVER[$serverField]) ? $_SERVER[$serverField] : null;
if ($headerData !== null) { if ($headerData !== null) {
$headers[$headerField] = $headerData; $headers[$headerField] = $headerData;
} }
...@@ -148,7 +148,8 @@ class Cors extends ActionFilter ...@@ -148,7 +148,8 @@ class Cors extends ActionFilter
// handle Origin // handle Origin
if (isset($requestHeaders['Origin'])) { if (isset($requestHeaders['Origin'])) {
if ((in_array('*', $this->cors['Origin']) === true) if ((in_array('*', $this->cors['Origin']) === true)
|| (in_array($requestHeaders['Origin'], $this->cors['Origin']))) { || (in_array($requestHeaders['Origin'], $this->cors['Origin']))
) {
$responseHeaders['Access-Control-Allow-Origin'] = $requestHeaders['Origin']; $responseHeaders['Access-Control-Allow-Origin'] = $requestHeaders['Origin'];
} }
} }
...@@ -160,13 +161,11 @@ class Cors extends ActionFilter ...@@ -160,13 +161,11 @@ class Cors extends ActionFilter
$responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']); $responseHeaders['Access-Control-Allow-Methods'] = implode(', ', $this->cors['Access-Control-Request-Method']);
} }
if ($this->cors['Access-Control-Allow-Credentials'] === true) { if (isset($this->cors['Access-Control-Allow-Credentials'])) {
$responseHeaders['Access-Control-Allow-Credentials'] = 'true'; $responseHeaders['Access-Control-Allow-Credentials'] = $this->cors['Access-Control-Allow-Credentials'] ? 'true' : 'false';
} elseif ($this->cors['Access-Control-Allow-Credentials'] === false) {
$responseHeaders['Access-Control-Allow-Credentials'] = 'false';
} }
if (($_SERVER['REQUEST_METHOD'] === 'OPTIONS') && ($this->cors['Access-Control-Max-Age'] !== null)) { if (isset($this->cors['Access-Control-Max-Age']) && Yii::$app->getRequest()->getIsOptions()) {
$responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age']; $responseHeaders['Access-Control-Max-Age'] = $this->cors['Access-Control-Max-Age'];
} }
...@@ -181,8 +180,8 @@ class Cors extends ActionFilter ...@@ -181,8 +180,8 @@ class Cors extends ActionFilter
*/ */
protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders) protected function prepareAllowHeaders($type, $requestHeaders, &$responseHeaders)
{ {
$requestHeaderField = 'Access-Control-Request-'.$type; $requestHeaderField = 'Access-Control-Request-' . $type;
$responseHeaderField = 'Access-Control-Allow-'.$type; $responseHeaderField = 'Access-Control-Allow-' . $type;
if (isset($requestHeaders[$requestHeaderField])) { if (isset($requestHeaders[$requestHeaderField])) {
if (in_array('*', $this->cors[$requestHeaderField])) { if (in_array('*', $this->cors[$requestHeaderField])) {
$responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]); $responseHeaders[$responseHeaderField] = $this->headerize($requestHeaders[$requestHeaderField]);
...@@ -226,8 +225,8 @@ class Cors extends ActionFilter ...@@ -226,8 +225,8 @@ class Cors extends ActionFilter
*/ */
protected function headerize($string) protected function headerize($string)
{ {
$headers = preg_split("/[\s,]+/", $string, -1, PREG_SPLIT_NO_EMPTY); $headers = preg_split("/[\\s,]+/", $string, -1, PREG_SPLIT_NO_EMPTY);
$headers = array_map(function($element) { $headers = array_map(function ($element) {
return str_replace(' ', '-', ucwords(strtolower(str_replace(['_', '-'], [' ', ' '], $element)))); return str_replace(' ', '-', ucwords(strtolower(str_replace(['_', '-'], [' ', ' '], $element))));
}, $headers); }, $headers);
return implode(', ', $headers); return implode(', ', $headers);
...@@ -242,6 +241,6 @@ class Cors extends ActionFilter ...@@ -242,6 +241,6 @@ class Cors extends ActionFilter
*/ */
protected function headerizeToPhp($string) protected function headerizeToPhp($string)
{ {
return 'HTTP_'.strtoupper(str_replace([' ', '-'], ['_', '_'], $string)); return 'HTTP_' . strtoupper(str_replace([' ', '-'], ['_', '_'], $string));
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment