summaryrefslogtreecommitdiffstats
path: root/system/core/Common.php
diff options
context:
space:
mode:
Diffstat (limited to 'system/core/Common.php')
-rw-r--r--system/core/Common.php879
1 files changed, 577 insertions, 302 deletions
diff --git a/system/core/Common.php b/system/core/Common.php
index 4bf8a9ef5..d6a1fdb4e 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -1,24 +1,41 @@
-<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
-/**
- * MODIFIED
- * config_item(): option to override returned values
- */
-
+<?php
/**
* CodeIgniter
*
- * An open source application development framework for PHP 5.1.6 or newer
+ * An open source application development framework for PHP
*
- * @package CodeIgniter
- * @author ExpressionEngine Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc.
- * @license http://codeigniter.com/user_guide/license.html
- * @link http://codeigniter.com
- * @since Version 1.0
+ * This content is released under the MIT License (MIT)
+ *
+ * Copyright (c) 2014 - 2017, British Columbia Institute of Technology
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (https://ellislab.com/)
+ * @copyright Copyright (c) 2014 - 2017, British Columbia Institute of Technology (http://bcit.ca/)
+ * @license http://opensource.org/licenses/MIT MIT License
+ * @link https://codeigniter.com
+ * @since Version 1.0.0
* @filesource
*/
-
-// ------------------------------------------------------------------------
+defined('BASEPATH') OR exit('No direct script access allowed');
/**
* Common Functions
@@ -26,34 +43,30 @@
* Loads the base classes and executes the request.
*
* @package CodeIgniter
- * @subpackage codeigniter
+ * @subpackage CodeIgniter
* @category Common Functions
- * @author ExpressionEngine Dev Team
- * @link http://codeigniter.com/user_guide/
+ * @author EllisLab Dev Team
+ * @link https://codeigniter.com/user_guide/
*/
// ------------------------------------------------------------------------
-/**
-* Determines if the current version of PHP is greater then the supplied value
-*
-* Since there are a few places where we conditionally test for PHP > 5
-* we'll set a static variable.
-*
-* @access public
-* @param string
-* @return bool TRUE if the current version is $version or higher
-*/
if ( ! function_exists('is_php'))
{
- function is_php($version = '5.0.0')
+ /**
+ * Determines if the current version of PHP is equal to or greater than the supplied value
+ *
+ * @param string
+ * @return bool TRUE if the current version is $version or higher
+ */
+ function is_php($version)
{
static $_is_php;
- $version = (string)$version;
+ $version = (string) $version;
if ( ! isset($_is_php[$version]))
{
- $_is_php[$version] = (version_compare(PHP_VERSION, $version) < 0) ? FALSE : TRUE;
+ $_is_php[$version] = version_compare(PHP_VERSION, $version, '>=');
}
return $_is_php[$version];
@@ -62,43 +75,44 @@ if ( ! function_exists('is_php'))
// ------------------------------------------------------------------------
-/**
- * Tests for file writability
- *
- * is_writable() returns TRUE on Windows servers when you really can't write to
- * the file, based on the read-only attribute. is_writable() is also unreliable
- * on Unix servers if safe_mode is on.
- *
- * @access private
- * @return void
- */
if ( ! function_exists('is_really_writable'))
{
+ /**
+ * Tests for file writability
+ *
+ * is_writable() returns TRUE on Windows servers when you really can't write to
+ * the file, based on the read-only attribute. is_writable() is also unreliable
+ * on Unix servers if safe_mode is on.
+ *
+ * @link https://bugs.php.net/bug.php?id=54709
+ * @param string
+ * @return bool
+ */
function is_really_writable($file)
{
// If we're on a Unix server with safe_mode off we call is_writable
- if (DIRECTORY_SEPARATOR == '/' AND @ini_get("safe_mode") == FALSE)
+ if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode')))
{
return is_writable($file);
}
- // For windows servers and safe_mode "on" installations we'll actually
- // write a file then read it. Bah...
+ /* For Windows servers and safe_mode "on" installations we'll actually
+ * write a file then read it. Bah...
+ */
if (is_dir($file))
{
- $file = rtrim($file, '/').'/'.md5(mt_rand(1,100).mt_rand(1,100));
-
- if (($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
+ $file = rtrim($file, '/').'/'.md5(mt_rand());
+ if (($fp = @fopen($file, 'ab')) === FALSE)
{
return FALSE;
}
fclose($fp);
- @chmod($file, DIR_WRITE_MODE);
+ @chmod($file, 0777);
@unlink($file);
return TRUE;
}
- elseif ( ! is_file($file) OR ($fp = @fopen($file, FOPEN_WRITE_CREATE)) === FALSE)
+ elseif ( ! is_file($file) OR ($fp = @fopen($file, 'ab')) === FALSE)
{
return FALSE;
}
@@ -110,26 +124,25 @@ if ( ! function_exists('is_really_writable'))
// ------------------------------------------------------------------------
-/**
-* Class registry
-*
-* This function acts as a singleton. If the requested class does not
-* exist it is instantiated and set to a static variable. If it has
-* previously been instantiated the variable is returned.
-*
-* @access public
-* @param string the class name being requested
-* @param string the directory where the class should be found
-* @param string the class name prefix
-* @return object
-*/
if ( ! function_exists('load_class'))
{
- function &load_class($class, $directory = 'libraries', $prefix = 'CI_')
+ /**
+ * Class registry
+ *
+ * This function acts as a singleton. If the requested class does not
+ * exist it is instantiated and set to a static variable. If it has
+ * previously been instantiated the variable is returned.
+ *
+ * @param string the class name being requested
+ * @param string the directory where the class should be found
+ * @param mixed an optional argument to pass to the class constructor
+ * @return object
+ */
+ function &load_class($class, $directory = 'libraries', $param = NULL)
{
static $_classes = array();
- // Does the class exist? If so, we're done...
+ // Does the class exist? If so, we're done...
if (isset($_classes[$class]))
{
return $_classes[$class];
@@ -143,60 +156,64 @@ if ( ! function_exists('load_class'))
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
- $name = $prefix.$class;
+ $name = 'CI_'.$class;
- if (class_exists($name) === FALSE)
+ if (class_exists($name, FALSE) === FALSE)
{
- require($path.$directory.'/'.$class.'.php');
+ require_once($path.$directory.'/'.$class.'.php');
}
break;
}
}
- // Is the request a class extension? If so we load it too
+ // Is the request a class extension? If so we load it too
if (file_exists(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php'))
{
$name = config_item('subclass_prefix').$class;
- if (class_exists($name) === FALSE)
+ if (class_exists($name, FALSE) === FALSE)
{
- require(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
+ require_once(APPPATH.$directory.'/'.$name.'.php');
}
}
// Did we find the class?
if ($name === FALSE)
{
- // Note: We use exit() rather then show_error() in order to avoid a
- // self-referencing loop with the Excptions class
- exit('Unable to locate the specified class: '.$class.'.php');
+ // Note: We use exit() rather than show_error() in order to avoid a
+ // self-referencing loop with the Exceptions class
+ set_status_header(503);
+ echo 'Unable to locate the specified class: '.$class.'.php';
+ exit(5); // EXIT_UNK_CLASS
}
// Keep track of what we just loaded
is_loaded($class);
- $_classes[$class] = new $name();
+ $_classes[$class] = isset($param)
+ ? new $name($param)
+ : new $name();
return $_classes[$class];
}
}
// --------------------------------------------------------------------
-/**
-* Keeps track of which libraries have been loaded. This function is
-* called by the load_class() function above
-*
-* @access public
-* @return array
-*/
if ( ! function_exists('is_loaded'))
{
+ /**
+ * Keeps track of which libraries have been loaded. This function is
+ * called by the load_class() function above
+ *
+ * @param string
+ * @return array
+ */
function &is_loaded($class = '')
{
static $_is_loaded = array();
- if ($class != '')
+ if ($class !== '')
{
$_is_loaded[strtolower($class)] = $class;
}
@@ -207,333 +224,500 @@ if ( ! function_exists('is_loaded'))
// ------------------------------------------------------------------------
-/**
-* Loads the main config.php file
-*
-* This function lets us grab the config file even if the Config class
-* hasn't been instantiated yet
-*
-* @access private
-* @return array
-*/
if ( ! function_exists('get_config'))
{
- function &get_config($replace = array())
+ /**
+ * Loads the main config.php file
+ *
+ * This function lets us grab the config file even if the Config class
+ * hasn't been instantiated yet
+ *
+ * @param array
+ * @return array
+ */
+ function &get_config(Array $replace = array())
{
- static $_config;
+ static $config;
- if (isset($_config))
- {
- return $_config[0];
- }
-
- // Is the config file in the environment folder?
- if ( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ if (empty($config))
{
$file_path = APPPATH.'config/config.php';
+ $found = FALSE;
+ if (file_exists($file_path))
+ {
+ $found = TRUE;
+ require($file_path);
+ }
+
+ // Is the config file in the environment folder?
+ if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ {
+ require($file_path);
+ }
+ elseif ( ! $found)
+ {
+ set_status_header(503);
+ echo 'The configuration file does not exist.';
+ exit(3); // EXIT_CONFIG
+ }
+
+ // Does the $config array exist in the file?
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ set_status_header(503);
+ echo 'Your config file does not appear to be formatted correctly.';
+ exit(3); // EXIT_CONFIG
+ }
}
- // Fetch the config file
- if ( ! file_exists($file_path))
+ // Are any values being dynamically added or replaced?
+ foreach ($replace as $key => $val)
{
- exit('The configuration file does not exist.');
+ $config[$key] = $val;
}
- require($file_path);
+ return $config;
+ }
+}
- // Does the $config array exist in the file?
- if ( ! isset($config) OR ! is_array($config))
- {
- exit('Your config file does not appear to be formatted correctly.');
- }
+// ------------------------------------------------------------------------
- // Are any values being dynamically replaced?
- if (count($replace) > 0)
+if ( ! function_exists('config_item'))
+{
+ /**
+ * Returns the specified config item
+ *
+ * @param string
+ * @return mixed
+ */
+ function config_item($item)
+ {
+ static $_config;
+
+ if (empty($_config))
{
- foreach ($replace as $key => $val)
- {
- if (isset($config[$key]))
- {
- $config[$key] = $val;
- }
- }
+ // references cannot be directly assigned to static variables, so we use an array
+ $_config[0] =& get_config();
}
- $_config[0] =& $config;
- return $_config[0];
+ return isset($_config[0][$item]) ? $_config[0][$item] : NULL;
}
}
// ------------------------------------------------------------------------
-/**
-* Returns the specified config item
-*
-* @access public
-* @return mixed
-*/
-if ( ! function_exists('config_item'))
+if ( ! function_exists('get_mimes'))
{
- function config_item($item, $value = null)
+ /**
+ * Returns the MIME types array from config/mimes.php
+ *
+ * @return array
+ */
+ function &get_mimes()
{
- static $_config_item = array();
+ static $_mimes;
- if ( ! isset($_config_item[$item]))
+ if (empty($_mimes))
{
- $config =& get_config();
+ $_mimes = file_exists(APPPATH.'config/mimes.php')
+ ? include(APPPATH.'config/mimes.php')
+ : array();
- if ( ! isset($config[$item]))
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
- return FALSE;
+ $_mimes = array_merge($_mimes, include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'));
}
- $_config_item[$item] = $config[$item];
}
- if ($value !== null) {
- $_config_item[$item] = $value;
+ return $_mimes;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_https'))
+{
+ /**
+ * Is HTTPS?
+ *
+ * Determines if the application is accessed via an encrypted
+ * (HTTPS) connection.
+ *
+ * @return bool
+ */
+ function is_https()
+ {
+ if ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off')
+ {
+ return TRUE;
+ }
+ elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
+ {
+ return TRUE;
+ }
+ elseif ( ! empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower($_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off')
+ {
+ return TRUE;
}
- return $_config_item[$item];
+ return FALSE;
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('is_cli'))
+{
+
+ /**
+ * Is CLI?
+ *
+ * Test to see if a request was made from the command line.
+ *
+ * @return bool
+ */
+ function is_cli()
+ {
+ return (PHP_SAPI === 'cli' OR defined('STDIN'));
}
}
// ------------------------------------------------------------------------
-/**
-* Error Handler
-*
-* This function lets us invoke the exception class and
-* display errors using the standard error template located
-* in application/errors/errors.php
-* This function will send the error page directly to the
-* browser and exit.
-*
-* @access public
-* @return void
-*/
if ( ! function_exists('show_error'))
{
+ /**
+ * Error Handler
+ *
+ * This function lets us invoke the exception class and
+ * display errors using the standard error template located
+ * in application/views/errors/error_general.php
+ * This function will send the error page directly to the
+ * browser and exit.
+ *
+ * @param string
+ * @param int
+ * @param string
+ * @return void
+ */
function show_error($message, $status_code = 500, $heading = 'An Error Was Encountered')
{
+ $status_code = abs($status_code);
+ if ($status_code < 100)
+ {
+ $exit_status = $status_code + 9; // 9 is EXIT__AUTO_MIN
+ $status_code = 500;
+ }
+ else
+ {
+ $exit_status = 1; // EXIT_ERROR
+ }
+
$_error =& load_class('Exceptions', 'core');
echo $_error->show_error($heading, $message, 'error_general', $status_code);
- exit;
+ exit($exit_status);
}
}
// ------------------------------------------------------------------------
-/**
-* 404 Page Handler
-*
-* This function is similar to the show_error() function above
-* However, instead of the standard error template it displays
-* 404 errors.
-*
-* @access public
-* @return void
-*/
if ( ! function_exists('show_404'))
{
+ /**
+ * 404 Page Handler
+ *
+ * This function is similar to the show_error() function above
+ * However, instead of the standard error template it displays
+ * 404 errors.
+ *
+ * @param string
+ * @param bool
+ * @return void
+ */
function show_404($page = '', $log_error = TRUE)
{
$_error =& load_class('Exceptions', 'core');
$_error->show_404($page, $log_error);
- exit;
+ exit(4); // EXIT_UNKNOWN_FILE
}
}
// ------------------------------------------------------------------------
-/**
-* Error Logging Interface
-*
-* We use this as a simple mechanism to access the logging
-* class and send messages to be logged.
-*
-* @access public
-* @return void
-*/
if ( ! function_exists('log_message'))
{
- function log_message($level = 'error', $message, $php_error = FALSE)
+ /**
+ * Error Logging Interface
+ *
+ * We use this as a simple mechanism to access the logging
+ * class and send messages to be logged.
+ *
+ * @param string the error level: 'error', 'debug' or 'info'
+ * @param string the error message
+ * @return void
+ */
+ function log_message($level, $message)
{
static $_log;
- if (config_item('log_threshold') == 0)
+ if ($_log === NULL)
{
- return;
+ // references cannot be directly assigned to static variables, so we use an array
+ $_log[0] =& load_class('Log', 'core');
}
- $_log =& load_class('Log');
- $_log->write_log($level, $message, $php_error);
+ $_log[0]->write_log($level, $message);
}
}
// ------------------------------------------------------------------------
-/**
- * Set HTTP Status Header
- *
- * @access public
- * @param int the status code
- * @param string
- * @return void
- */
if ( ! function_exists('set_status_header'))
{
+ /**
+ * Set HTTP Status Header
+ *
+ * @param int the status code
+ * @param string
+ * @return void
+ */
function set_status_header($code = 200, $text = '')
{
- $stati = array(
- 200 => 'OK',
- 201 => 'Created',
- 202 => 'Accepted',
- 203 => 'Non-Authoritative Information',
- 204 => 'No Content',
- 205 => 'Reset Content',
- 206 => 'Partial Content',
-
- 300 => 'Multiple Choices',
- 301 => 'Moved Permanently',
- 302 => 'Found',
- 304 => 'Not Modified',
- 305 => 'Use Proxy',
- 307 => 'Temporary Redirect',
-
- 400 => 'Bad Request',
- 401 => 'Unauthorized',
- 403 => 'Forbidden',
- 404 => 'Not Found',
- 405 => 'Method Not Allowed',
- 406 => 'Not Acceptable',
- 407 => 'Proxy Authentication Required',
- 408 => 'Request Timeout',
- 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 Not Satisfiable',
- 417 => 'Expectation Failed',
-
- 500 => 'Internal Server Error',
- 501 => 'Not Implemented',
- 502 => 'Bad Gateway',
- 503 => 'Service Unavailable',
- 504 => 'Gateway Timeout',
- 505 => 'HTTP Version Not Supported'
- );
-
- if ($code == '' OR ! is_numeric($code))
+ if (is_cli())
{
- show_error('Status codes must be numeric', 500);
+ return;
}
- if (isset($stati[$code]) AND $text == '')
+ if (empty($code) OR ! is_numeric($code))
{
- $text = $stati[$code];
+ show_error('Status codes must be numeric', 500);
}
- if ($text == '')
+ if (empty($text))
{
- show_error('No status text available. Please check your status code number or supply your own message text.', 500);
+ is_int($code) OR $code = (int) $code;
+ $stati = array(
+ 100 => 'Continue',
+ 101 => 'Switching Protocols',
+
+ 200 => 'OK',
+ 201 => 'Created',
+ 202 => 'Accepted',
+ 203 => 'Non-Authoritative Information',
+ 204 => 'No Content',
+ 205 => 'Reset Content',
+ 206 => 'Partial Content',
+
+ 300 => 'Multiple Choices',
+ 301 => 'Moved Permanently',
+ 302 => 'Found',
+ 303 => 'See Other',
+ 304 => 'Not Modified',
+ 305 => 'Use Proxy',
+ 307 => 'Temporary 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 Timeout',
+ 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 Not Satisfiable',
+ 417 => 'Expectation Failed',
+ 422 => 'Unprocessable Entity',
+ 426 => 'Upgrade Required',
+ 428 => 'Precondition Required',
+ 429 => 'Too Many Requests',
+ 431 => 'Request Header Fields Too Large',
+
+ 500 => 'Internal Server Error',
+ 501 => 'Not Implemented',
+ 502 => 'Bad Gateway',
+ 503 => 'Service Unavailable',
+ 504 => 'Gateway Timeout',
+ 505 => 'HTTP Version Not Supported',
+ 511 => 'Network Authentication Required',
+ );
+
+ if (isset($stati[$code]))
+ {
+ $text = $stati[$code];
+ }
+ else
+ {
+ show_error('No status text available. Please check your status code number or supply your own message text.', 500);
+ }
}
- $server_protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
-
- if (substr(php_sapi_name(), 0, 3) == 'cgi')
- {
- header("Status: {$code} {$text}", TRUE);
- }
- elseif ($server_protocol == 'HTTP/1.1' OR $server_protocol == 'HTTP/1.0')
- {
- header($server_protocol." {$code} {$text}", TRUE, $code);
- }
- else
+ if (strpos(PHP_SAPI, 'cgi') === 0)
{
- header("HTTP/1.1 {$code} {$text}", TRUE, $code);
+ header('Status: '.$code.' '.$text, TRUE);
+ return;
}
+
+ $server_protocol = (isset($_SERVER['SERVER_PROTOCOL']) && in_array($_SERVER['SERVER_PROTOCOL'], array('HTTP/1.0', 'HTTP/1.1', 'HTTP/2'), TRUE))
+ ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.1';
+ header($server_protocol.' '.$code.' '.$text, TRUE, $code);
}
}
// --------------------------------------------------------------------
-/**
-* Exception Handler
-*
-* This is the custom exception handler that is declaired at the top
-* of Codeigniter.php. The main reason we use this is to permit
-* PHP errors to be logged in our own log files since the user may
-* not have access to server logs. Since this function
-* effectively intercepts PHP errors, however, we also need
-* to display errors based on the current error_reporting level.
-* We do that with the use of a PHP error template.
-*
-* @access private
-* @return void
-*/
-if ( ! function_exists('_exception_handler'))
+if ( ! function_exists('_error_handler'))
{
- function _exception_handler($severity, $message, $filepath, $line)
+ /**
+ * Error Handler
+ *
+ * This is the custom error handler that is declared at the (relative)
+ * top of CodeIgniter.php. The main reason we use this is to permit
+ * PHP errors to be logged in our own log files since the user may
+ * not have access to server logs. Since this function effectively
+ * intercepts PHP errors, however, we also need to display errors
+ * based on the current error_reporting level.
+ * We do that with the use of a PHP error template.
+ *
+ * @param int $severity
+ * @param string $message
+ * @param string $filepath
+ * @param int $line
+ * @return void
+ */
+ function _error_handler($severity, $message, $filepath, $line)
{
- // We don't bother with "strict" notices since they tend to fill up
- // the log file with excess information that isn't normally very helpful.
- // For example, if you are running PHP 5 and you use version 4 style
- // class functions (without prefixes like "public", "private", etc.)
- // you'll get notices telling you that these have been deprecated.
- if ($severity == E_STRICT)
+ $is_error = (((E_ERROR | E_PARSE | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
+
+ // When an error occurred, set the status header to '500 Internal Server Error'
+ // to indicate to the client something went wrong.
+ // This can't be done within the $_error->show_php_error method because
+ // it is only called when the display_errors flag is set (which isn't usually
+ // the case in a production environment) or when errors are ignored because
+ // they are above the error_reporting threshold.
+ if ($is_error)
+ {
+ set_status_header(500);
+ }
+
+ // Should we ignore the error? We'll get the current error_reporting
+ // level and add its bits with the severity bits to find out.
+ if (($severity & error_reporting()) !== $severity)
{
return;
}
$_error =& load_class('Exceptions', 'core');
+ $_error->log_exception($severity, $message, $filepath, $line);
- // Should we display the error? We'll get the current error_reporting
- // level and add its bits with the severity bits to find out.
- if (($severity & error_reporting()) == $severity)
+ // Should we display the error?
+ if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))
{
$_error->show_php_error($severity, $message, $filepath, $line);
}
- // Should we log the error? No? We're done...
- if (config_item('log_threshold') == 0)
+ // If the error is fatal, the execution of the script should be stopped because
+ // errors can't be recovered from. Halting the script conforms with PHP's
+ // default error handling. See http://www.php.net/manual/en/errorfunc.constants.php
+ if ($is_error)
{
- return;
+ exit(1); // EXIT_ERROR
}
+ }
+}
- $_error->log_exception($severity, $message, $filepath, $line);
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_exception_handler'))
+{
+ /**
+ * Exception Handler
+ *
+ * Sends uncaught exceptions to the logger and displays them
+ * only if display_errors is On so that they don't show up in
+ * production environments.
+ *
+ * @param Exception $exception
+ * @return void
+ */
+ function _exception_handler($exception)
+ {
+ $_error =& load_class('Exceptions', 'core');
+ $_error->log_exception('error', 'Exception: '.$exception->getMessage(), $exception->getFile(), $exception->getLine());
+
+ is_cli() OR set_status_header(500);
+ // Should we display the error?
+ if (str_ireplace(array('off', 'none', 'no', 'false', 'null'), '', ini_get('display_errors')))
+ {
+ $_error->show_exception($exception);
+ }
+
+ exit(1); // EXIT_ERROR
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_shutdown_handler'))
+{
+ /**
+ * Shutdown Handler
+ *
+ * This is the shutdown handler that is declared at the top
+ * of CodeIgniter.php. The main reason we use this is to simulate
+ * a complete custom exception handler.
+ *
+ * E_STRICT is purposively neglected because such events may have
+ * been caught. Duplication or none? None is preferred for now.
+ *
+ * @link http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a
+ * @return void
+ */
+ function _shutdown_handler()
+ {
+ $last_error = error_get_last();
+ if (isset($last_error) &&
+ ($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))
+ {
+ _error_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
+ }
}
}
// --------------------------------------------------------------------
-/**
- * Remove Invisible Characters
- *
- * This prevents sandwiching null characters
- * between ascii characters, like Java\0script.
- *
- * @access public
- * @param string
- * @return string
- */
if ( ! function_exists('remove_invisible_characters'))
{
+ /**
+ * Remove Invisible Characters
+ *
+ * This prevents sandwiching null characters
+ * between ascii characters, like Java\0script.
+ *
+ * @param string
+ * @param bool
+ * @return string
+ */
function remove_invisible_characters($str, $url_encoded = TRUE)
{
$non_displayables = array();
-
- // every control character except newline (dec 10)
- // carriage return (dec 13), and horizontal tab (dec 09)
-
+
+ // every control character except newline (dec 10),
+ // carriage return (dec 13) and horizontal tab (dec 09)
if ($url_encoded)
{
- $non_displayables[] = '/%0[0-8bcef]/'; // url encoded 00-08, 11, 12, 14, 15
- $non_displayables[] = '/%1[0-9a-f]/'; // url encoded 16-31
+ $non_displayables[] = '/%0[0-8bcef]/i'; // url encoded 00-08, 11, 12, 14, 15
+ $non_displayables[] = '/%1[0-9a-f]/i'; // url encoded 16-31
+ $non_displayables[] = '/%7f/i'; // url encoded 127
}
-
+
$non_displayables[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
do
@@ -548,27 +732,118 @@ if ( ! function_exists('remove_invisible_characters'))
// ------------------------------------------------------------------------
-/**
-* Returns HTML escaped variable
-*
-* @access public
-* @param mixed
-* @return mixed
-*/
if ( ! function_exists('html_escape'))
{
- function html_escape($var)
+ /**
+ * Returns HTML escaped variable.
+ *
+ * @param mixed $var The input string or array of strings to be escaped.
+ * @param bool $double_encode $double_encode set to FALSE prevents escaping twice.
+ * @return mixed The escaped string or array of strings as a result.
+ */
+ function html_escape($var, $double_encode = TRUE)
{
+ if (empty($var))
+ {
+ return $var;
+ }
+
if (is_array($var))
{
- return array_map('html_escape', $var);
+ foreach (array_keys($var) as $key)
+ {
+ $var[$key] = html_escape($var[$key], $double_encode);
+ }
+
+ return $var;
}
- else
+
+ return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_stringify_attributes'))
+{
+ /**
+ * Stringify attributes for use in HTML tags.
+ *
+ * Helper function used to convert a string, array, or object
+ * of attributes to a string.
+ *
+ * @param mixed string, array, object
+ * @param bool
+ * @return string
+ */
+ function _stringify_attributes($attributes, $js = FALSE)
+ {
+ $atts = NULL;
+
+ if (empty($attributes))
+ {
+ return $atts;
+ }
+
+ if (is_string($attributes))
{
- return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
+ return ' '.$attributes;
}
+
+ $attributes = (array) $attributes;
+
+ foreach ($attributes as $key => $val)
+ {
+ $atts .= ($js) ? $key.'='.$val.',' : ' '.$key.'="'.$val.'"';
+ }
+
+ return rtrim($atts, ',');
}
}
-/* End of file Common.php */
-/* Location: ./system/core/Common.php */ \ No newline at end of file
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('function_usable'))
+{
+ /**
+ * Function usable
+ *
+ * Executes a function_exists() check, and if the Suhosin PHP
+ * extension is loaded - checks whether the function that is
+ * checked might be disabled in there as well.
+ *
+ * This is useful as function_exists() will return FALSE for
+ * functions disabled via the *disable_functions* php.ini
+ * setting, but not for *suhosin.executor.func.blacklist* and
+ * *suhosin.executor.disable_eval*. These settings will just
+ * terminate script execution if a disabled function is executed.
+ *
+ * The above described behavior turned out to be a bug in Suhosin,
+ * but even though a fix was committed for 0.9.34 on 2012-02-12,
+ * that version is yet to be released. This function will therefore
+ * be just temporary, but would probably be kept for a few years.
+ *
+ * @link http://www.hardened-php.net/suhosin/
+ * @param string $function_name Function to check for
+ * @return bool TRUE if the function exists and is safe to call,
+ * FALSE otherwise.
+ */
+ function function_usable($function_name)
+ {
+ static $_suhosin_func_blacklist;
+
+ if (function_exists($function_name))
+ {
+ if ( ! isset($_suhosin_func_blacklist))
+ {
+ $_suhosin_func_blacklist = extension_loaded('suhosin')
+ ? explode(',', trim(ini_get('suhosin.executor.func.blacklist')))
+ : array();
+ }
+
+ return ! in_array($function_name, $_suhosin_func_blacklist, TRUE);
+ }
+
+ return FALSE;
+ }
+}