579 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			579 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | ||
| /**
 | ||
|  * This file contains the error handler application component.
 | ||
|  *
 | ||
|  * @author Qiang Xue <qiang.xue@gmail.com>
 | ||
|  * @link http://www.yiiframework.com/
 | ||
|  * @copyright 2008-2013 Yii Software LLC
 | ||
|  * @license http://www.yiiframework.com/license/
 | ||
|  */
 | ||
| 
 | ||
| Yii::import('CHtml',true);
 | ||
| 
 | ||
| /**
 | ||
|  * CErrorHandler handles uncaught PHP errors and exceptions.
 | ||
|  *
 | ||
|  * It displays these errors using appropriate views based on the
 | ||
|  * nature of the error and the mode the application runs at.
 | ||
|  * It also chooses the most preferred language for displaying the error.
 | ||
|  *
 | ||
|  * CErrorHandler uses two sets of views:
 | ||
|  * <ul>
 | ||
|  * <li>development views, named as <code>exception.php</code>;
 | ||
|  * <li>production views, named as <code>error<StatusCode>.php</code>;
 | ||
|  * </ul>
 | ||
|  * where <StatusCode> stands for the HTTP error code (e.g. error500.php).
 | ||
|  * Localized views are named similarly but located under a subdirectory
 | ||
|  * whose name is the language code (e.g. zh_cn/error500.php).
 | ||
|  *
 | ||
|  * Development views are displayed when the application is in debug mode
 | ||
|  * (i.e. YII_DEBUG is defined as true). Detailed error information with source code
 | ||
|  * are displayed in these views. Production views are meant to be shown
 | ||
|  * to end-users and are used when the application is in production mode.
 | ||
|  * For security reasons, they only display the error message without any
 | ||
|  * sensitive information.
 | ||
|  *
 | ||
|  * CErrorHandler looks for the view templates from the following locations in order:
 | ||
|  * <ol>
 | ||
|  * <li><code>themes/ThemeName/views/system</code>: when a theme is active.</li>
 | ||
|  * <li><code>protected/views/system</code></li>
 | ||
|  * <li><code>framework/views</code></li>
 | ||
|  * </ol>
 | ||
|  * If the view is not found in a directory, it will be looked for in the next directory.
 | ||
|  *
 | ||
|  * The property {@link maxSourceLines} can be changed to specify the number
 | ||
|  * of source code lines to be displayed in development views.
 | ||
|  *
 | ||
|  * CErrorHandler is a core application component that can be accessed via
 | ||
|  * {@link CApplication::getErrorHandler()}.
 | ||
|  *
 | ||
|  * @property array $error The error details. Null if there is no error.
 | ||
|  *
 | ||
|  * @author Qiang Xue <qiang.xue@gmail.com>
 | ||
|  * @package system.base
 | ||
|  * @since 1.0
 | ||
|  */
 | ||
| class CErrorHandler extends CApplicationComponent
 | ||
| {
 | ||
| 	/**
 | ||
| 	 * @var integer maximum number of source code lines to be displayed. Defaults to 25.
 | ||
| 	 */
 | ||
| 	public $maxSourceLines=25;
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * @var integer maximum number of trace source code lines to be displayed. Defaults to 10.
 | ||
| 	 * @since 1.1.6
 | ||
| 	 */
 | ||
| 	public $maxTraceSourceLines = 10;
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * @var string the application administrator information (could be a name or email link). It is displayed in error pages to end users. Defaults to 'the webmaster'.
 | ||
| 	 */
 | ||
| 	public $adminInfo='the webmaster';
 | ||
| 	/**
 | ||
| 	 * @var boolean whether to discard any existing page output before error display. Defaults to true.
 | ||
| 	 */
 | ||
| 	public $discardOutput=true;
 | ||
| 	/**
 | ||
| 	 * @var string the route (eg 'site/error') to the controller action that will be used to display external errors.
 | ||
| 	 * Inside the action, it can retrieve the error information by Yii::app()->errorHandler->error.
 | ||
| 	 * This property defaults to null, meaning CErrorHandler will handle the error display.
 | ||
| 	 */
 | ||
| 	public $errorAction;
 | ||
| 
 | ||
| 	private $_error;
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Handles the exception/error event.
 | ||
| 	 * This method is invoked by the application whenever it captures
 | ||
| 	 * an exception or PHP error.
 | ||
| 	 * @param CEvent $event the event containing the exception/error information
 | ||
| 	 */
 | ||
| 	public function handle($event)
 | ||
| 	{
 | ||
| 		// set event as handled to prevent it from being handled by other event handlers
 | ||
| 		$event->handled=true;
 | ||
| 
 | ||
| 		if($this->discardOutput)
 | ||
| 		{
 | ||
| 			$gzHandler=false;
 | ||
| 			foreach(ob_list_handlers() as $h)
 | ||
| 			{
 | ||
| 				if(strpos($h,'gzhandler')!==false)
 | ||
| 					$gzHandler=true;
 | ||
| 			}
 | ||
| 			// the following manual level counting is to deal with zlib.output_compression set to On
 | ||
| 			// for an output buffer created by zlib.output_compression set to On ob_end_clean will fail
 | ||
| 			for($level=ob_get_level();$level>0;--$level)
 | ||
| 			{
 | ||
| 				if(!@ob_end_clean())
 | ||
| 					ob_clean();
 | ||
| 			}
 | ||
| 			// reset headers in case there was an ob_start("ob_gzhandler") before
 | ||
| 			if($gzHandler && !headers_sent() && ob_list_handlers()===array())
 | ||
| 			{
 | ||
| 				if(function_exists('header_remove')) // php >= 5.3
 | ||
| 				{
 | ||
| 					header_remove('Vary');
 | ||
| 					header_remove('Content-Encoding');
 | ||
| 				}
 | ||
| 				else
 | ||
| 				{
 | ||
| 					header('Vary:');
 | ||
| 					header('Content-Encoding:');
 | ||
| 				}
 | ||
| 			}
 | ||
| 		}
 | ||
| 
 | ||
| 		if($event instanceof CExceptionEvent)
 | ||
| 			$this->handleException($event->exception);
 | ||
| 		else // CErrorEvent
 | ||
| 			$this->handleError($event);
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Returns the details about the error that is currently being handled.
 | ||
| 	 * The error is returned in terms of an array, with the following information:
 | ||
| 	 * <ul>
 | ||
| 	 * <li>code - the HTTP status code (e.g. 403, 500)</li>
 | ||
| 	 * <li>type - the error type (e.g. 'CHttpException', 'PHP Error')</li>
 | ||
| 	 * <li>message - the error message</li>
 | ||
| 	 * <li>file - the name of the PHP script file where the error occurs</li>
 | ||
| 	 * <li>line - the line number of the code where the error occurs</li>
 | ||
| 	 * <li>trace - the call stack of the error</li>
 | ||
| 	 * <li>source - the context source code where the error occurs</li>
 | ||
| 	 * </ul>
 | ||
| 	 * @return array the error details. Null if there is no error.
 | ||
| 	 */
 | ||
| 	public function getError()
 | ||
| 	{
 | ||
| 		return $this->_error;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Handles the exception.
 | ||
| 	 * @param Exception $exception the exception captured
 | ||
| 	 */
 | ||
| 	protected function handleException($exception)
 | ||
| 	{
 | ||
| 		$app=Yii::app();
 | ||
| 		if($app instanceof CWebApplication)
 | ||
| 		{
 | ||
| 			if(($trace=$this->getExactTrace($exception))===null)
 | ||
| 			{
 | ||
| 				$fileName=$exception->getFile();
 | ||
| 				$errorLine=$exception->getLine();
 | ||
| 			}
 | ||
| 			else
 | ||
| 			{
 | ||
| 				$fileName=$trace['file'];
 | ||
| 				$errorLine=$trace['line'];
 | ||
| 			}
 | ||
| 
 | ||
| 			$trace = $exception->getTrace();
 | ||
| 
 | ||
| 			foreach($trace as $i=>$t)
 | ||
| 			{
 | ||
| 				if(!isset($t['file']))
 | ||
| 					$trace[$i]['file']='unknown';
 | ||
| 
 | ||
| 				if(!isset($t['line']))
 | ||
| 					$trace[$i]['line']=0;
 | ||
| 
 | ||
| 				if(!isset($t['function']))
 | ||
| 					$trace[$i]['function']='unknown';
 | ||
| 
 | ||
| 				unset($trace[$i]['object']);
 | ||
| 			}
 | ||
| 
 | ||
| 			$this->_error=$data=array(
 | ||
| 				'code'=>($exception instanceof CHttpException)?$exception->statusCode:500,
 | ||
| 				'type'=>get_class($exception),
 | ||
| 				'errorCode'=>$exception->getCode(),
 | ||
| 				'message'=>$exception->getMessage(),
 | ||
| 				'file'=>$fileName,
 | ||
| 				'line'=>$errorLine,
 | ||
| 				'trace'=>$exception->getTraceAsString(),
 | ||
| 				'traces'=>$trace,
 | ||
| 			);
 | ||
| 
 | ||
| 			if(!headers_sent())
 | ||
| 				header("HTTP/1.0 {$data['code']} ".$this->getHttpHeader($data['code'], get_class($exception)));
 | ||
| 
 | ||
| 			if($exception instanceof CHttpException || !YII_DEBUG)
 | ||
| 				$this->render('error',$data);
 | ||
| 			else
 | ||
| 			{
 | ||
| 				if($this->isAjaxRequest())
 | ||
| 					$app->displayException($exception);
 | ||
| 				else
 | ||
| 					$this->render('exception',$data);
 | ||
| 			}
 | ||
| 		}
 | ||
| 		else
 | ||
| 			$app->displayException($exception);
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Handles the PHP error.
 | ||
| 	 * @param CErrorEvent $event the PHP error event
 | ||
| 	 */
 | ||
| 	protected function handleError($event)
 | ||
| 	{
 | ||
| 		$trace=debug_backtrace();
 | ||
| 		// skip the first 3 stacks as they do not tell the error position
 | ||
| 		if(count($trace)>3)
 | ||
| 			$trace=array_slice($trace,3);
 | ||
| 		$traceString='';
 | ||
| 		foreach($trace as $i=>$t)
 | ||
| 		{
 | ||
| 			if(!isset($t['file']))
 | ||
| 				$trace[$i]['file']='unknown';
 | ||
| 
 | ||
| 			if(!isset($t['line']))
 | ||
| 				$trace[$i]['line']=0;
 | ||
| 
 | ||
| 			if(!isset($t['function']))
 | ||
| 				$trace[$i]['function']='unknown';
 | ||
| 
 | ||
| 			$traceString.="#$i {$trace[$i]['file']}({$trace[$i]['line']}): ";
 | ||
| 			if(isset($t['object']) && is_object($t['object']))
 | ||
| 				$traceString.=get_class($t['object']).'->';
 | ||
| 			$traceString.="{$trace[$i]['function']}()\n";
 | ||
| 
 | ||
| 			unset($trace[$i]['object']);
 | ||
| 		}
 | ||
| 
 | ||
| 		$app=Yii::app();
 | ||
| 		if($app instanceof CWebApplication)
 | ||
| 		{
 | ||
| 			switch($event->code)
 | ||
| 			{
 | ||
| 				case E_WARNING:
 | ||
| 					$type = 'PHP warning';
 | ||
| 					break;
 | ||
| 				case E_NOTICE:
 | ||
| 					$type = 'PHP notice';
 | ||
| 					break;
 | ||
| 				case E_USER_ERROR:
 | ||
| 					$type = 'User error';
 | ||
| 					break;
 | ||
| 				case E_USER_WARNING:
 | ||
| 					$type = 'User warning';
 | ||
| 					break;
 | ||
| 				case E_USER_NOTICE:
 | ||
| 					$type = 'User notice';
 | ||
| 					break;
 | ||
| 				case E_RECOVERABLE_ERROR:
 | ||
| 					$type = 'Recoverable error';
 | ||
| 					break;
 | ||
| 				default:
 | ||
| 					$type = 'PHP error';
 | ||
| 			}
 | ||
| 			$this->_error=$data=array(
 | ||
| 				'code'=>500,
 | ||
| 				'type'=>$type,
 | ||
| 				'message'=>$event->message,
 | ||
| 				'file'=>$event->file,
 | ||
| 				'line'=>$event->line,
 | ||
| 				'trace'=>$traceString,
 | ||
| 				'traces'=>$trace,
 | ||
| 			);
 | ||
| 			if(!headers_sent())
 | ||
| 				header("HTTP/1.0 500 Internal Server Error");
 | ||
| 			if($this->isAjaxRequest())
 | ||
| 				$app->displayError($event->code,$event->message,$event->file,$event->line);
 | ||
| 			elseif(YII_DEBUG)
 | ||
| 				$this->render('exception',$data);
 | ||
| 			else
 | ||
| 				$this->render('error',$data);
 | ||
| 		}
 | ||
| 		else
 | ||
| 			$app->displayError($event->code,$event->message,$event->file,$event->line);
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * whether the current request is an AJAX (XMLHttpRequest) request.
 | ||
| 	 * @return boolean whether the current request is an AJAX request.
 | ||
| 	 */
 | ||
| 	protected function isAjaxRequest()
 | ||
| 	{
 | ||
| 		return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH']==='XMLHttpRequest';
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Returns the exact trace where the problem occurs.
 | ||
| 	 * @param Exception $exception the uncaught exception
 | ||
| 	 * @return array the exact trace where the problem occurs
 | ||
| 	 */
 | ||
| 	protected function getExactTrace($exception)
 | ||
| 	{
 | ||
| 		$traces=$exception->getTrace();
 | ||
| 
 | ||
| 		foreach($traces as $trace)
 | ||
| 		{
 | ||
| 			// property access exception
 | ||
| 			if(isset($trace['function']) && ($trace['function']==='__get' || $trace['function']==='__set'))
 | ||
| 				return $trace;
 | ||
| 		}
 | ||
| 		return null;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Renders the view.
 | ||
| 	 * @param string $view the view name (file name without extension).
 | ||
| 	 * See {@link getViewFile} for how a view file is located given its name.
 | ||
| 	 * @param array $data data to be passed to the view
 | ||
| 	 */
 | ||
| 	protected function render($view,$data)
 | ||
| 	{
 | ||
| 		if($view==='error' && $this->errorAction!==null)
 | ||
| 			Yii::app()->runController($this->errorAction);
 | ||
| 		else
 | ||
| 		{
 | ||
| 			// additional information to be passed to view
 | ||
| 			$data['version']=$this->getVersionInfo();
 | ||
| 			$data['time']=time();
 | ||
| 			$data['admin']=$this->adminInfo;
 | ||
| 			include($this->getViewFile($view,$data['code']));
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Determines which view file should be used.
 | ||
| 	 * @param string $view view name (either 'exception' or 'error')
 | ||
| 	 * @param integer $code HTTP status code
 | ||
| 	 * @return string view file path
 | ||
| 	 */
 | ||
| 	protected function getViewFile($view,$code)
 | ||
| 	{
 | ||
| 		$viewPaths=array(
 | ||
| 			Yii::app()->getTheme()===null ? null :  Yii::app()->getTheme()->getSystemViewPath(),
 | ||
| 			Yii::app() instanceof CWebApplication ? Yii::app()->getSystemViewPath() : null,
 | ||
| 			YII_PATH.DIRECTORY_SEPARATOR.'views',
 | ||
| 		);
 | ||
| 
 | ||
| 		foreach($viewPaths as $i=>$viewPath)
 | ||
| 		{
 | ||
| 			if($viewPath!==null)
 | ||
| 			{
 | ||
| 				 $viewFile=$this->getViewFileInternal($viewPath,$view,$code,$i===2?'en_us':null);
 | ||
| 				 if(is_file($viewFile))
 | ||
| 				 	 return $viewFile;
 | ||
| 			}
 | ||
| 		}
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Looks for the view under the specified directory.
 | ||
| 	 * @param string $viewPath the directory containing the views
 | ||
| 	 * @param string $view view name (either 'exception' or 'error')
 | ||
| 	 * @param integer $code HTTP status code
 | ||
| 	 * @param string $srcLanguage the language that the view file is in
 | ||
| 	 * @return string view file path
 | ||
| 	 */
 | ||
| 	protected function getViewFileInternal($viewPath,$view,$code,$srcLanguage=null)
 | ||
| 	{
 | ||
| 		$app=Yii::app();
 | ||
| 		if($view==='error')
 | ||
| 		{
 | ||
| 			$viewFile=$app->findLocalizedFile($viewPath.DIRECTORY_SEPARATOR."error{$code}.php",$srcLanguage);
 | ||
| 			if(!is_file($viewFile))
 | ||
| 				$viewFile=$app->findLocalizedFile($viewPath.DIRECTORY_SEPARATOR.'error.php',$srcLanguage);
 | ||
| 		}
 | ||
| 		else
 | ||
| 			$viewFile=$viewPath.DIRECTORY_SEPARATOR."exception.php";
 | ||
| 		return $viewFile;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Returns server version information.
 | ||
| 	 * If the application is in production mode, empty string is returned.
 | ||
| 	 * @return string server version information. Empty if in production mode.
 | ||
| 	 */
 | ||
| 	protected function getVersionInfo()
 | ||
| 	{
 | ||
| 		if(YII_DEBUG)
 | ||
| 		{
 | ||
| 			$version='<a href="http://www.yiiframework.com/">Yii Framework</a>/'.Yii::getVersion();
 | ||
| 			if(isset($_SERVER['SERVER_SOFTWARE']))
 | ||
| 				$version=$_SERVER['SERVER_SOFTWARE'].' '.$version;
 | ||
| 		}
 | ||
| 		else
 | ||
| 			$version='';
 | ||
| 		return $version;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Converts arguments array to its string representation
 | ||
| 	 *
 | ||
| 	 * @param array $args arguments array to be converted
 | ||
| 	 * @return string string representation of the arguments array
 | ||
| 	 */
 | ||
| 	protected function argumentsToString($args)
 | ||
| 	{
 | ||
| 		$count=0;
 | ||
| 
 | ||
| 		$isAssoc=$args!==array_values($args);
 | ||
| 
 | ||
| 		foreach($args as $key => $value)
 | ||
| 		{
 | ||
| 			$count++;
 | ||
| 			if($count>=5)
 | ||
| 			{
 | ||
| 				if($count>5)
 | ||
| 					unset($args[$key]);
 | ||
| 				else
 | ||
| 					$args[$key]='...';
 | ||
| 				continue;
 | ||
| 			}
 | ||
| 
 | ||
| 			if(is_object($value))
 | ||
| 				$args[$key] = get_class($value);
 | ||
| 			elseif(is_bool($value))
 | ||
| 				$args[$key] = $value ? 'true' : 'false';
 | ||
| 			elseif(is_string($value))
 | ||
| 			{
 | ||
| 				if(strlen($value)>64)
 | ||
| 					$args[$key] = '"'.substr($value,0,64).'..."';
 | ||
| 				else
 | ||
| 					$args[$key] = '"'.$value.'"';
 | ||
| 			}
 | ||
| 			elseif(is_array($value))
 | ||
| 				$args[$key] = 'array('.$this->argumentsToString($value).')';
 | ||
| 			elseif($value===null)
 | ||
| 				$args[$key] = 'null';
 | ||
| 			elseif(is_resource($value))
 | ||
| 				$args[$key] = 'resource';
 | ||
| 
 | ||
| 			if(is_string($key))
 | ||
| 			{
 | ||
| 				$args[$key] = '"'.$key.'" => '.$args[$key];
 | ||
| 			}
 | ||
| 			elseif($isAssoc)
 | ||
| 			{
 | ||
| 				$args[$key] = $key.' => '.$args[$key];
 | ||
| 			}
 | ||
| 		}
 | ||
| 		$out = implode(", ", $args);
 | ||
| 
 | ||
| 		return $out;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Returns a value indicating whether the call stack is from application code.
 | ||
| 	 * @param array $trace the trace data
 | ||
| 	 * @return boolean whether the call stack is from application code.
 | ||
| 	 */
 | ||
| 	protected function isCoreCode($trace)
 | ||
| 	{
 | ||
| 		if(isset($trace['file']))
 | ||
| 		{
 | ||
| 			$systemPath=realpath(dirname(__FILE__).'/..');
 | ||
| 			return $trace['file']==='unknown' || strpos(realpath($trace['file']),$systemPath.DIRECTORY_SEPARATOR)===0;
 | ||
| 		}
 | ||
| 		return false;
 | ||
| 	}
 | ||
| 
 | ||
| 	/**
 | ||
| 	 * Renders the source code around the error line.
 | ||
| 	 * @param string $file source file path
 | ||
| 	 * @param integer $errorLine the error line number
 | ||
| 	 * @param integer $maxLines maximum number of lines to display
 | ||
| 	 * @return string the rendering result
 | ||
| 	 */
 | ||
| 	protected function renderSourceCode($file,$errorLine,$maxLines)
 | ||
| 	{
 | ||
| 		$errorLine--;	// adjust line number to 0-based from 1-based
 | ||
| 		if($errorLine<0 || ($lines=@file($file))===false || ($lineCount=count($lines))<=$errorLine)
 | ||
| 			return '';
 | ||
| 
 | ||
| 		$halfLines=(int)($maxLines/2);
 | ||
| 		$beginLine=$errorLine-$halfLines>0 ? $errorLine-$halfLines:0;
 | ||
| 		$endLine=$errorLine+$halfLines<$lineCount?$errorLine+$halfLines:$lineCount-1;
 | ||
| 		$lineNumberWidth=strlen($endLine+1);
 | ||
| 
 | ||
| 		$output='';
 | ||
| 		for($i=$beginLine;$i<=$endLine;++$i)
 | ||
| 		{
 | ||
| 			$isErrorLine = $i===$errorLine;
 | ||
| 			$code=sprintf("<span class=\"ln".($isErrorLine?' error-ln':'')."\">%0{$lineNumberWidth}d</span> %s",$i+1,CHtml::encode(str_replace("\t",'    ',$lines[$i])));
 | ||
| 			if(!$isErrorLine)
 | ||
| 				$output.=$code;
 | ||
| 			else
 | ||
| 				$output.='<span class="error">'.$code.'</span>';
 | ||
| 		}
 | ||
| 		return '<div class="code"><pre>'.$output.'</pre></div>';
 | ||
| 	}
 | ||
| 	/**
 | ||
| 	 * Return correct message for each known http error code
 | ||
| 	 * @param integer $httpCode error code to map
 | ||
| 	 * @param string $replacement replacement error string that is returned if code is unknown
 | ||
| 	 * @return string the textual representation of the given error code or the replacement string if the error code is unknown
 | ||
| 	 */
 | ||
| 	protected function getHttpHeader($httpCode, $replacement='')
 | ||
| 	{
 | ||
| 		$httpCodes = array(
 | ||
| 			100 => 'Continue',
 | ||
| 			101 => 'Switching Protocols',
 | ||
| 			102 => 'Processing',
 | ||
| 			118 => 'Connection timed out',
 | ||
| 			200 => 'OK',
 | ||
| 			201 => 'Created',
 | ||
| 			202 => 'Accepted',
 | ||
| 			203 => 'Non-Authoritative',
 | ||
| 			204 => 'No Content',
 | ||
| 			205 => 'Reset Content',
 | ||
| 			206 => 'Partial Content',
 | ||
| 			207 => 'Multi-Status',
 | ||
| 			210 => 'Content Different',
 | ||
| 			300 => 'Multiple Choices',
 | ||
| 			301 => 'Moved Permanently',
 | ||
| 			302 => 'Found',
 | ||
| 			303 => 'See Other',
 | ||
| 			304 => 'Not Modified',
 | ||
| 			305 => 'Use Proxy',
 | ||
| 			307 => 'Temporary Redirect',
 | ||
| 			310 => 'Too many Redirect',
 | ||
| 			400 => 'Bad Request',
 | ||
| 			401 => 'Unauthorized',
 | ||
| 			402 => 'Payment Required',
 | ||
| 			403 => 'Forbidden',
 | ||
| 			404 => 'Not Found',
 | ||
| 			405 => 'Method Not Allowed',
 | ||
| 			406 => 'Not Acceptable',
 | ||
| 			407 => 'Proxy Authentication Required',
 | ||
| 			408 => 'Request Time-out',
 | ||
| 			409 => 'Conflict',
 | ||
| 			410 => 'Gone',
 | ||
| 			411 => 'Length Required',
 | ||
| 			412 => 'Precondition Failed',
 | ||
| 			413 => 'Request Entity Too Large',
 | ||
| 			414 => 'Request-URI Too Long',
 | ||
| 			415 => 'Unsupported Media Type',
 | ||
| 			416 => 'Requested range unsatisfiable',
 | ||
| 			417 => 'Expectation failed',
 | ||
| 			418 => 'I’m a teapot',
 | ||
| 			422 => 'Unprocessable entity',
 | ||
| 			423 => 'Locked',
 | ||
| 			424 => 'Method failure',
 | ||
| 			425 => 'Unordered Collection',
 | ||
| 			426 => 'Upgrade Required',
 | ||
| 			449 => 'Retry With',
 | ||
| 			450 => 'Blocked by Windows Parental Controls',
 | ||
| 			500 => 'Internal Server Error',
 | ||
| 			501 => 'Not Implemented',
 | ||
| 			502 => 'Bad Gateway ou Proxy Error',
 | ||
| 			503 => 'Service Unavailable',
 | ||
| 			504 => 'Gateway Time-out',
 | ||
| 			505 => 'HTTP Version not supported',
 | ||
| 			507 => 'Insufficient storage',
 | ||
| 			509 => 'Bandwidth Limit Exceeded',
 | ||
| 		);
 | ||
| 		if(isset($httpCodes[$httpCode]))
 | ||
| 			return $httpCodes[$httpCode];
 | ||
| 		else
 | ||
| 			return $replacement;
 | ||
| 	}
 | ||
| }
 |