Commit 72ff81f7 by Qiang Xue

Web WIP

parent 0657381f
...@@ -308,7 +308,7 @@ class Component extends \yii\base\Object ...@@ -308,7 +308,7 @@ class Component extends \yii\base\Object
* where `$event` is an [[Event]] object which includes parameters associated with the event. * where `$event` is an [[Event]] object which includes parameters associated with the event.
* *
* @param string $name the event name * @param string $name the event name
* @param callback $handler the event handler * @param string|array|\Closure $handler the event handler
* @see off * @see off
*/ */
public function on($name, $handler) public function on($name, $handler)
...@@ -320,7 +320,7 @@ class Component extends \yii\base\Object ...@@ -320,7 +320,7 @@ class Component extends \yii\base\Object
* Detaches an existing event handler. * Detaches an existing event handler.
* This method is the opposite of [[on]]. * This method is the opposite of [[on]].
* @param string $name event name * @param string $name event name
* @param callback $handler the event handler to be removed * @param string|array|\Closure $handler the event handler to be removed
* @return boolean if a handler is found and detached * @return boolean if a handler is found and detached
* @see on * @see on
*/ */
......
...@@ -87,4 +87,51 @@ class FileHelper ...@@ -87,4 +87,51 @@ class FileHelper
$desiredFile = dirname($file) . DIRECTORY_SEPARATOR . $sourceLanguage . DIRECTORY_SEPARATOR . basename($file); $desiredFile = dirname($file) . DIRECTORY_SEPARATOR . $sourceLanguage . DIRECTORY_SEPARATOR . basename($file);
return is_file($desiredFile) ? $desiredFile : $file; return is_file($desiredFile) ? $desiredFile : $file;
} }
/**
* Determines the MIME type of the specified file.
* This method will first try to determine the MIME type based on
* [finfo_open](http://php.net/manual/en/function.finfo-open.php). If this doesn't work, it will
* fall back to [[getMimeTypeByExtension()]].
* @param string $file the file name.
* @param string $magicFile name of the optional magic database file, usually something like `/path/to/magic.mime`.
* This will be passed as the second parameter to [finfo_open](http://php.net/manual/en/function.finfo-open.php).
* @param boolean $checkExtension whether to use the file extension to determine the MIME type in case
* `finfo_open()` cannot determine it.
* @return string the MIME type (e.g. `text/plain`). Null is returned if the MIME type cannot be determined.
*/
public static function getMimeType($file, $magicFile = null, $checkExtension = true)
{
if (function_exists('finfo_open')) {
$info = finfo_open(FILEINFO_MIME_TYPE, $magicFile);
if ($info && ($result = finfo_file($info, $file)) !== false) {
return $result;
}
}
return $checkExtension ? self::getMimeTypeByExtension($file) : null;
}
/**
* Determines the MIME type based on the extension name of the specified file.
* This method will use a local map between extension names and MIME types.
* @param string $file the file name.
* @param string $magicFile the path of the file that contains all available MIME type information.
* If this is not set, the default file aliased by `@yii/util/mimeTypes.php` will be used.
* @return string the MIME type. Null is returned if the MIME type cannot be determined.
*/
public static function getMimeTypeByExtension($file, $magicFile = null)
{
if ($magicFile === null) {
$magicFile = \Yii::getAlias('@yii/util/mimeTypes.php');
}
$mimeTypes = require($magicFile);
if (($ext = pathinfo($file, PATHINFO_EXTENSION)) !== '') {
$ext = strtolower($ext);
if (isset($mimeTypes[$ext])) {
return $mimeTypes[$ext];
}
}
return null;
}
} }
<?php
/**
* MIME types.
*
* This file contains most commonly used MIME types
* according to file extension names.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
* @since 2.0
*/
return array(
'ai' => 'application/postscript',
'aif' => 'audio/x-aiff',
'aifc' => 'audio/x-aiff',
'aiff' => 'audio/x-aiff',
'anx' => 'application/annodex',
'asc' => 'text/plain',
'au' => 'audio/basic',
'avi' => 'video/x-msvideo',
'axa' => 'audio/annodex',
'axv' => 'video/annodex',
'bcpio' => 'application/x-bcpio',
'bin' => 'application/octet-stream',
'bmp' => 'image/bmp',
'c' => 'text/plain',
'cc' => 'text/plain',
'ccad' => 'application/clariscad',
'cdf' => 'application/x-netcdf',
'class' => 'application/octet-stream',
'cpio' => 'application/x-cpio',
'cpt' => 'application/mac-compactpro',
'csh' => 'application/x-csh',
'css' => 'text/css',
'dcr' => 'application/x-director',
'dir' => 'application/x-director',
'dms' => 'application/octet-stream',
'doc' => 'application/msword',
'drw' => 'application/drafting',
'dvi' => 'application/x-dvi',
'dwg' => 'application/acad',
'dxf' => 'application/dxf',
'dxr' => 'application/x-director',
'eps' => 'application/postscript',
'etx' => 'text/x-setext',
'exe' => 'application/octet-stream',
'ez' => 'application/andrew-inset',
'f' => 'text/plain',
'f90' => 'text/plain',
'flac' => 'audio/flac',
'fli' => 'video/x-fli',
'flv' => 'video/x-flv',
'gif' => 'image/gif',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
'h' => 'text/plain',
'hdf' => 'application/x-hdf',
'hh' => 'text/plain',
'hqx' => 'application/mac-binhex40',
'htm' => 'text/html',
'html' => 'text/html',
'ice' => 'x-conference/x-cooltalk',
'ief' => 'image/ief',
'iges' => 'model/iges',
'igs' => 'model/iges',
'ips' => 'application/x-ipscript',
'ipx' => 'application/x-ipix',
'jpe' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'jpg' => 'image/jpeg',
'js' => 'application/x-javascript',
'kar' => 'audio/midi',
'latex' => 'application/x-latex',
'lha' => 'application/octet-stream',
'lsp' => 'application/x-lisp',
'lzh' => 'application/octet-stream',
'm' => 'text/plain',
'man' => 'application/x-troff-man',
'me' => 'application/x-troff-me',
'mesh' => 'model/mesh',
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mif' => 'application/vnd.mif',
'mime' => 'www/mime',
'mov' => 'video/quicktime',
'movie' => 'video/x-sgi-movie',
'mp2' => 'audio/mpeg',
'mp3' => 'audio/mpeg',
'mpe' => 'video/mpeg',
'mpeg' => 'video/mpeg',
'mpg' => 'video/mpeg',
'mpga' => 'audio/mpeg',
'ms' => 'application/x-troff-ms',
'msh' => 'model/mesh',
'nc' => 'application/x-netcdf',
'oga' => 'audio/ogg',
'ogg' => 'audio/ogg',
'ogv' => 'video/ogg',
'ogx' => 'application/ogg',
'oda' => 'application/oda',
'pbm' => 'image/x-portable-bitmap',
'pdb' => 'chemical/x-pdb',
'pdf' => 'application/pdf',
'pgm' => 'image/x-portable-graymap',
'pgn' => 'application/x-chess-pgn',
'png' => 'image/png',
'pnm' => 'image/x-portable-anymap',
'pot' => 'application/mspowerpoint',
'ppm' => 'image/x-portable-pixmap',
'pps' => 'application/mspowerpoint',
'ppt' => 'application/mspowerpoint',
'ppz' => 'application/mspowerpoint',
'pre' => 'application/x-freelance',
'prt' => 'application/pro_eng',
'ps' => 'application/postscript',
'qt' => 'video/quicktime',
'ra' => 'audio/x-realaudio',
'ram' => 'audio/x-pn-realaudio',
'ras' => 'image/cmu-raster',
'rgb' => 'image/x-rgb',
'rm' => 'audio/x-pn-realaudio',
'roff' => 'application/x-troff',
'rpm' => 'audio/x-pn-realaudio-plugin',
'rtf' => 'text/rtf',
'rtx' => 'text/richtext',
'scm' => 'application/x-lotusscreencam',
'set' => 'application/set',
'sgm' => 'text/sgml',
'sgml' => 'text/sgml',
'sh' => 'application/x-sh',
'shar' => 'application/x-shar',
'silo' => 'model/mesh',
'sit' => 'application/x-stuffit',
'skd' => 'application/x-koan',
'skm' => 'application/x-koan',
'skp' => 'application/x-koan',
'skt' => 'application/x-koan',
'smi' => 'application/smil',
'smil' => 'application/smil',
'snd' => 'audio/basic',
'sol' => 'application/solids',
'spl' => 'application/x-futuresplash',
'spx' => 'audio/ogg',
'src' => 'application/x-wais-source',
'step' => 'application/STEP',
'stl' => 'application/SLA',
'stp' => 'application/STEP',
'sv4cpio' => 'application/x-sv4cpio',
'sv4crc' => 'application/x-sv4crc',
'swf' => 'application/x-shockwave-flash',
't' => 'application/x-troff',
'tar' => 'application/x-tar',
'tcl' => 'application/x-tcl',
'tex' => 'application/x-tex',
'texi' => 'application/x-texinfo',
'texinfo' => 'application/x-texinfo',
'tif' => 'image/tiff',
'tiff' => 'image/tiff',
'tr' => 'application/x-troff',
'tsi' => 'audio/TSP-audio',
'tsp' => 'application/dsptype',
'tsv' => 'text/tab-separated-values',
'txt' => 'text/plain',
'unv' => 'application/i-deas',
'ustar' => 'application/x-ustar',
'vcd' => 'application/x-cdlink',
'vda' => 'application/vda',
'viv' => 'video/vnd.vivo',
'vivo' => 'video/vnd.vivo',
'vrml' => 'model/vrml',
'wav' => 'audio/x-wav',
'wrl' => 'model/vrml',
'xbm' => 'image/x-xbitmap',
'xlc' => 'application/vnd.ms-excel',
'xll' => 'application/vnd.ms-excel',
'xlm' => 'application/vnd.ms-excel',
'xls' => 'application/vnd.ms-excel',
'xlw' => 'application/vnd.ms-excel',
'xml' => 'application/xml',
'xpm' => 'image/x-xpixmap',
'xspf' => 'application/xspf+xml',
'xwd' => 'image/x-xwindowdump',
'xyz' => 'chemical/x-pdb',
'zip' => 'application/zip',
);
<?php <?php
/** /**
* CHttpCookie class file. * Cookie class file.
* *
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
/** /**
* A CHttpCookie instance stores a single cookie, including the cookie name, value, domain, path, expire, and secure. * Cookie represents information related with a cookie, such as [[name]], [[value]], [[domain]], etc.
* *
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id$ * @since 2.0
* @package system.web
* @since 1.0
*/ */
class CHttpCookie extends CComponent class Cookie extends \yii\base\Object
{ {
/** /**
* @var string name of the cookie * @var string name of the cookie
...@@ -25,39 +22,41 @@ class CHttpCookie extends CComponent ...@@ -25,39 +22,41 @@ class CHttpCookie extends CComponent
/** /**
* @var string value of the cookie * @var string value of the cookie
*/ */
public $value=''; public $value = '';
/** /**
* @var string domain of the cookie * @var string domain of the cookie
*/ */
public $domain=''; public $domain = '';
/** /**
* @var integer the timestamp at which the cookie expires. This is the server timestamp. Defaults to 0, meaning "until the browser is closed". * @var integer the timestamp at which the cookie expires. This is the server timestamp.
* Defaults to 0, meaning "until the browser is closed".
*/ */
public $expire=0; public $expire = 0;
/** /**
* @var string the path on the server in which the cookie will be available on. The default is '/'. * @var string the path on the server in which the cookie will be available on. The default is '/'.
*/ */
public $path='/'; public $path = '/';
/** /**
* @var boolean whether cookie should be sent via secure connection * @var boolean whether cookie should be sent via secure connection
*/ */
public $secure=false; public $secure = false;
/** /**
* @var boolean whether the cookie should be accessible only through the HTTP protocol. * @var boolean whether the cookie should be accessible only through the HTTP protocol.
* By setting this property to true, the cookie will not be accessible by scripting languages, * By setting this property to true, the cookie will not be accessible by scripting languages,
* such as JavaScript, which can effectly help to reduce identity theft through XSS attacks. * such as JavaScript, which can effectively help to reduce identity theft through XSS attacks.
* Note, this property is only effective for PHP 5.2.0 or above.
*/ */
public $httpOnly=false; public $httpOnly = false;
/** /**
* Constructor. * Constructor.
* @param string $name name of this cookie * @param string $name name of this cookie
* @param string $value value of this cookie * @param string $value value of this cookie
* @param array $config name-value pairs that will be used to initialize the object properties
*/ */
public function __construct($name,$value) public function __construct($name, $value, $config = array())
{ {
$this->name=$name; $this->name = $name;
$this->value=$value; $this->value = $value;
parent::__construct($config);
} }
} }
...@@ -70,16 +70,16 @@ class CPagination extends CComponent ...@@ -70,16 +70,16 @@ class CPagination extends CComponent
/** /**
* The default page size. * The default page size.
*/ */
const DEFAULT_PAGE_SIZE=10; const DEFAULT_PAGE_SIZE = 10;
/** /**
* @var string name of the GET variable storing the current page index. Defaults to 'page'. * @var string name of the GET variable storing the current page index. Defaults to 'page'.
*/ */
public $pageVar='page'; public $pageVar = 'page';
/** /**
* @var string the route (controller ID and action ID) for displaying the paged contents. * @var string the route (controller ID and action ID) for displaying the paged contents.
* Defaults to empty string, meaning using the current route. * Defaults to empty string, meaning using the current route.
*/ */
public $route=''; public $route = '';
/** /**
* @var array of parameters (name=>value) that should be used instead of GET when generating pagination URLs. * @var array of parameters (name=>value) that should be used instead of GET when generating pagination URLs.
* Defaults to null, meaning using the currently available GET parameters. * Defaults to null, meaning using the currently available GET parameters.
...@@ -95,17 +95,17 @@ class CPagination extends CComponent ...@@ -95,17 +95,17 @@ class CPagination extends CComponent
* Defaults to true. * Defaults to true.
* @since 1.1.4 * @since 1.1.4
*/ */
public $validateCurrentPage=true; public $validateCurrentPage = true;
private $_pageSize=self::DEFAULT_PAGE_SIZE; private $_pageSize = self::DEFAULT_PAGE_SIZE;
private $_itemCount=0; private $_itemCount = 0;
private $_currentPage; private $_currentPage;
/** /**
* Constructor. * Constructor.
* @param integer $itemCount total number of items. * @param integer $itemCount total number of items.
*/ */
public function __construct($itemCount=0) public function __construct($itemCount = 0)
{ {
$this->setItemCount($itemCount); $this->setItemCount($itemCount);
} }
...@@ -123,8 +123,9 @@ class CPagination extends CComponent ...@@ -123,8 +123,9 @@ class CPagination extends CComponent
*/ */
public function setPageSize($value) public function setPageSize($value)
{ {
if(($this->_pageSize=$value)<=0) if (($this->_pageSize = $value) <= 0) {
$this->_pageSize=self::DEFAULT_PAGE_SIZE; $this->_pageSize = self::DEFAULT_PAGE_SIZE;
}
} }
/** /**
...@@ -140,8 +141,9 @@ class CPagination extends CComponent ...@@ -140,8 +141,9 @@ class CPagination extends CComponent
*/ */
public function setItemCount($value) public function setItemCount($value)
{ {
if(($this->_itemCount=$value)<0) if (($this->_itemCount = $value) < 0) {
$this->_itemCount=0; $this->_itemCount = 0;
}
} }
/** /**
...@@ -149,31 +151,30 @@ class CPagination extends CComponent ...@@ -149,31 +151,30 @@ class CPagination extends CComponent
*/ */
public function getPageCount() public function getPageCount()
{ {
return (int)(($this->_itemCount+$this->_pageSize-1)/$this->_pageSize); return (int)(($this->_itemCount + $this->_pageSize - 1) / $this->_pageSize);
} }
/** /**
* @param boolean $recalculate whether to recalculate the current page based on the page size and item count. * @param boolean $recalculate whether to recalculate the current page based on the page size and item count.
* @return integer the zero-based index of the current page. Defaults to 0. * @return integer the zero-based index of the current page. Defaults to 0.
*/ */
public function getCurrentPage($recalculate=true) public function getCurrentPage($recalculate = true)
{
if($this->_currentPage===null || $recalculate)
{
if(isset($_GET[$this->pageVar]))
{
$this->_currentPage=(int)$_GET[$this->pageVar]-1;
if($this->validateCurrentPage)
{ {
$pageCount=$this->getPageCount(); if ($this->_currentPage === null || $recalculate) {
if($this->_currentPage>=$pageCount) if (isset($_GET[$this->pageVar])) {
$this->_currentPage=$pageCount-1; $this->_currentPage = (int)$_GET[$this->pageVar] - 1;
if ($this->validateCurrentPage) {
$pageCount = $this->getPageCount();
if ($this->_currentPage >= $pageCount) {
$this->_currentPage = $pageCount - 1;
} }
if($this->_currentPage<0)
$this->_currentPage=0;
} }
else if ($this->_currentPage < 0) {
$this->_currentPage=0; $this->_currentPage = 0;
}
} else {
$this->_currentPage = 0;
}
} }
return $this->_currentPage; return $this->_currentPage;
} }
...@@ -183,8 +184,8 @@ class CPagination extends CComponent ...@@ -183,8 +184,8 @@ class CPagination extends CComponent
*/ */
public function setCurrentPage($value) public function setCurrentPage($value)
{ {
$this->_currentPage=$value; $this->_currentPage = $value;
$_GET[$this->pageVar]=$value+1; $_GET[$this->pageVar] = $value + 1;
} }
/** /**
...@@ -198,14 +199,16 @@ class CPagination extends CComponent ...@@ -198,14 +199,16 @@ class CPagination extends CComponent
* @param integer $page the page that the URL should point to. This is a zero-based index. * @param integer $page the page that the URL should point to. This is a zero-based index.
* @return string the created URL * @return string the created URL
*/ */
public function createPageUrl($controller,$page) public function createPageUrl($controller, $page)
{ {
$params=$this->params===null ? $_GET : $this->params; $params = $this->params === null ? $_GET : $this->params;
if($page>0) // page 0 is the default if ($page > 0) // page 0 is the default
$params[$this->pageVar]=$page+1; {
else $params[$this->pageVar] = $page + 1;
} else {
unset($params[$this->pageVar]); unset($params[$this->pageVar]);
return $controller->createUrl($this->route,$params); }
return $controller->createUrl($this->route, $params);
} }
/** /**
...@@ -214,8 +217,8 @@ class CPagination extends CComponent ...@@ -214,8 +217,8 @@ class CPagination extends CComponent
*/ */
public function applyLimit($criteria) public function applyLimit($criteria)
{ {
$criteria->limit=$this->getLimit(); $criteria->limit = $this->getLimit();
$criteria->offset=$this->getOffset(); $criteria->offset = $this->getOffset();
} }
/** /**
...@@ -225,7 +228,7 @@ class CPagination extends CComponent ...@@ -225,7 +228,7 @@ class CPagination extends CComponent
*/ */
public function getOffset() public function getOffset()
{ {
return $this->getCurrentPage()*$this->getPageSize(); return $this->getCurrentPage() * $this->getPageSize();
} }
/** /**
......
<?php <?php
/** /**
* CHttpRequest and CCookieCollection class file. * Request class file.
* *
* @author Qiang Xue <qiang.xue@gmail.com>
* @link http://www.yiiframework.com/ * @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2011 Yii Software LLC * @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/ * @license http://www.yiiframework.com/license/
*/ */
namespace yii\web;
/** /**
* CHttpRequest encapsulates the $_SERVER variable and resolves its inconsistency among different Web servers.
*
* CHttpRequest also manages the cookies sent from and sent to the user.
* By setting {@link enableCookieValidation} to true,
* cookies sent from the user will be validated to see if they are tampered.
* The property {@link getCookies cookies} returns the collection of cookies.
* For more details, see {@link CCookieCollection}.
*
* CHttpRequest is a default application component loaded by {@link CWebApplication}. It can be
* accessed via {@link CWebApplication::getRequest()}.
*
* @property string $url Part of the request URL after the host info.
* @property string $hostInfo Schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com).
* @property string $baseUrl The relative URL for the application.
* @property string $scriptUrl The relative URL of the entry script.
* @property string $pathInfo Part of the request URL that is after the entry script and before the question mark.
* Note, the returned pathinfo is decoded starting from 1.1.4.
* Prior to 1.1.4, whether it is decoded or not depends on the server configuration
* (in most cases it is not decoded).
* @property string $requestUri The request URI portion for the currently requested URL.
* @property string $queryString Part of the request URL that is after the question mark.
* @property boolean $isSecureConnection If the request is sent via secure channel (https).
* @property string $requestType Request type, such as GET, POST, HEAD, PUT, DELETE.
* @property boolean $isPostRequest Whether this is a POST request.
* @property boolean $isDeleteRequest Whether this is a DELETE request.
* @property boolean $isPutRequest Whether this is a PUT request.
* @property boolean $isAjaxRequest Whether this is an AJAX (XMLHttpRequest) request.
* @property boolean $isFlashRequest Whether this is an Adobe Flash or Adobe Flex request.
* @property string $serverName Server name.
* @property integer $serverPort Server port number.
* @property string $urlReferrer URL referrer, null if not present.
* @property string $userAgent User agent, null if not present.
* @property string $userHostAddress User IP address.
* @property string $userHost User host name, null if cannot be determined.
* @property string $scriptFile Entry script file path (processed w/ realpath()).
* @property array $browser User browser capabilities.
* @property string $acceptTypes User browser accept types, null if not present.
* @property integer $port Port number for insecure requests.
* @property integer $securePort Port number for secure requests.
* @property CCookieCollection $cookies The cookie collection.
* @property string $preferredLanguage The user preferred language.
* @property string $csrfToken The random token for CSRF validation.
*
* @author Qiang Xue <qiang.xue@gmail.com> * @author Qiang Xue <qiang.xue@gmail.com>
* @version $Id$ * @since 2.0
* @package system.web
* @since 1.0
*/ */
class CHttpRequest extends CApplicationComponent class Request extends \yii\base\Request
{ {
/** /**
* @var boolean whether cookies should be validated to ensure they are not tampered. Defaults to false. * @var boolean whether cookies should be validated to ensure they are not tampered. Defaults to false.
*/ */
public $enableCookieValidation=false; public $enableCookieValidation = false;
/** /**
* @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false. * @var boolean whether to enable CSRF (Cross-Site Request Forgery) validation. Defaults to false.
* By setting this property to true, forms submitted to an Yii Web application must be originated * By setting this property to true, forms submitted to an Yii Web application must be originated
...@@ -73,12 +28,12 @@ class CHttpRequest extends CApplicationComponent ...@@ -73,12 +28,12 @@ class CHttpRequest extends CApplicationComponent
* the needed HTML forms in your pages. * the needed HTML forms in your pages.
* @see http://seclab.stanford.edu/websec/csrf/csrf.pdf * @see http://seclab.stanford.edu/websec/csrf/csrf.pdf
*/ */
public $enableCsrfValidation=false; public $enableCsrfValidation = false;
/** /**
* @var string the name of the token used to prevent CSRF. Defaults to 'YII_CSRF_TOKEN'. * @var string the name of the token used to prevent CSRF. Defaults to 'YII_CSRF_TOKEN'.
* This property is effectively only when {@link enableCsrfValidation} is true. * This property is effective only when {@link enableCsrfValidation} is true.
*/ */
public $csrfTokenName='YII_CSRF_TOKEN'; public $csrfTokenName = 'YII_CSRF_TOKEN';
/** /**
* @var array the property values (in name-value pairs) used to initialize the CSRF cookie. * @var array the property values (in name-value pairs) used to initialize the CSRF cookie.
* Any property of {@link CHttpCookie} may be initialized. * Any property of {@link CHttpCookie} may be initialized.
...@@ -116,23 +71,25 @@ class CHttpRequest extends CApplicationComponent ...@@ -116,23 +71,25 @@ class CHttpRequest extends CApplicationComponent
*/ */
protected function normalizeRequest() protected function normalizeRequest()
{ {
// normalize request if (get_magic_quotes_gpc()) {
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) if (isset($_GET)) {
{ $_GET = $this->stripSlashes($_GET);
if(isset($_GET)) }
$_GET=$this->stripSlashes($_GET); if (isset($_POST)) {
if(isset($_POST)) $_POST = $this->stripSlashes($_POST);
$_POST=$this->stripSlashes($_POST); }
if(isset($_REQUEST)) if (isset($_REQUEST)) {
$_REQUEST=$this->stripSlashes($_REQUEST); $_REQUEST = $this->stripSlashes($_REQUEST);
if(isset($_COOKIE)) }
$_COOKIE=$this->stripSlashes($_COOKIE); if (isset($_COOKIE)) {
$_COOKIE = $this->stripSlashes($_COOKIE);
} }
if($this->enableCsrfValidation)
\Yii::$application->attachEventHandler('onBeginRequest',array($this,'validateCsrfToken'));
} }
if ($this->enableCsrfValidation) {
\Yii::$application->on('beginRequest', array($this, 'validateCsrfToken'));
}
}
/** /**
* Strips slashes from input data. * Strips slashes from input data.
...@@ -140,9 +97,9 @@ class CHttpRequest extends CApplicationComponent ...@@ -140,9 +97,9 @@ class CHttpRequest extends CApplicationComponent
* @param mixed $data input data to be processed * @param mixed $data input data to be processed
* @return mixed processed data * @return mixed processed data
*/ */
public function stripSlashes(&$data) public function stripSlashes($data)
{ {
return is_array($data)?array_map(array($this,'stripSlashes'),$data):stripslashes($data); return is_array($data) ? array_map(array($this, 'stripSlashes'), $data) : stripslashes($data);
} }
/** /**
...@@ -155,7 +112,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -155,7 +112,7 @@ class CHttpRequest extends CApplicationComponent
* @see getQuery * @see getQuery
* @see getPost * @see getPost
*/ */
public function getParam($name,$defaultValue=null) public function getParam($name, $defaultValue = null)
{ {
return isset($_GET[$name]) ? $_GET[$name] : (isset($_POST[$name]) ? $_POST[$name] : $defaultValue); return isset($_GET[$name]) ? $_GET[$name] : (isset($_POST[$name]) ? $_POST[$name] : $defaultValue);
} }
...@@ -169,7 +126,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -169,7 +126,7 @@ class CHttpRequest extends CApplicationComponent
* @see getPost * @see getPost
* @see getParam * @see getParam
*/ */
public function getQuery($name,$defaultValue=null) public function getQuery($name, $defaultValue = null)
{ {
return isset($_GET[$name]) ? $_GET[$name] : $defaultValue; return isset($_GET[$name]) ? $_GET[$name] : $defaultValue;
} }
...@@ -183,7 +140,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -183,7 +140,7 @@ class CHttpRequest extends CApplicationComponent
* @see getParam * @see getParam
* @see getQuery * @see getQuery
*/ */
public function getPost($name,$defaultValue=null) public function getPost($name, $defaultValue = null)
{ {
return isset($_POST[$name]) ? $_POST[$name] : $defaultValue; return isset($_POST[$name]) ? $_POST[$name] : $defaultValue;
} }
...@@ -199,13 +156,15 @@ class CHttpRequest extends CApplicationComponent ...@@ -199,13 +156,15 @@ class CHttpRequest extends CApplicationComponent
* @return mixed the DELETE parameter value * @return mixed the DELETE parameter value
* @since 1.1.7 * @since 1.1.7
*/ */
public function getDelete($name,$defaultValue=null) public function getDelete($name, $defaultValue = null)
{ {
if($this->getIsDeleteViaPostRequest()) if ($this->getIsDeleteViaPostRequest()) {
return $this->getPost($name, $defaultValue); return $this->getPost($name, $defaultValue);
}
if($this->_deleteParams===null) if ($this->_deleteParams === null) {
$this->_deleteParams=$this->getIsDeleteRequest() ? $this->getRestParams() : array(); $this->_deleteParams = $this->getIsDeleteRequest() ? $this->getRestParams() : array();
}
return isset($this->_deleteParams[$name]) ? $this->_deleteParams[$name] : $defaultValue; return isset($this->_deleteParams[$name]) ? $this->_deleteParams[$name] : $defaultValue;
} }
...@@ -220,13 +179,15 @@ class CHttpRequest extends CApplicationComponent ...@@ -220,13 +179,15 @@ class CHttpRequest extends CApplicationComponent
* @return mixed the PUT parameter value * @return mixed the PUT parameter value
* @since 1.1.7 * @since 1.1.7
*/ */
public function getPut($name,$defaultValue=null) public function getPut($name, $defaultValue = null)
{ {
if($this->getIsPutViaPostReqest()) if ($this->getIsPutViaPostReqest()) {
return $this->getPost($name, $defaultValue); return $this->getPost($name, $defaultValue);
}
if($this->_putParams===null) if ($this->_putParams === null) {
$this->_putParams=$this->getIsPutRequest() ? $this->getRestParams() : array(); $this->_putParams = $this->getIsPutRequest() ? $this->getRestParams() : array();
}
return isset($this->_putParams[$name]) ? $this->_putParams[$name] : $defaultValue; return isset($this->_putParams[$name]) ? $this->_putParams[$name] : $defaultValue;
} }
...@@ -237,11 +198,12 @@ class CHttpRequest extends CApplicationComponent ...@@ -237,11 +198,12 @@ class CHttpRequest extends CApplicationComponent
*/ */
protected function getRestParams() protected function getRestParams()
{ {
$result=array(); $result = array();
if(function_exists('mb_parse_str')) if (function_exists('mb_parse_str')) {
mb_parse_str(file_get_contents('php://input'), $result); mb_parse_str(file_get_contents('php://input'), $result);
else } else {
parse_str(file_get_contents('php://input'), $result); parse_str(file_get_contents('php://input'), $result);
}
return $result; return $result;
} }
...@@ -264,42 +226,43 @@ class CHttpRequest extends CApplicationComponent ...@@ -264,42 +226,43 @@ class CHttpRequest extends CApplicationComponent
* @return string schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com) * @return string schema and hostname part (with port number if needed) of the request URL (e.g. http://www.yiiframework.com)
* @see setHostInfo * @see setHostInfo
*/ */
public function getHostInfo($schema='') public function getHostInfo($schema = '')
{ {
if($this->_hostInfo===null) if ($this->_hostInfo === null) {
{ if ($secure = $this->getIsSecureConnection()) {
if($secure=$this->getIsSecureConnection()) $http = 'https';
$http='https'; } else {
else $http = 'http';
$http='http';
if(isset($_SERVER['HTTP_HOST']))
$this->_hostInfo=$http.'://'.$_SERVER['HTTP_HOST'];
else
{
$this->_hostInfo=$http.'://'.$_SERVER['SERVER_NAME'];
$port=$secure ? $this->getSecurePort() : $this->getPort();
if(($port!==80 && !$secure) || ($port!==443 && $secure))
$this->_hostInfo.=':'.$port;
} }
if (isset($_SERVER['HTTP_HOST'])) {
$this->_hostInfo = $http . '://' . $_SERVER['HTTP_HOST'];
} else {
$this->_hostInfo = $http . '://' . $_SERVER['SERVER_NAME'];
$port = $secure ? $this->getSecurePort() : $this->getPort();
if (($port !== 80 && !$secure) || ($port !== 443 && $secure)) {
$this->_hostInfo .= ':' . $port;
} }
if($schema!=='') }
{ }
$secure=$this->getIsSecureConnection(); if ($schema !== '') {
if($secure && $schema==='https' || !$secure && $schema==='http') $secure = $this->getIsSecureConnection();
if ($secure && $schema === 'https' || !$secure && $schema === 'http') {
return $this->_hostInfo; return $this->_hostInfo;
}
$port=$schema==='https' ? $this->getSecurePort() : $this->getPort(); $port = $schema === 'https' ? $this->getSecurePort() : $this->getPort();
if($port!==80 && $schema==='http' || $port!==443 && $schema==='https') if ($port !== 80 && $schema === 'http' || $port !== 443 && $schema === 'https') {
$port=':'.$port; $port = ':' . $port;
else } else {
$port=''; $port = '';
$pos=strpos($this->_hostInfo,':');
return $schema.substr($this->_hostInfo,$pos,strcspn($this->_hostInfo,':',$pos+1)+1).$port;
} }
else
$pos = strpos($this->_hostInfo, ':');
return $schema . substr($this->_hostInfo, $pos, strcspn($this->_hostInfo, ':', $pos + 1) + 1) . $port;
} else {
return $this->_hostInfo; return $this->_hostInfo;
} }
}
/** /**
* Sets the schema and host part of the application URL. * Sets the schema and host part of the application URL.
...@@ -309,7 +272,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -309,7 +272,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function setHostInfo($value) public function setHostInfo($value)
{ {
$this->_hostInfo=rtrim($value,'/'); $this->_hostInfo = rtrim($value, '/');
} }
/** /**
...@@ -320,10 +283,11 @@ class CHttpRequest extends CApplicationComponent ...@@ -320,10 +283,11 @@ class CHttpRequest extends CApplicationComponent
* @return string the relative URL for the application * @return string the relative URL for the application
* @see setScriptUrl * @see setScriptUrl
*/ */
public function getBaseUrl($absolute=false) public function getBaseUrl($absolute = false)
{ {
if($this->_baseUrl===null) if ($this->_baseUrl === null) {
$this->_baseUrl=rtrim(dirname($this->getScriptUrl()),'\\/'); $this->_baseUrl = rtrim(dirname($this->getScriptUrl()), '\\/');
}
return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl; return $absolute ? $this->getHostInfo() . $this->_baseUrl : $this->_baseUrl;
} }
...@@ -335,7 +299,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -335,7 +299,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function setBaseUrl($value) public function setBaseUrl($value)
{ {
$this->_baseUrl=$value; $this->_baseUrl = $value;
} }
/** /**
...@@ -345,21 +309,29 @@ class CHttpRequest extends CApplicationComponent ...@@ -345,21 +309,29 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getScriptUrl() public function getScriptUrl()
{ {
if($this->_scriptUrl===null) if ($this->_scriptUrl === null) {
{ $scriptName = basename($_SERVER['SCRIPT_FILENAME']);
$scriptName=basename($_SERVER['SCRIPT_FILENAME']); if (basename($_SERVER['SCRIPT_NAME']) === $scriptName) {
if(basename($_SERVER['SCRIPT_NAME'])===$scriptName) $this->_scriptUrl = $_SERVER['SCRIPT_NAME'];
$this->_scriptUrl=$_SERVER['SCRIPT_NAME']; } else {
else if(basename($_SERVER['PHP_SELF'])===$scriptName) if (basename($_SERVER['PHP_SELF']) === $scriptName) {
$this->_scriptUrl=$_SERVER['PHP_SELF']; $this->_scriptUrl = $_SERVER['PHP_SELF'];
else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName) } else {
$this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME']; if (isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME']) === $scriptName) {
else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false) $this->_scriptUrl = $_SERVER['ORIG_SCRIPT_NAME'];
$this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName; } else {
else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0) if (($pos = strpos($_SERVER['PHP_SELF'], '/' . $scriptName)) !== false) {
$this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME'])); $this->_scriptUrl = substr($_SERVER['SCRIPT_NAME'], 0, $pos) . '/' . $scriptName;
else } else {
throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.')); if (isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'], $_SERVER['DOCUMENT_ROOT']) === 0) {
$this->_scriptUrl = str_replace('\\', '/', str_replace($_SERVER['DOCUMENT_ROOT'], '', $_SERVER['SCRIPT_FILENAME']));
} else {
throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the entry script URL.'));
}
}
}
}
}
} }
return $this->_scriptUrl; return $this->_scriptUrl;
} }
...@@ -372,7 +344,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -372,7 +344,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function setScriptUrl($value) public function setScriptUrl($value)
{ {
$this->_scriptUrl='/'.trim($value,'/'); $this->_scriptUrl = '/' . trim($value, '/');
} }
/** /**
...@@ -387,27 +359,32 @@ class CHttpRequest extends CApplicationComponent ...@@ -387,27 +359,32 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getPathInfo() public function getPathInfo()
{ {
if($this->_pathInfo===null) if ($this->_pathInfo === null) {
{ $pathInfo = $this->getRequestUri();
$pathInfo=$this->getRequestUri();
if(($pos=strpos($pathInfo,'?'))!==false) if (($pos = strpos($pathInfo, '?')) !== false) {
$pathInfo=substr($pathInfo,0,$pos); $pathInfo = substr($pathInfo, 0, $pos);
}
$pathInfo=$this->decodePathInfo($pathInfo); $pathInfo = $this->decodePathInfo($pathInfo);
$scriptUrl=$this->getScriptUrl(); $scriptUrl = $this->getScriptUrl();
$baseUrl=$this->getBaseUrl(); $baseUrl = $this->getBaseUrl();
if(strpos($pathInfo,$scriptUrl)===0) if (strpos($pathInfo, $scriptUrl) === 0) {
$pathInfo=substr($pathInfo,strlen($scriptUrl)); $pathInfo = substr($pathInfo, strlen($scriptUrl));
else if($baseUrl==='' || strpos($pathInfo,$baseUrl)===0) } else {
$pathInfo=substr($pathInfo,strlen($baseUrl)); if ($baseUrl === '' || strpos($pathInfo, $baseUrl) === 0) {
else if(strpos($_SERVER['PHP_SELF'],$scriptUrl)===0) $pathInfo = substr($pathInfo, strlen($baseUrl));
$pathInfo=substr($_SERVER['PHP_SELF'],strlen($scriptUrl)); } else {
else if (strpos($_SERVER['PHP_SELF'], $scriptUrl) === 0) {
throw new CException(Yii::t('yii','CHttpRequest is unable to determine the path info of the request.')); $pathInfo = substr($_SERVER['PHP_SELF'], strlen($scriptUrl));
} else {
throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the path info of the request.'));
}
}
}
$this->_pathInfo=trim($pathInfo,'/'); $this->_pathInfo = trim($pathInfo, '/');
} }
return $this->_pathInfo; return $this->_pathInfo;
} }
...@@ -426,7 +403,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -426,7 +403,7 @@ class CHttpRequest extends CApplicationComponent
// is it UTF-8? // is it UTF-8?
// http://w3.org/International/questions/qa-forms-utf-8.html // http://w3.org/International/questions/qa-forms-utf-8.html
if(preg_match('%^(?: if (preg_match('%^(?:
[\x09\x0A\x0D\x20-\x7E] # ASCII [\x09\x0A\x0D\x20-\x7E] # ASCII
| [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte | [\xC2-\xDF][\x80-\xBF] # non-overlong 2-byte
| \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs | \xE0[\xA0-\xBF][\x80-\xBF] # excluding overlongs
...@@ -435,12 +412,10 @@ class CHttpRequest extends CApplicationComponent ...@@ -435,12 +412,10 @@ class CHttpRequest extends CApplicationComponent
| \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3 | \xF0[\x90-\xBF][\x80-\xBF]{2} # planes 1-3
| [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15 | [\xF1-\xF3][\x80-\xBF]{3} # planes 4-15
| \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16 | \xF4[\x80-\x8F][\x80-\xBF]{2} # plane 16
)*$%xs', $pathInfo)) )*$%xs', $pathInfo)
{ ) {
return $pathInfo; return $pathInfo;
} } else {
else
{
return utf8_encode($pathInfo); return utf8_encode($pathInfo);
} }
} }
...@@ -455,29 +430,32 @@ class CHttpRequest extends CApplicationComponent ...@@ -455,29 +430,32 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getRequestUri() public function getRequestUri()
{ {
if($this->_requestUri===null) if ($this->_requestUri === null) {
if (isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS
{ {
if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS $this->_requestUri = $_SERVER['HTTP_X_REWRITE_URL'];
$this->_requestUri=$_SERVER['HTTP_X_REWRITE_URL']; } else {
else if(isset($_SERVER['REQUEST_URI'])) if (isset($_SERVER['REQUEST_URI'])) {
{ $this->_requestUri = $_SERVER['REQUEST_URI'];
$this->_requestUri=$_SERVER['REQUEST_URI']; if (!empty($_SERVER['HTTP_HOST'])) {
if(!empty($_SERVER['HTTP_HOST'])) if (strpos($this->_requestUri, $_SERVER['HTTP_HOST']) !== false) {
{ $this->_requestUri = preg_replace('/^\w+:\/\/[^\/]+/', '', $this->_requestUri);
if(strpos($this->_requestUri,$_SERVER['HTTP_HOST'])!==false)
$this->_requestUri=preg_replace('/^\w+:\/\/[^\/]+/','',$this->_requestUri);
} }
else } else {
$this->_requestUri=preg_replace('/^(http|https):\/\/[^\/]+/i','',$this->_requestUri); $this->_requestUri = preg_replace('/^(http|https):\/\/[^\/]+/i', '', $this->_requestUri);
} }
else if(isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI } else {
if (isset($_SERVER['ORIG_PATH_INFO'])) // IIS 5.0 CGI
{ {
$this->_requestUri=$_SERVER['ORIG_PATH_INFO']; $this->_requestUri = $_SERVER['ORIG_PATH_INFO'];
if(!empty($_SERVER['QUERY_STRING'])) if (!empty($_SERVER['QUERY_STRING'])) {
$this->_requestUri.='?'.$_SERVER['QUERY_STRING']; $this->_requestUri .= '?' . $_SERVER['QUERY_STRING'];
}
} else {
throw new CException(Yii::t('yii', 'CHttpRequest is unable to determine the request URI.'));
}
}
} }
else
throw new CException(Yii::t('yii','CHttpRequest is unable to determine the request URI.'));
} }
return $this->_requestUri; return $this->_requestUri;
...@@ -489,7 +467,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -489,7 +467,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getQueryString() public function getQueryString()
{ {
return isset($_SERVER['QUERY_STRING'])?$_SERVER['QUERY_STRING']:''; return isset($_SERVER['QUERY_STRING']) ? $_SERVER['QUERY_STRING'] : '';
} }
/** /**
...@@ -498,7 +476,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -498,7 +476,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsSecureConnection() public function getIsSecureConnection()
{ {
return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'],'on'); return isset($_SERVER['HTTPS']) && !strcasecmp($_SERVER['HTTPS'], 'on');
} }
/** /**
...@@ -510,10 +488,11 @@ class CHttpRequest extends CApplicationComponent ...@@ -510,10 +488,11 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getRequestType() public function getRequestType()
{ {
if(isset($_POST['_method'])) if (isset($_POST['_method'])) {
return strtoupper($_POST['_method']); return strtoupper($_POST['_method']);
}
return strtoupper(isset($_SERVER['REQUEST_METHOD'])?$_SERVER['REQUEST_METHOD']:'GET'); return strtoupper(isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET');
} }
/** /**
...@@ -522,7 +501,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -522,7 +501,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsPostRequest() public function getIsPostRequest()
{ {
return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'POST'); return isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'POST');
} }
/** /**
...@@ -532,7 +511,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -532,7 +511,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsDeleteRequest() public function getIsDeleteRequest()
{ {
return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'DELETE')) || $this->getIsDeleteViaPostRequest(); return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'DELETE')) || $this->getIsDeleteViaPostRequest();
} }
/** /**
...@@ -542,7 +521,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -542,7 +521,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
protected function getIsDeleteViaPostRequest() protected function getIsDeleteViaPostRequest()
{ {
return isset($_POST['_method']) && !strcasecmp($_POST['_method'],'DELETE'); return isset($_POST['_method']) && !strcasecmp($_POST['_method'], 'DELETE');
} }
/** /**
...@@ -552,7 +531,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -552,7 +531,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsPutRequest() public function getIsPutRequest()
{ {
return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'],'PUT')) || $this->getIsPutViaPostReqest(); return (isset($_SERVER['REQUEST_METHOD']) && !strcasecmp($_SERVER['REQUEST_METHOD'], 'PUT')) || $this->getIsPutViaPostReqest();
} }
/** /**
...@@ -562,7 +541,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -562,7 +541,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
protected function getIsPutViaPostReqest() protected function getIsPutViaPostReqest()
{ {
return isset($_POST['_method']) && !strcasecmp($_POST['_method'],'PUT'); return isset($_POST['_method']) && !strcasecmp($_POST['_method'], 'PUT');
} }
/** /**
...@@ -571,7 +550,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -571,7 +550,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsAjaxRequest() public function getIsAjaxRequest()
{ {
return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest'; return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest';
} }
/** /**
...@@ -581,7 +560,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -581,7 +560,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getIsFlashRequest() public function getIsFlashRequest()
{ {
return isset($_SERVER['HTTP_USER_AGENT']) && (stripos($_SERVER['HTTP_USER_AGENT'],'Shockwave')!==false || stripos($_SERVER['HTTP_USER_AGENT'],'Flash')!==false); return isset($_SERVER['HTTP_USER_AGENT']) && (stripos($_SERVER['HTTP_USER_AGENT'], 'Shockwave') !== false || stripos($_SERVER['HTTP_USER_AGENT'], 'Flash') !== false);
} }
/** /**
...@@ -608,7 +587,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -608,7 +587,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getUrlReferrer() public function getUrlReferrer()
{ {
return isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:null; return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : null;
} }
/** /**
...@@ -617,7 +596,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -617,7 +596,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getUserAgent() public function getUserAgent()
{ {
return isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null; return isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : null;
} }
/** /**
...@@ -626,7 +605,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -626,7 +605,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getUserHostAddress() public function getUserHostAddress()
{ {
return isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:'127.0.0.1'; return isset($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
} }
/** /**
...@@ -635,7 +614,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -635,7 +614,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getUserHost() public function getUserHost()
{ {
return isset($_SERVER['REMOTE_HOST'])?$_SERVER['REMOTE_HOST']:null; return isset($_SERVER['REMOTE_HOST']) ? $_SERVER['REMOTE_HOST'] : null;
} }
/** /**
...@@ -644,10 +623,11 @@ class CHttpRequest extends CApplicationComponent ...@@ -644,10 +623,11 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getScriptFile() public function getScriptFile()
{ {
if($this->_scriptFile!==null) if ($this->_scriptFile !== null) {
return $this->_scriptFile; return $this->_scriptFile;
else } else {
return $this->_scriptFile=realpath($_SERVER['SCRIPT_FILENAME']); return $this->_scriptFile = realpath($_SERVER['SCRIPT_FILENAME']);
}
} }
/** /**
...@@ -657,9 +637,9 @@ class CHttpRequest extends CApplicationComponent ...@@ -657,9 +637,9 @@ class CHttpRequest extends CApplicationComponent
* @return array user browser capabilities. * @return array user browser capabilities.
* @see http://www.php.net/manual/en/function.get-browser.php * @see http://www.php.net/manual/en/function.get-browser.php
*/ */
public function getBrowser($userAgent=null) public function getBrowser($userAgent = null)
{ {
return get_browser($userAgent,true); return get_browser($userAgent, true);
} }
/** /**
...@@ -668,7 +648,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -668,7 +648,7 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getAcceptTypes() public function getAcceptTypes()
{ {
return isset($_SERVER['HTTP_ACCEPT'])?$_SERVER['HTTP_ACCEPT']:null; return isset($_SERVER['HTTP_ACCEPT']) ? $_SERVER['HTTP_ACCEPT'] : null;
} }
private $_port; private $_port;
...@@ -684,8 +664,9 @@ class CHttpRequest extends CApplicationComponent ...@@ -684,8 +664,9 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getPort() public function getPort()
{ {
if($this->_port===null) if ($this->_port === null) {
$this->_port=!$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 80; $this->_port = !$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 80;
}
return $this->_port; return $this->_port;
} }
...@@ -698,8 +679,8 @@ class CHttpRequest extends CApplicationComponent ...@@ -698,8 +679,8 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function setPort($value) public function setPort($value)
{ {
$this->_port=(int)$value; $this->_port = (int)$value;
$this->_hostInfo=null; $this->_hostInfo = null;
} }
private $_securePort; private $_securePort;
...@@ -715,8 +696,9 @@ class CHttpRequest extends CApplicationComponent ...@@ -715,8 +696,9 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getSecurePort() public function getSecurePort()
{ {
if($this->_securePort===null) if ($this->_securePort === null) {
$this->_securePort=$this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 443; $this->_securePort = $this->getIsSecureConnection() && isset($_SERVER['SERVER_PORT']) ? (int)$_SERVER['SERVER_PORT'] : 443;
}
return $this->_securePort; return $this->_securePort;
} }
...@@ -729,8 +711,8 @@ class CHttpRequest extends CApplicationComponent ...@@ -729,8 +711,8 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function setSecurePort($value) public function setSecurePort($value)
{ {
$this->_securePort=(int)$value; $this->_securePort = (int)$value;
$this->_hostInfo=null; $this->_hostInfo = null;
} }
/** /**
...@@ -742,10 +724,11 @@ class CHttpRequest extends CApplicationComponent ...@@ -742,10 +724,11 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getCookies() public function getCookies()
{ {
if($this->_cookies!==null) if ($this->_cookies !== null) {
return $this->_cookies; return $this->_cookies;
else } else {
return $this->_cookies=new CCookieCollection($this); return $this->_cookies = new CCookieCollection($this);
}
} }
/** /**
...@@ -756,14 +739,16 @@ class CHttpRequest extends CApplicationComponent ...@@ -756,14 +739,16 @@ class CHttpRequest extends CApplicationComponent
* @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} * @param integer $statusCode the HTTP status code. Defaults to 302. See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html}
* for details about HTTP status code. * for details about HTTP status code.
*/ */
public function redirect($url,$terminate=true,$statusCode=302) public function redirect($url, $terminate = true, $statusCode = 302)
{ {
if(strpos($url,'/')===0) if (strpos($url, '/') === 0) {
$url=$this->getHostInfo().$url; $url = $this->getHostInfo() . $url;
header('Location: '.$url, true, $statusCode); }
if($terminate) header('Location: ' . $url, true, $statusCode);
if ($terminate) {
\Yii::$application->end(); \Yii::$application->end();
} }
}
/** /**
* Returns the user preferred language. * Returns the user preferred language.
...@@ -773,18 +758,18 @@ class CHttpRequest extends CApplicationComponent ...@@ -773,18 +758,18 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getPreferredLanguage() public function getPreferredLanguage()
{ {
if($this->_preferredLanguage===null) if ($this->_preferredLanguage === null) {
{ if (isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n = preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches)) > 0) {
if(isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) && ($n=preg_match_all('/([\w\-_]+)\s*(;\s*q\s*=\s*(\d*\.\d*))?/',$_SERVER['HTTP_ACCEPT_LANGUAGE'],$matches))>0) $languages = array();
{ for ($i = 0; $i < $n; ++$i) {
$languages=array(); $languages[$matches[1][$i]] = empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
for($i=0;$i<$n;++$i) }
$languages[$matches[1][$i]]=empty($matches[3][$i]) ? 1.0 : floatval($matches[3][$i]);
arsort($languages); arsort($languages);
foreach($languages as $language=>$pref) foreach ($languages as $language => $pref) {
return $this->_preferredLanguage=CLocale::getCanonicalID($language); return $this->_preferredLanguage = CLocale::getCanonicalID($language);
} }
return $this->_preferredLanguage=false; }
return $this->_preferredLanguage = false;
} }
return $this->_preferredLanguage; return $this->_preferredLanguage;
} }
...@@ -796,33 +781,33 @@ class CHttpRequest extends CApplicationComponent ...@@ -796,33 +781,33 @@ class CHttpRequest extends CApplicationComponent
* @param string $mimeType mime type of the content. If null, it will be guessed automatically based on the given file name. * @param string $mimeType mime type of the content. If null, it will be guessed automatically based on the given file name.
* @param boolean $terminate whether to terminate the current application after calling this method * @param boolean $terminate whether to terminate the current application after calling this method
*/ */
public function sendFile($fileName,$content,$mimeType=null,$terminate=true) public function sendFile($fileName, $content, $mimeType = null, $terminate = true)
{
if($mimeType===null)
{ {
if(($mimeType=CFileHelper::getMimeTypeByExtension($fileName))===null) if ($mimeType === null) {
$mimeType='text/plain'; if (($mimeType = CFileHelper::getMimeTypeByExtension($fileName)) === null) {
$mimeType = 'text/plain';
}
} }
header('Pragma: public'); header('Pragma: public');
header('Expires: 0'); header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0'); header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-type: $mimeType"); header("Content-type: $mimeType");
if(ob_get_length()===false) if (ob_get_length() === false) {
header('Content-Length: '.(function_exists('mb_strlen') ? mb_strlen($content,'8bit') : strlen($content))); header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content)));
}
header("Content-Disposition: attachment; filename=\"$fileName\""); header("Content-Disposition: attachment; filename=\"$fileName\"");
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
if($terminate) if ($terminate) {
{
// clean up the application first because the file downloading could take long time // clean up the application first because the file downloading could take long time
// which may cause timeout of some resources (such as DB connection) // which may cause timeout of some resources (such as DB connection)
\Yii::$application->end(0,false); \Yii::$application->end(0, false);
echo $content; echo $content;
exit(0); exit(0);
} } else {
else
echo $content; echo $content;
} }
}
/** /**
* Sends existing file to a browser as a download using x-sendfile. * Sends existing file to a browser as a download using x-sendfile.
...@@ -876,38 +861,43 @@ class CHttpRequest extends CApplicationComponent ...@@ -876,38 +861,43 @@ class CHttpRequest extends CApplicationComponent
* <li>addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)</li> * <li>addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)</li>
* </ul> * </ul>
*/ */
public function xSendFile($filePath, $options=array()) public function xSendFile($filePath, $options = array())
{ {
if(!isset($options['forceDownload']) || $options['forceDownload']) if (!isset($options['forceDownload']) || $options['forceDownload']) {
$disposition='attachment'; $disposition = 'attachment';
else } else {
$disposition='inline'; $disposition = 'inline';
}
if(!isset($options['saveName'])) if (!isset($options['saveName'])) {
$options['saveName']=basename($filePath); $options['saveName'] = basename($filePath);
}
if(!isset($options['mimeType'])) if (!isset($options['mimeType'])) {
{ if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) {
if(($options['mimeType']=CFileHelper::getMimeTypeByExtension($filePath))===null) $options['mimeType'] = 'text/plain';
$options['mimeType']='text/plain'; }
} }
if(!isset($options['xHeader'])) if (!isset($options['xHeader'])) {
$options['xHeader']='X-Sendfile'; $options['xHeader'] = 'X-Sendfile';
}
if($options['mimeType'] !== null) if ($options['mimeType'] !== null) {
header('Content-type: '.$options['mimeType']); header('Content-type: ' . $options['mimeType']);
header('Content-Disposition: '.$disposition.'; filename="'.$options['saveName'].'"'); }
if(isset($options['addHeaders'])) header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"');
{ if (isset($options['addHeaders'])) {
foreach($options['addHeaders'] as $header=>$value) foreach ($options['addHeaders'] as $header => $value) {
header($header.': '.$value); header($header . ': ' . $value);
}
} }
header(trim($options['xHeader']).': '.$filePath); header(trim($options['xHeader']) . ': ' . $filePath);
if(!isset($options['terminate']) || $options['terminate']) if (!isset($options['terminate']) || $options['terminate']) {
\Yii::$application->end(); \Yii::$application->end();
} }
}
/** /**
* Returns the random token used to perform CSRF validation. * Returns the random token used to perform CSRF validation.
...@@ -918,14 +908,12 @@ class CHttpRequest extends CApplicationComponent ...@@ -918,14 +908,12 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function getCsrfToken() public function getCsrfToken()
{ {
if($this->_csrfToken===null) if ($this->_csrfToken === null) {
{ $cookie = $this->getCookies()->itemAt($this->csrfTokenName);
$cookie=$this->getCookies()->itemAt($this->csrfTokenName); if (!$cookie || ($this->_csrfToken = $cookie->value) == null) {
if(!$cookie || ($this->_csrfToken=$cookie->value)==null) $cookie = $this->createCsrfCookie();
{ $this->_csrfToken = $cookie->value;
$cookie=$this->createCsrfCookie(); $this->getCookies()->add($cookie->name, $cookie);
$this->_csrfToken=$cookie->value;
$this->getCookies()->add($cookie->name,$cookie);
} }
} }
...@@ -941,11 +929,11 @@ class CHttpRequest extends CApplicationComponent ...@@ -941,11 +929,11 @@ class CHttpRequest extends CApplicationComponent
*/ */
protected function createCsrfCookie() protected function createCsrfCookie()
{ {
$cookie=new CHttpCookie($this->csrfTokenName,sha1(uniqid(mt_rand(),true))); $cookie = new CHttpCookie($this->csrfTokenName, sha1(uniqid(mt_rand(), true)));
if(is_array($this->csrfCookie)) if (is_array($this->csrfCookie)) {
{ foreach ($this->csrfCookie as $name => $value) {
foreach($this->csrfCookie as $name=>$value) $cookie->$name = $value;
$cookie->$name=$value; }
} }
return $cookie; return $cookie;
} }
...@@ -960,20 +948,19 @@ class CHttpRequest extends CApplicationComponent ...@@ -960,20 +948,19 @@ class CHttpRequest extends CApplicationComponent
*/ */
public function validateCsrfToken($event) public function validateCsrfToken($event)
{ {
if($this->getIsPostRequest()) if ($this->getIsPostRequest()) {
{
// only validate POST requests // only validate POST requests
$cookies=$this->getCookies(); $cookies = $this->getCookies();
if($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName])) if ($cookies->contains($this->csrfTokenName) && isset($_POST[$this->csrfTokenName])) {
{ $tokenFromCookie = $cookies->itemAt($this->csrfTokenName)->value;
$tokenFromCookie=$cookies->itemAt($this->csrfTokenName)->value; $tokenFromPost = $_POST[$this->csrfTokenName];
$tokenFromPost=$_POST[$this->csrfTokenName]; $valid = $tokenFromCookie === $tokenFromPost;
$valid=$tokenFromCookie===$tokenFromPost; } else {
$valid = false;
}
if (!$valid) {
throw new CHttpException(400, Yii::t('yii', 'The CSRF token could not be verified.'));
} }
else
$valid=false;
if(!$valid)
throw new CHttpException(400,Yii::t('yii','The CSRF token could not be verified.'));
} }
} }
} }
...@@ -1000,7 +987,7 @@ class CHttpRequest extends CApplicationComponent ...@@ -1000,7 +987,7 @@ class CHttpRequest extends CApplicationComponent
class CCookieCollection extends CMap class CCookieCollection extends CMap
{ {
private $_request; private $_request;
private $_initialized=false; private $_initialized = false;
/** /**
* Constructor. * Constructor.
...@@ -1008,9 +995,9 @@ class CCookieCollection extends CMap ...@@ -1008,9 +995,9 @@ class CCookieCollection extends CMap
*/ */
public function __construct(CHttpRequest $request) public function __construct(CHttpRequest $request)
{ {
$this->_request=$request; $this->_request = $request;
$this->copyfrom($this->getCookies()); $this->copyfrom($this->getCookies());
$this->_initialized=true; $this->_initialized = true;
} }
/** /**
...@@ -1026,20 +1013,18 @@ class CCookieCollection extends CMap ...@@ -1026,20 +1013,18 @@ class CCookieCollection extends CMap
*/ */
protected function getCookies() protected function getCookies()
{ {
$cookies=array(); $cookies = array();
if($this->_request->enableCookieValidation) if ($this->_request->enableCookieValidation) {
{ $sm = \Yii::$application->getSecurityManager();
$sm=\Yii::$application->getSecurityManager(); foreach ($_COOKIE as $name => $value) {
foreach($_COOKIE as $name=>$value) if (is_string($value) && ($value = $sm->validateData($value)) !== false) {
{ $cookies[$name] = new CHttpCookie($name, @unserialize($value));
if(is_string($value) && ($value=$sm->validateData($value))!==false)
$cookies[$name]=new CHttpCookie($name,@unserialize($value));
} }
} }
else } else {
{ foreach ($_COOKIE as $name => $value) {
foreach($_COOKIE as $name=>$value) $cookies[$name] = new CHttpCookie($name, $value);
$cookies[$name]=new CHttpCookie($name,$value); }
} }
return $cookies; return $cookies;
} }
...@@ -1052,17 +1037,17 @@ class CCookieCollection extends CMap ...@@ -1052,17 +1037,17 @@ class CCookieCollection extends CMap
* @param CHttpCookie $cookie Cookie object. * @param CHttpCookie $cookie Cookie object.
* @throws CException if the item to be inserted is not a CHttpCookie object. * @throws CException if the item to be inserted is not a CHttpCookie object.
*/ */
public function add($name,$cookie) public function add($name, $cookie)
{
if($cookie instanceof CHttpCookie)
{ {
if ($cookie instanceof CHttpCookie) {
$this->remove($name); $this->remove($name);
parent::add($name,$cookie); parent::add($name, $cookie);
if($this->_initialized) if ($this->_initialized) {
$this->addCookie($cookie); $this->addCookie($cookie);
} }
else } else {
throw new CException(Yii::t('yii','CHttpCookieCollection can only hold CHttpCookie objects.')); throw new CException(Yii::t('yii', 'CHttpCookieCollection can only hold CHttpCookie objects.'));
}
} }
/** /**
...@@ -1074,11 +1059,11 @@ class CCookieCollection extends CMap ...@@ -1074,11 +1059,11 @@ class CCookieCollection extends CMap
*/ */
public function remove($name) public function remove($name)
{ {
if(($cookie=parent::remove($name))!==null) if (($cookie = parent::remove($name)) !== null) {
{ if ($this->_initialized) {
if($this->_initialized)
$this->removeCookie($cookie); $this->removeCookie($cookie);
} }
}
return $cookie; return $cookie;
} }
...@@ -1088,13 +1073,11 @@ class CCookieCollection extends CMap ...@@ -1088,13 +1073,11 @@ class CCookieCollection extends CMap
*/ */
protected function addCookie($cookie) protected function addCookie($cookie)
{ {
$value=$cookie->value; $value = $cookie->value;
if($this->_request->enableCookieValidation) if ($this->_request->enableCookieValidation) {
$value=\Yii::$application->getSecurityManager()->hashData(serialize($value)); $value = \Yii::$application->getSecurityManager()->hashData(serialize($value));
if(version_compare(PHP_VERSION,'5.2.0','>=')) }
setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly); setcookie($cookie->name, $value, $cookie->expire, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
else
setcookie($cookie->name,$value,$cookie->expire,$cookie->path,$cookie->domain,$cookie->secure);
} }
/** /**
...@@ -1103,9 +1086,6 @@ class CCookieCollection extends CMap ...@@ -1103,9 +1086,6 @@ class CCookieCollection extends CMap
*/ */
protected function removeCookie($cookie) protected function removeCookie($cookie)
{ {
if(version_compare(PHP_VERSION,'5.2.0','>=')) setcookie($cookie->name, null, 0, $cookie->path, $cookie->domain, $cookie->secure, $cookie->httpOnly);
setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure,$cookie->httpOnly);
else
setcookie($cookie->name,null,0,$cookie->path,$cookie->domain,$cookie->secure);
} }
} }
<?php
/**
* Response class file.
*
* @link http://www.yiiframework.com/
* @copyright Copyright &copy; 2008-2012 Yii Software LLC
* @license http://www.yiiframework.com/license/
*/
namespace yii\web;
use yii\util\FileHelper;
/**
* @author Qiang Xue <qiang.xue@gmail.com>
* @since 2.0
*/
class Response extends \yii\base\Response
{
/**
* Sends a file to user.
* @param string $fileName file name
* @param string $content content to be set.
* @param string $mimeType mime type of the content. If null, it will be guessed automatically based on the given file name.
* @param boolean $terminate whether to terminate the current application after calling this method
* @todo
*/
public function sendFile($fileName, $content, $mimeType = null, $terminate = true)
{
if ($mimeType === null && ($mimeType = FileHelper::getMimeType($fileName)) === null) {
$mimeType = 'application/octet-stream';
}
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-type: $mimeType");
if (ob_get_length() === false) {
header('Content-Length: ' . (function_exists('mb_strlen') ? mb_strlen($content, '8bit') : strlen($content)));
}
header("Content-Disposition: attachment; filename=\"$fileName\"");
header('Content-Transfer-Encoding: binary');
if ($terminate) {
// clean up the application first because the file downloading could take long time
// which may cause timeout of some resources (such as DB connection)
Yii::app()->end(0, false);
echo $content;
exit(0);
} else {
echo $content;
}
}
/**
* Sends existing file to a browser as a download using x-sendfile.
*
* X-Sendfile is a feature allowing a web application to redirect the request for a file to the webserver
* that in turn processes the request, this way eliminating the need to perform tasks like reading the file
* and sending it to the user. When dealing with a lot of files (or very big files) this can lead to a great
* increase in performance as the web application is allowed to terminate earlier while the webserver is
* handling the request.
*
* The request is sent to the server through a special non-standard HTTP-header.
* When the web server encounters the presence of such header it will discard all output and send the file
* specified by that header using web server internals including all optimizations like caching-headers.
*
* As this header directive is non-standard different directives exists for different web servers applications:
* <ul>
* <li>Apache: {@link http://tn123.org/mod_xsendfile X-Sendfile}</li>
* <li>Lighttpd v1.4: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-LIGHTTPD-send-file}</li>
* <li>Lighttpd v1.5: {@link http://redmine.lighttpd.net/projects/lighttpd/wiki/X-LIGHTTPD-send-file X-Sendfile}</li>
* <li>Nginx: {@link http://wiki.nginx.org/XSendfile X-Accel-Redirect}</li>
* <li>Cherokee: {@link http://www.cherokee-project.com/doc/other_goodies.html#x-sendfile X-Sendfile and X-Accel-Redirect}</li>
* </ul>
* So for this method to work the X-SENDFILE option/module should be enabled by the web server and
* a proper xHeader should be sent.
*
* <b>Note:</b>
* This option allows to download files that are not under web folders, and even files that are otherwise protected (deny from all) like .htaccess
*
* <b>Side effects</b>:
* If this option is disabled by the web server, when this method is called a download configuration dialog
* will open but the downloaded file will have 0 bytes.
*
* <b>Example</b>:
* <pre>
* <?php
* Yii::app()->request->xSendFile('/home/user/Pictures/picture1.jpg',array(
* 'saveName'=>'image1.jpg',
* 'mimeType'=>'image/jpeg',
* 'terminate'=>false,
* ));
* ?>
* </pre>
* @param string $filePath file name with full path
* @param array $options additional options:
* <ul>
* <li>saveName: file name shown to the user, if not set real file name will be used</li>
* <li>mimeType: mime type of the file, if not set it will be guessed automatically based on the file name, if set to null no content-type header will be sent.</li>
* <li>xHeader: appropriate x-sendfile header, defaults to "X-Sendfile"</li>
* <li>terminate: whether to terminate the current application after calling this method, defaults to true</li>
* <li>forceDownload: specifies whether the file will be downloaded or shown inline, defaults to true. (Since version 1.1.9.)</li>
* <li>addHeaders: an array of additional http headers in header-value pairs (available since version 1.1.10)</li>
* </ul>
* @todo
*/
public function xSendFile($filePath, $options = array())
{
if (!isset($options['forceDownload']) || $options['forceDownload']) {
$disposition = 'attachment';
} else {
$disposition = 'inline';
}
if (!isset($options['saveName'])) {
$options['saveName'] = basename($filePath);
}
if (!isset($options['mimeType'])) {
if (($options['mimeType'] = CFileHelper::getMimeTypeByExtension($filePath)) === null) {
$options['mimeType'] = 'text/plain';
}
}
if (!isset($options['xHeader'])) {
$options['xHeader'] = 'X-Sendfile';
}
if ($options['mimeType'] !== null) {
header('Content-type: ' . $options['mimeType']);
}
header('Content-Disposition: ' . $disposition . '; filename="' . $options['saveName'] . '"');
if (isset($options['addHeaders'])) {
foreach ($options['addHeaders'] as $header => $value) {
header($header . ': ' . $value);
}
}
header(trim($options['xHeader']) . ': ' . $filePath);
if (!isset($options['terminate']) || $options['terminate']) {
Yii::app()->end();
}
}
}
...@@ -64,7 +64,7 @@ class CSort extends CComponent ...@@ -64,7 +64,7 @@ class CSort extends CComponent
* @var boolean whether the sorting can be applied to multiple attributes simultaneously. * @var boolean whether the sorting can be applied to multiple attributes simultaneously.
* Defaults to false, which means each time the data can only be sorted by one attribute. * Defaults to false, which means each time the data can only be sorted by one attribute.
*/ */
public $multiSort=false; public $multiSort = false;
/** /**
* @var string the name of the model class whose attributes can be sorted. * @var string the name of the model class whose attributes can be sorted.
* The model class must be a child class of {@link CActiveRecord}. * The model class must be a child class of {@link CActiveRecord}.
...@@ -143,17 +143,17 @@ class CSort extends CComponent ...@@ -143,17 +143,17 @@ class CSort extends CComponent
* element is the first element in the array, the model attribute takes precedence; and if the star * element is the first element in the array, the model attribute takes precedence; and if the star
* element is the last one, the virtual attribute takes precedence. * element is the last one, the virtual attribute takes precedence.
*/ */
public $attributes=array(); public $attributes = array();
/** /**
* @var string the name of the GET parameter that specifies which attributes to be sorted * @var string the name of the GET parameter that specifies which attributes to be sorted
* in which direction. Defaults to 'sort'. * in which direction. Defaults to 'sort'.
*/ */
public $sortVar='sort'; public $sortVar = 'sort';
/** /**
* @var string the tag appeared in the GET parameter that indicates the attribute should be sorted * @var string the tag appeared in the GET parameter that indicates the attribute should be sorted
* in descending order. Defaults to 'desc'. * in descending order. Defaults to 'desc'.
*/ */
public $descTag='desc'; public $descTag = 'desc';
/** /**
* @var mixed the default order that should be applied to the query criteria when * @var mixed the default order that should be applied to the query criteria when
* the current request does not specify any sort. For example, 'name, create_time DESC' or * the current request does not specify any sort. For example, 'name, create_time DESC' or
...@@ -180,14 +180,14 @@ class CSort extends CComponent ...@@ -180,14 +180,14 @@ class CSort extends CComponent
* @var string the route (controller ID and action ID) for generating the sorted contents. * @var string the route (controller ID and action ID) for generating the sorted contents.
* Defaults to empty string, meaning using the currently requested route. * Defaults to empty string, meaning using the currently requested route.
*/ */
public $route=''; public $route = '';
/** /**
* @var array separators used in the generated URL. This must be an array consisting of * @var array separators used in the generated URL. This must be an array consisting of
* two elements. The first element specifies the character separating different * two elements. The first element specifies the character separating different
* attributes, while the second element specifies the character separating attribute name * attributes, while the second element specifies the character separating attribute name
* and the corresponding sort direction. Defaults to array('-','.'). * and the corresponding sort direction. Defaults to array('-','.').
*/ */
public $separators=array('-','.'); public $separators = array('-', '.');
/** /**
* @var array the additional GET parameters (name=>value) that should be used when generating sort URLs. * @var array the additional GET parameters (name=>value) that should be used when generating sort URLs.
* Defaults to null, meaning using the currently available GET parameters. * Defaults to null, meaning using the currently available GET parameters.
...@@ -201,9 +201,9 @@ class CSort extends CComponent ...@@ -201,9 +201,9 @@ class CSort extends CComponent
* @param string $modelClass the class name of data models that need to be sorted. * @param string $modelClass the class name of data models that need to be sorted.
* This should be a child class of {@link CActiveRecord}. * This should be a child class of {@link CActiveRecord}.
*/ */
public function __construct($modelClass=null) public function __construct($modelClass = null)
{ {
$this->modelClass=$modelClass; $this->modelClass = $modelClass;
} }
/** /**
...@@ -215,12 +215,12 @@ class CSort extends CComponent ...@@ -215,12 +215,12 @@ class CSort extends CComponent
*/ */
public function applyOrder($criteria) public function applyOrder($criteria)
{ {
$order=$this->getOrderBy(); $order = $this->getOrderBy();
if(!empty($order)) if (!empty($order)) {
{ if (!empty($criteria->order)) {
if(!empty($criteria->order)) $criteria->order .= ', ';
$criteria->order.=', '; }
$criteria->order.=$order; $criteria->order .= $order;
} }
} }
...@@ -231,38 +231,37 @@ class CSort extends CComponent ...@@ -231,38 +231,37 @@ class CSort extends CComponent
*/ */
public function getOrderBy() public function getOrderBy()
{ {
$directions=$this->getDirections(); $directions = $this->getDirections();
if(empty($directions)) if (empty($directions)) {
return is_string($this->defaultOrder) ? $this->defaultOrder : ''; return is_string($this->defaultOrder) ? $this->defaultOrder : '';
else } else {
{ if ($this->modelClass !== null) {
if($this->modelClass!==null) $schema = CActiveRecord::model($this->modelClass)->getDbConnection()->getSchema();
$schema=CActiveRecord::model($this->modelClass)->getDbConnection()->getSchema();
$orders=array();
foreach($directions as $attribute=>$descending)
{
$definition=$this->resolveAttribute($attribute);
if(is_array($definition))
{
if($descending)
$orders[]=isset($definition['desc']) ? $definition['desc'] : $attribute.' DESC';
else
$orders[]=isset($definition['asc']) ? $definition['asc'] : $attribute;
} }
else if($definition!==false) $orders = array();
{ foreach ($directions as $attribute => $descending) {
$attribute=$definition; $definition = $this->resolveAttribute($attribute);
if(isset($schema)) if (is_array($definition)) {
{ if ($descending) {
if(($pos=strpos($attribute,'.'))!==false) $orders[] = isset($definition['desc']) ? $definition['desc'] : $attribute . ' DESC';
$attribute=$schema->quoteTableName(substr($attribute,0,$pos)).'.'.$schema->quoteColumnName(substr($attribute,$pos+1)); } else {
else $orders[] = isset($definition['asc']) ? $definition['asc'] : $attribute;
$attribute=CActiveRecord::model($this->modelClass)->getTableAlias(true).'.'.$schema->quoteColumnName($attribute); }
} else {
if ($definition !== false) {
$attribute = $definition;
if (isset($schema)) {
if (($pos = strpos($attribute, '.')) !== false) {
$attribute = $schema->quoteTableName(substr($attribute, 0, $pos)) . '.' . $schema->quoteColumnName(substr($attribute, $pos + 1));
} else {
$attribute = CActiveRecord::model($this->modelClass)->getTableAlias(true) . '.' . $schema->quoteColumnName($attribute);
}
}
$orders[] = $descending ? $attribute . ' DESC' : $attribute;
} }
$orders[]=$descending?$attribute.' DESC':$attribute;
} }
} }
return implode(', ',$orders); return implode(', ', $orders);
} }
} }
...@@ -276,36 +275,41 @@ class CSort extends CComponent ...@@ -276,36 +275,41 @@ class CSort extends CComponent
* @param array $htmlOptions additional HTML attributes for the hyperlink tag * @param array $htmlOptions additional HTML attributes for the hyperlink tag
* @return string the generated hyperlink * @return string the generated hyperlink
*/ */
public function link($attribute,$label=null,$htmlOptions=array()) public function link($attribute, $label = null, $htmlOptions = array())
{ {
if($label===null) if ($label === null) {
$label=$this->resolveLabel($attribute); $label = $this->resolveLabel($attribute);
if(($definition=$this->resolveAttribute($attribute))===false) }
if (($definition = $this->resolveAttribute($attribute)) === false) {
return $label; return $label;
$directions=$this->getDirections(); }
if(isset($directions[$attribute])) $directions = $this->getDirections();
{ if (isset($directions[$attribute])) {
$class=$directions[$attribute] ? 'desc' : 'asc'; $class = $directions[$attribute] ? 'desc' : 'asc';
if(isset($htmlOptions['class'])) if (isset($htmlOptions['class'])) {
$htmlOptions['class'].=' '.$class; $htmlOptions['class'] .= ' ' . $class;
else } else {
$htmlOptions['class']=$class; $htmlOptions['class'] = $class;
$descending=!$directions[$attribute]; }
$descending = !$directions[$attribute];
unset($directions[$attribute]); unset($directions[$attribute]);
} else {
if (is_array($definition) && isset($definition['default'])) {
$descending = $definition['default'] === 'desc';
} else {
$descending = false;
}
} }
else if(is_array($definition) && isset($definition['default']))
$descending=$definition['default']==='desc';
else
$descending=false;
if($this->multiSort) if ($this->multiSort) {
$directions=array_merge(array($attribute=>$descending),$directions); $directions = array_merge(array($attribute => $descending), $directions);
else } else {
$directions=array($attribute=>$descending); $directions = array($attribute => $descending);
}
$url=$this->createUrl(\Yii::$application->getController(),$directions); $url = $this->createUrl(\Yii::$application->getController(), $directions);
return $this->createLink($attribute,$label,$url,$htmlOptions); return $this->createLink($attribute, $label, $url, $htmlOptions);
} }
/** /**
...@@ -318,19 +322,22 @@ class CSort extends CComponent ...@@ -318,19 +322,22 @@ class CSort extends CComponent
*/ */
public function resolveLabel($attribute) public function resolveLabel($attribute)
{ {
$definition=$this->resolveAttribute($attribute); $definition = $this->resolveAttribute($attribute);
if(is_array($definition)) if (is_array($definition)) {
{ if (isset($definition['label'])) {
if(isset($definition['label']))
return $definition['label']; return $definition['label'];
} }
else if(is_string($definition)) } else {
$attribute=$definition; if (is_string($definition)) {
if($this->modelClass!==null) $attribute = $definition;
}
}
if ($this->modelClass !== null) {
return CActiveRecord::model($this->modelClass)->getAttributeLabel($attribute); return CActiveRecord::model($this->modelClass)->getAttributeLabel($attribute);
else } else {
return $attribute; return $attribute;
} }
}
/** /**
* Returns the currently requested sort information. * Returns the currently requested sort information.
...@@ -340,33 +347,31 @@ class CSort extends CComponent ...@@ -340,33 +347,31 @@ class CSort extends CComponent
*/ */
public function getDirections() public function getDirections()
{ {
if($this->_directions===null) if ($this->_directions === null) {
{ $this->_directions = array();
$this->_directions=array(); if (isset($_GET[$this->sortVar]) && is_string($_GET[$this->sortVar])) {
if(isset($_GET[$this->sortVar]) && is_string($_GET[$this->sortVar])) $attributes = explode($this->separators[0], $_GET[$this->sortVar]);
{ foreach ($attributes as $attribute) {
$attributes=explode($this->separators[0],$_GET[$this->sortVar]); if (($pos = strrpos($attribute, $this->separators[1])) !== false) {
foreach($attributes as $attribute) $descending = substr($attribute, $pos + 1) === $this->descTag;
{ if ($descending) {
if(($pos=strrpos($attribute,$this->separators[1]))!==false) $attribute = substr($attribute, 0, $pos);
{ }
$descending=substr($attribute,$pos+1)===$this->descTag; } else {
if($descending) $descending = false;
$attribute=substr($attribute,0,$pos);
} }
else
$descending=false;
if(($this->resolveAttribute($attribute))!==false) if (($this->resolveAttribute($attribute)) !== false) {
{ $this->_directions[$attribute] = $descending;
$this->_directions[$attribute]=$descending; if (!$this->multiSort) {
if(!$this->multiSort)
return $this->_directions; return $this->_directions;
} }
} }
} }
if($this->_directions===array() && is_array($this->defaultOrder)) }
$this->_directions=$this->defaultOrder; if ($this->_directions === array() && is_array($this->defaultOrder)) {
$this->_directions = $this->defaultOrder;
}
} }
return $this->_directions; return $this->_directions;
} }
...@@ -392,14 +397,15 @@ class CSort extends CComponent ...@@ -392,14 +397,15 @@ class CSort extends CComponent
* CSort::SORT_DESC for descending order. * CSort::SORT_DESC for descending order.
* @return string the URL for sorting * @return string the URL for sorting
*/ */
public function createUrl($controller,$directions) public function createUrl($controller, $directions)
{ {
$sorts=array(); $sorts = array();
foreach($directions as $attribute=>$descending) foreach ($directions as $attribute => $descending) {
$sorts[]=$descending ? $attribute.$this->separators[1].$this->descTag : $attribute; $sorts[] = $descending ? $attribute . $this->separators[1] . $this->descTag : $attribute;
$params=$this->params===null ? $_GET : $this->params; }
$params[$this->sortVar]=implode($this->separators[0],$sorts); $params = $this->params === null ? $_GET : $this->params;
return $controller->createUrl($this->route,$params); $params[$this->sortVar] = implode($this->separators[0], $sorts);
return $controller->createUrl($this->route, $params);
} }
/** /**
...@@ -419,27 +425,32 @@ class CSort extends CComponent ...@@ -419,27 +425,32 @@ class CSort extends CComponent
*/ */
public function resolveAttribute($attribute) public function resolveAttribute($attribute)
{ {
if($this->attributes!==array()) if ($this->attributes !== array()) {
$attributes=$this->attributes; $attributes = $this->attributes;
else if($this->modelClass!==null) } else {
$attributes=CActiveRecord::model($this->modelClass)->attributeNames(); if ($this->modelClass !== null) {
else $attributes = CActiveRecord::model($this->modelClass)->attributeNames();
} else {
return false; return false;
foreach($attributes as $name=>$definition) }
{ }
if(is_string($name)) foreach ($attributes as $name => $definition) {
{ if (is_string($name)) {
if($name===$attribute) if ($name === $attribute) {
return $definition; return $definition;
} }
else if($definition==='*') } else {
{ if ($definition === '*') {
if($this->modelClass!==null && CActiveRecord::model($this->modelClass)->hasAttribute($attribute)) if ($this->modelClass !== null && CActiveRecord::model($this->modelClass)->hasAttribute($attribute)) {
return $attribute; return $attribute;
} }
else if($definition===$attribute) } else {
if ($definition === $attribute) {
return $attribute; return $attribute;
} }
}
}
}
return false; return false;
} }
...@@ -452,8 +463,8 @@ class CSort extends CComponent ...@@ -452,8 +463,8 @@ class CSort extends CComponent
* @param array $htmlOptions additional HTML options * @param array $htmlOptions additional HTML options
* @return string the generated hyperlink * @return string the generated hyperlink
*/ */
protected function createLink($attribute,$label,$url,$htmlOptions) protected function createLink($attribute, $label, $url, $htmlOptions)
{ {
return CHtml::link($label,$url,$htmlOptions); return CHtml::link($label, $url, $htmlOptions);
} }
} }
\ No newline at end of file
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