*/ /** * YiiDebugToolbarRouter represents an ... * * Description of YiiDebugToolbarRouter * * @author Sergey Malyshev * @version $Id$ * @package YiiDebugToolbar * @since 1.1.7 */ class YiiDebugToolbarRoute extends CLogRoute { private $_panels = array( //'YiiDebugToolbarPanelServer', 'YiiDebugToolbarPanelRequest', 'YiiDebugToolbarPanelSettings', 'YiiDebugToolbarPanelViews', 'YiiDebugToolbarPanelSql', 'YiiDebugToolbarPanelLogging', ); /** * The filters are given in an array, each filter being: * - a normal IP (192.168.0.10 or '::1') * - an incomplete IP (192.168.0.* or 192.168.0.) * - a CIDR mask (192.168.0.0/24) * - "*" for everything. */ public $ipFilters=array('127.0.0.1','::1'); /** * Whitelist for response content types. DebugToolbarRoute won't write any * output if the server generates output that isn't listed here (json, xml, * files, ...) * @var array of content type strings (in lower case) */ public $contentTypeWhitelist = array( // Yii framework doesn't seem to send content-type header by default. '', 'text/html', 'application/xhtml+xml', ); private $_toolbarWidget, $_startTime, $_endTime; private $_proxyMap = array( 'viewRenderer' => 'YiiDebugViewRenderer' ); public function setPanels(array $pannels) { $selfPanels = array_fill_keys($this->_panels, array()); $this->_panels = array_merge($selfPanels, $pannels); } public function getPanels() { return $this->_panels; } public function getStartTime() { return $this->_startTime; } public function getEndTime() { return $this->_endTime; } public function getLoadTime() { return ($this->endTime-$this->startTime); } protected function getToolbarWidget() { if (null === $this->_toolbarWidget) { $this->_toolbarWidget = Yii::createComponent(array( 'class'=>'YiiDebugToolbar', 'panels'=> $this->panels ), $this); } return $this->_toolbarWidget; } public function init() { Yii::app()->controllerMap = array_merge(array( 'debug' => array( 'class' => 'YiiDebugController' ) ), Yii::app()->controllerMap); Yii::setPathOfAlias('yii-debug-toolbar', dirname(__FILE__)); Yii::app()->setImport(array( 'yii-debug-toolbar.*' )); $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest()); $this->enabled = strpos(trim($route, '/'), 'debug') !== 0; $this->enabled && $this->enabled = ($this->allowIp(Yii::app()->request->userHostAddress) && !Yii::app()->getRequest()->getIsAjaxRequest() && (Yii::app() instanceof CWebApplication)) && $this->checkContentTypeWhitelist(); if ($this->enabled) { Yii::app()->attachEventHandler('onBeginRequest', array($this, 'onBeginRequest')); Yii::app()->attachEventHandler('onEndRequest', array($this, 'onEndRequest')); $this->categories = ''; $this->levels=''; } $this->_startTime = microtime(true); parent::init(); } protected function onBeginRequest(CEvent $event) { $this->initComponents(); $this->getToolbarWidget() ->init(); } protected function initComponents() { foreach ($this->_proxyMap as $name=>$class) { $instance = Yii::app()->getComponent($name); if (null !== ($instance)) { Yii::app()->setComponent($name, null); } $this->_proxyMap[$name] = array( 'class'=>$class, 'instance' => $instance ); } Yii::app()->setComponents($this->_proxyMap, false); } /** * Processes the current request. * It first resolves the request into controller and action, * and then creates the controller to perform the action. */ private function processRequest() { if (is_array(Yii::app()->catchAllRequest) && isset(Yii::app()->catchAllRequest[0])) { $route = Yii::app()->catchAllRequest[0]; foreach(array_splice(Yii::app()->catchAllRequest,1) as $name=>$value) $_GET[$name] = $value; } else { $route = Yii::app()->getUrlManager()->parseUrl(Yii::app()->getRequest()); } Yii::app()->runController($route); } protected function onEndRequest(CEvent $event) { $this->_endTime = microtime(true); } public function collectLogs($logger, $processLogs=false) { $logs = $logger->getLogs(); $this->logs = empty($this->logs) ? $logs : array_merge($this->logs, $logs); $this->processLogs($this->logs); $this->logs = array(); } protected function processLogs($logs) { $this->getToolbarWidget()->run(); } private function checkContentTypeWhitelist() { $contentType = ''; foreach (headers_list() as $header) { list($key, $value) = explode(':', $header); $value = ltrim($value, ' '); if (strtolower($key) === 'content-type') { // Split encoding if exists $contentType = explode(";", strtolower($value)); $contentType = current($contentType); break; } } return in_array( $contentType, $this->contentTypeWhitelist ); } /** * Checks to see if the user IP is allowed by {@link ipFilters}. * @param string $ip the user IP * @return boolean whether the user IP is allowed by {@link ipFilters}. */ protected function allowIp($ip) { foreach ($this->ipFilters as $filter) { $filter = trim($filter); // normal or incomplete IPv4 if (preg_match('/^[\d\.]*\*?$/', $filter)) { $filter = rtrim($filter, '*'); if (strncmp($ip, $filter, strlen($filter)) === 0) { return true; } } // CIDR else if (preg_match('/^([\d\.]+)\/(\d+)$/', $filter, $match)) { if (self::matchIpMask($ip, $match[1], $match[2])) { return true; } } // IPv6 else if ($ip === $filter) { return true; } } return false; } /** * Check if an IP matches a CIDR mask. * * @param integer|string $ip IP to check. * @param integer|string $matchIp Radical of the mask (e.g. 192.168.0.0). * @param integer $maskBits Size of the mask (e.g. 24). */ protected static function matchIpMask($ip, $maskIp, $maskBits) { $mask =~ (pow(2, 32-$maskBits)-1); if (false === is_int($ip)) { $ip = ip2long($ip); } if (false === is_int($maskIp)) { $maskIp = ip2long($maskIp); } if (($ip & $mask) === ($maskIp & $mask)) { return true; } else { return false; } } }