|
|
|
@ -13,6 +13,7 @@ use yii\base\InvalidParamException;
|
|
|
|
|
use yii\helpers\FileHelper; |
|
|
|
|
use yii\helpers\Html; |
|
|
|
|
use yii\helpers\Json; |
|
|
|
|
use yii\helpers\SecurityHelper; |
|
|
|
|
use yii\helpers\StringHelper; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -131,18 +132,35 @@ class Response extends \yii\base\Response
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function begin() |
|
|
|
|
{ |
|
|
|
|
parent::begin(); |
|
|
|
|
$this->beginOutput(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function end() |
|
|
|
|
{ |
|
|
|
|
$this->content .= $this->endOutput(); |
|
|
|
|
$this->send(); |
|
|
|
|
parent::end(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function getStatusCode() |
|
|
|
|
{ |
|
|
|
|
return $this->_statusCode; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public function setStatusCode($value) |
|
|
|
|
public function setStatusCode($value, $text = null) |
|
|
|
|
{ |
|
|
|
|
$this->_statusCode = (int)$value; |
|
|
|
|
if ($this->isInvalid()) { |
|
|
|
|
throw new InvalidParamException("The HTTP status code is invalid: $value"); |
|
|
|
|
} |
|
|
|
|
if ($text === null) { |
|
|
|
|
$this->statusText = isset(self::$statusTexts[$this->_statusCode]) ? self::$statusTexts[$this->_statusCode] : ''; |
|
|
|
|
} else { |
|
|
|
|
$this->statusText = $text; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -186,13 +204,42 @@ class Response extends \yii\base\Response
|
|
|
|
|
*/ |
|
|
|
|
protected function sendHeaders() |
|
|
|
|
{ |
|
|
|
|
if (headers_sent()) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
header("HTTP/{$this->version} " . $this->getStatusCode() . " {$this->statusText}"); |
|
|
|
|
foreach ($this->_headers as $name => $values) { |
|
|
|
|
if ($this->_headers) { |
|
|
|
|
$headers = $this->getHeaders(); |
|
|
|
|
foreach ($headers as $name => $values) { |
|
|
|
|
foreach ($values as $value) { |
|
|
|
|
header("$name: $value"); |
|
|
|
|
header("$name: $value", false); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
$headers->removeAll(); |
|
|
|
|
} |
|
|
|
|
$this->sendCookies(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Sends the cookies to the client. |
|
|
|
|
*/ |
|
|
|
|
protected function sendCookies() |
|
|
|
|
{ |
|
|
|
|
if ($this->_cookies === null) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
$request = Yii::$app->getRequest(); |
|
|
|
|
if ($request->enableCookieValidation) { |
|
|
|
|
$validationKey = $request->getCookieValidationKey(); |
|
|
|
|
} |
|
|
|
|
foreach ($this->getCookies() as $cookie) { |
|
|
|
|
$value = $cookie->value; |
|
|
|
|
if ($cookie->expire != 1 && isset($validationKey)) { |
|
|
|
|
$value = SecurityHelper::hashData(serialize($value), $validationKey); |
|
|
|
|
} |
|
|
|
|
$this->_headers->removeAll(); |
|
|
|
|
setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly); |
|
|
|
|
} |
|
|
|
|
$this->getCookies()->removeAll(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -222,13 +269,15 @@ class Response extends \yii\base\Response
|
|
|
|
|
$contentStart = 0; |
|
|
|
|
$contentEnd = $fileSize - 1; |
|
|
|
|
|
|
|
|
|
$headers = $this->getHeaders(); |
|
|
|
|
|
|
|
|
|
// tell the client that we accept range requests |
|
|
|
|
header('Accept-Ranges: bytes'); |
|
|
|
|
$headers->set('Accept-Ranges', 'bytes'); |
|
|
|
|
|
|
|
|
|
if (isset($_SERVER['HTTP_RANGE'])) { |
|
|
|
|
// client sent us a multibyte range, can not hold this one for now |
|
|
|
|
if (strpos($_SERVER['HTTP_RANGE'], ',') !== false) { |
|
|
|
|
header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
$headers->set('Content-Range', "bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
throw new HttpException(416, 'Requested Range Not Satisfiable'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -257,25 +306,26 @@ class Response extends \yii\base\Response
|
|
|
|
|
$wrongContentStart = ($contentStart > $contentEnd || $contentStart > $fileSize - 1 || $contentStart < 0); |
|
|
|
|
|
|
|
|
|
if ($wrongContentStart) { |
|
|
|
|
header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
$headers->set('Content-Range', "bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
throw new HttpException(416, 'Requested Range Not Satisfiable'); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
header('HTTP/1.1 206 Partial Content'); |
|
|
|
|
header("Content-Range: bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
$this->setStatusCode(206); |
|
|
|
|
$headers->set('Content-Range', "bytes $contentStart-$contentEnd/$fileSize"); |
|
|
|
|
} else { |
|
|
|
|
header('HTTP/1.1 200 OK'); |
|
|
|
|
$this->setStatusCode(200); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$length = $contentEnd - $contentStart + 1; // Calculate new content length |
|
|
|
|
|
|
|
|
|
header('Pragma: public'); |
|
|
|
|
header('Expires: 0'); |
|
|
|
|
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); |
|
|
|
|
header('Content-Type: ' . $mimeType); |
|
|
|
|
header('Content-Length: ' . $length); |
|
|
|
|
header('Content-Disposition: attachment; filename="' . $fileName . '"'); |
|
|
|
|
header('Content-Transfer-Encoding: binary'); |
|
|
|
|
$headers->set('Pragma', 'public') |
|
|
|
|
->set('Expires', '0') |
|
|
|
|
->set('Cache-Control', 'must-revalidate, post-check=0, pre-check=0') |
|
|
|
|
->set('Content-Type', $mimeType) |
|
|
|
|
->set('Content-Length', $length) |
|
|
|
|
->set('Content-Disposition', "attachment; filename=\"$fileName\"") |
|
|
|
|
->set('Content-Transfer-Encoding', 'binary'); |
|
|
|
|
|
|
|
|
|
$content = StringHelper::substr($content, $contentStart, $length); |
|
|
|
|
|
|
|
|
|
if ($terminate) { |
|
|
|
@ -371,16 +421,18 @@ class Response extends \yii\base\Response
|
|
|
|
|
$options['xHeader'] = 'X-Sendfile'; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
$headers = $this->getHeaders(); |
|
|
|
|
|
|
|
|
|
if ($options['mimeType'] !== null) { |
|
|
|
|
header('Content-type: ' . $options['mimeType']); |
|
|
|
|
$headers->set('Content-Type', $options['mimeType']); |
|
|
|
|
} |
|
|
|
|
header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"'); |
|
|
|
|
$headers->set('Content-Disposition', "$disposition; filename=\"{$options['saveName']}\""); |
|
|
|
|
if (isset($options['addHeaders'])) { |
|
|
|
|
foreach ($options['addHeaders'] as $header => $value) { |
|
|
|
|
header($header . ': ' . $value); |
|
|
|
|
$headers->set($header, $value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
header(trim($options['xHeader']) . ': ' . $filePath); |
|
|
|
|
$headers->set(trim($options['xHeader']), $filePath); |
|
|
|
|
|
|
|
|
|
if (!isset($options['terminate']) || $options['terminate']) { |
|
|
|
|
Yii::$app->end(); |
|
|
|
@ -422,7 +474,8 @@ class Response extends \yii\base\Response
|
|
|
|
|
if (Yii::$app->getRequest()->getIsAjax()) { |
|
|
|
|
$statusCode = $this->ajaxRedirectCode; |
|
|
|
|
} |
|
|
|
|
header('Location: ' . $url, true, $statusCode); |
|
|
|
|
$this->getHeaders()->set('Location', $url); |
|
|
|
|
$this->setStatusCode($statusCode); |
|
|
|
|
if ($terminate) { |
|
|
|
|
Yii::$app->end(); |
|
|
|
|
} |
|
|
|
@ -441,6 +494,8 @@ class Response extends \yii\base\Response
|
|
|
|
|
$this->redirect(Yii::$app->getRequest()->getUrl() . $anchor, $terminate); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private $_cookies; |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Returns the cookie collection. |
|
|
|
|
* Through the returned cookie collection, you add or remove cookies as follows, |
|
|
|
@ -462,7 +517,10 @@ class Response extends \yii\base\Response
|
|
|
|
|
*/ |
|
|
|
|
public function getCookies() |
|
|
|
|
{ |
|
|
|
|
return Yii::$app->getRequest()->getCookies(); |
|
|
|
|
if ($this->_cookies === null) { |
|
|
|
|
$this->_cookies = new CookieCollection; |
|
|
|
|
} |
|
|
|
|
return $this->_cookies; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|