summaryrefslogtreecommitdiffstats
path: root/system/core
diff options
context:
space:
mode:
Diffstat (limited to 'system/core')
-rw-r--r--system/core/CodeIgniter.php89
-rw-r--r--system/core/Common.php14
-rw-r--r--system/core/Config.php16
-rw-r--r--system/core/Exceptions.php12
-rw-r--r--system/core/Hooks.php6
-rw-r--r--system/core/Input.php285
-rw-r--r--system/core/Loader.php72
-rw-r--r--system/core/Log.php29
-rw-r--r--system/core/Model.php8
-rw-r--r--system/core/Output.php19
-rw-r--r--system/core/Router.php43
-rw-r--r--system/core/Security.php43
-rw-r--r--system/core/URI.php122
-rw-r--r--system/core/Utf8.php14
-rw-r--r--system/core/compat/hash.php6
-rw-r--r--system/core/compat/index.html2
-rw-r--r--system/core/compat/mbstring.php6
-rw-r--r--system/core/compat/password.php10
-rw-r--r--system/core/compat/standard.php50
-rw-r--r--system/core/index.html2
20 files changed, 237 insertions, 611 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index e1d5d07d1..87dd868f9 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -56,7 +56,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @var string
*
*/
- const CI_VERSION = '3.1.12-dev';
+ const CI_VERSION = '3.2.0-dev';
/*
* ------------------------------------------------------
@@ -80,57 +80,6 @@ defined('BASEPATH') OR exit('No direct script access allowed');
*/
require_once(BASEPATH.'core/Common.php');
-
-/*
- * ------------------------------------------------------
- * Security procedures
- * ------------------------------------------------------
- */
-
-if ( ! is_php('5.4'))
-{
- ini_set('magic_quotes_runtime', 0);
-
- if ((bool) ini_get('register_globals'))
- {
- $_protected = array(
- '_SERVER',
- '_GET',
- '_POST',
- '_FILES',
- '_REQUEST',
- '_SESSION',
- '_ENV',
- '_COOKIE',
- 'GLOBALS',
- 'HTTP_RAW_POST_DATA',
- 'system_path',
- 'application_folder',
- 'view_folder',
- '_protected',
- '_registered'
- );
-
- $_registered = ini_get('variables_order');
- foreach (array('E' => '_ENV', 'G' => '_GET', 'P' => '_POST', 'C' => '_COOKIE', 'S' => '_SERVER') as $key => $superglobal)
- {
- if (strpos($_registered, $key) === FALSE)
- {
- continue;
- }
-
- foreach (array_keys($$superglobal) as $var)
- {
- if (isset($GLOBALS[$var]) && ! in_array($var, $_protected, TRUE))
- {
- $GLOBALS[$var] = NULL;
- }
- }
- }
- }
-}
-
-
/*
* ------------------------------------------------------
* Define a custom error handler so we can log PHP errors
@@ -195,20 +144,6 @@ if ( ! is_php('5.4'))
/*
* ------------------------------------------------------
- * Instantiate the hooks class
- * ------------------------------------------------------
- */
- $EXT =& load_class('Hooks', 'core');
-
-/*
- * ------------------------------------------------------
- * Is there a "pre_system" hook?
- * ------------------------------------------------------
- */
- $EXT->call_hook('pre_system');
-
-/*
- * ------------------------------------------------------
* Instantiate the config class
* ------------------------------------------------------
*
@@ -230,6 +165,20 @@ if ( ! is_php('5.4'))
/*
* ------------------------------------------------------
+ * Instantiate the hooks class
+ * ------------------------------------------------------
+ */
+ $EXT =& load_class('Hooks', 'core', $CFG);
+
+/*
+ * ------------------------------------------------------
+ * Is there a "pre_system" hook?
+ * ------------------------------------------------------
+ */
+ $EXT->call_hook('pre_system');
+
+/*
+ * ------------------------------------------------------
* Important charset-related stuff
* ------------------------------------------------------
*
@@ -295,14 +244,14 @@ if ( ! is_php('5.4'))
* Instantiate the UTF-8 class
* ------------------------------------------------------
*/
- $UNI =& load_class('Utf8', 'core');
+ $UNI =& load_class('Utf8', 'core', $charset);
/*
* ------------------------------------------------------
* Instantiate the URI class
* ------------------------------------------------------
*/
- $URI =& load_class('URI', 'core');
+ $URI =& load_class('URI', 'core', $CFG);
/*
* ------------------------------------------------------
@@ -333,14 +282,14 @@ if ( ! is_php('5.4'))
* Load the security class for xss and csrf support
* -----------------------------------------------------
*/
- $SEC =& load_class('Security', 'core');
+ $SEC =& load_class('Security', 'core', $charset);
/*
* ------------------------------------------------------
* Load the Input class and sanitize globals
* ------------------------------------------------------
*/
- $IN =& load_class('Input', 'core');
+ $IN =& load_class('Input', 'core', $SEC);
/*
* ------------------------------------------------------
diff --git a/system/core/Common.php b/system/core/Common.php
index a56cb1464..c7bb34549 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -82,8 +82,7 @@ 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.
+ * the file, based on the read-only attribute.
*
* @link https://bugs.php.net/bug.php?id=54709
* @param string
@@ -91,8 +90,8 @@ if ( ! function_exists('is_really_writable'))
*/
function is_really_writable($file)
{
- // If we're on a Unix server with safe_mode off we call is_writable
- if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR ! ini_get('safe_mode')))
+ // If we're on a UNIX-like server, just is_writable()
+ if (DIRECTORY_SEPARATOR === '/')
{
return is_writable($file);
}
@@ -500,6 +499,7 @@ if ( ! function_exists('set_status_header'))
$stati = array(
100 => 'Continue',
101 => 'Switching Protocols',
+ 103 => 'Early Hints',
200 => 'OK',
201 => 'Created',
@@ -508,6 +508,7 @@ if ( ! function_exists('set_status_header'))
204 => 'No Content',
205 => 'Reset Content',
206 => 'Partial Content',
+ 207 => 'Multi-Status',
300 => 'Multiple Choices',
301 => 'Moved Permanently',
@@ -516,6 +517,7 @@ if ( ! function_exists('set_status_header'))
304 => 'Not Modified',
305 => 'Use Proxy',
307 => 'Temporary Redirect',
+ 308 => 'Permanent Redirect',
400 => 'Bad Request',
401 => 'Unauthorized',
@@ -535,11 +537,13 @@ if ( ! function_exists('set_status_header'))
415 => 'Unsupported Media Type',
416 => 'Requested Range Not Satisfiable',
417 => 'Expectation Failed',
+ 421 => 'Misdirected Request',
422 => 'Unprocessable Entity',
426 => 'Upgrade Required',
428 => 'Precondition Required',
429 => 'Too Many Requests',
431 => 'Request Header Fields Too Large',
+ 451 => 'Unavailable For Legal Reasons',
500 => 'Internal Server Error',
501 => 'Not Implemented',
@@ -626,7 +630,7 @@ if ( ! function_exists('_error_handler'))
// 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
+ // default error handling. See https://secure.php.net/manual/en/errorfunc.constants.php
if ($is_error)
{
exit(1); // EXIT_ERROR
diff --git a/system/core/Config.php b/system/core/Config.php
index 2454a9d71..4efe1e1ec 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -170,7 +170,7 @@ class CI_Config {
$this->is_loaded[] = $file_path;
$config = NULL;
$loaded = TRUE;
- log_message('debug', 'Config file loaded: '.$file_path);
+ log_message('info', 'Config file loaded: '.$file_path);
}
}
@@ -352,20 +352,6 @@ class CI_Config {
// --------------------------------------------------------------------
/**
- * System URL
- *
- * @deprecated 3.0.0 Encourages insecure practices
- * @return string
- */
- public function system_url()
- {
- $x = explode('/', preg_replace('|/*(.+?)/*$|', '\\1', BASEPATH));
- return $this->slash_item('base_url').end($x).'/';
- }
-
- // --------------------------------------------------------------------
-
- /**
* Set a config file item
*
* @param string $item Config item key
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index b1bc2dec5..7244f3f28 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -162,6 +162,10 @@ class CI_Exceptions {
{
$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
}
+ else
+ {
+ $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR;
+ }
if (is_cli())
{
@@ -195,6 +199,10 @@ class CI_Exceptions {
{
$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
}
+ else
+ {
+ $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR;
+ }
$message = $exception->getMessage();
if (empty($message))
@@ -241,6 +249,10 @@ class CI_Exceptions {
{
$templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
}
+ else
+ {
+ $templates_path = rtrim($templates_path, '/\\').DIRECTORY_SEPARATOR;
+ }
$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 2246bbcb6..20248aa8a 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -84,16 +84,16 @@ class CI_Hooks {
/**
* Class constructor
*
+ * @param CI_Config $config
* @return void
*/
- public function __construct()
+ public function __construct(CI_Config $config)
{
- $CFG =& load_class('Config', 'core');
log_message('info', 'Hooks Class Initialized');
// If hooks are not enabled in the config file
// there is nothing else to do
- if ($CFG->item('enable_hooks') === FALSE)
+ if ($config->item('enable_hooks') === FALSE)
{
return;
}
diff --git a/system/core/Input.php b/system/core/Input.php
index eba5f67f0..59ca3e112 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -59,45 +59,6 @@ class CI_Input {
protected $ip_address = FALSE;
/**
- * Allow GET array flag
- *
- * If set to FALSE, then $_GET will be set to an empty array.
- *
- * @var bool
- */
- protected $_allow_get_array = TRUE;
-
- /**
- * Standardize new lines flag
- *
- * If set to TRUE, then newlines are standardized.
- *
- * @var bool
- */
- protected $_standardize_newlines;
-
- /**
- * Enable XSS flag
- *
- * Determines whether the XSS filter is always active when
- * GET, POST or COOKIE data is encountered.
- * Set automatically based on config setting.
- *
- * @var bool
- */
- protected $_enable_xss = FALSE;
-
- /**
- * Enable CSRF flag
- *
- * Enables a CSRF cookie token to be set.
- * Set automatically based on config setting.
- *
- * @var bool
- */
- protected $_enable_csrf = FALSE;
-
- /**
* List of all HTTP request headers
*
* @var array
@@ -123,8 +84,15 @@ class CI_Input {
*/
protected $_input_stream;
+ /**
+ * CI_Security instance
+ *
+ * Used for the optional $xss_filter parameter that most
+ * getter methods have here.
+ *
+ * @var CI_Security
+ */
protected $security;
- protected $uni;
// --------------------------------------------------------------------
@@ -136,30 +104,9 @@ class CI_Input {
*
* @return void
*/
- public function __construct()
+ public function __construct(CI_Security &$security)
{
- $this->_allow_get_array = (config_item('allow_get_array') !== FALSE);
- $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
- $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
- $this->_standardize_newlines = (bool) config_item('standardize_newlines');
-
- $this->security =& load_class('Security', 'core');
-
- // Do we need the UTF-8 class?
- if (UTF8_ENABLED === TRUE)
- {
- $this->uni =& load_class('Utf8', 'core');
- }
-
- // Sanitize global arrays
- $this->_sanitize_globals();
-
- // CSRF Protection check
- if ($this->_enable_csrf === TRUE && ! is_cli())
- {
- $this->security->csrf_verify();
- }
-
+ $this->security = $security;
log_message('info', 'Input Class Initialized');
}
@@ -175,10 +122,8 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = NULL)
+ protected function _fetch_from_array(&$array, $index = NULL, $xss_clean = FALSE)
{
- is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
-
// If $index is NULL, it means that the whole $array is requested
isset($index) OR $index = array_keys($array);
@@ -238,7 +183,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function get($index = NULL, $xss_clean = NULL)
+ public function get($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_GET, $index, $xss_clean);
}
@@ -252,7 +197,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function post($index = NULL, $xss_clean = NULL)
+ public function post($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_POST, $index, $xss_clean);
}
@@ -266,11 +211,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function post_get($index, $xss_clean = NULL)
+ public function post_get($index, $xss_clean = FALSE)
{
- return isset($_POST[$index])
- ? $this->post($index, $xss_clean)
- : $this->get($index, $xss_clean);
+ $output = $this->post($index, $xss_clean);
+ return isset($output) ? $output : $this->get($index, $xss_clean);
}
// --------------------------------------------------------------------
@@ -282,11 +226,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function get_post($index, $xss_clean = NULL)
+ public function get_post($index, $xss_clean = FALSE)
{
- return isset($_GET[$index])
- ? $this->get($index, $xss_clean)
- : $this->post($index, $xss_clean);
+ $output = $this->get($index, $xss_clean);
+ return isset($output) ? $output : $this->post($index, $xss_clean);
}
// --------------------------------------------------------------------
@@ -298,7 +241,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function cookie($index = NULL, $xss_clean = NULL)
+ public function cookie($index = NULL, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
}
@@ -312,7 +255,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function server($index, $xss_clean = NULL)
+ public function server($index, $xss_clean = FALSE)
{
return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
}
@@ -328,7 +271,7 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function input_stream($index = NULL, $xss_clean = NULL)
+ public function input_stream($index = NULL, $xss_clean = FALSE)
{
// Prior to PHP 5.6, the input stream can only be read once,
// so we'll need to check if we have already done that first.
@@ -361,7 +304,7 @@ class CI_Input {
* @param string $samesite SameSite attribute
* @return void
*/
- public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL)
+ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = NULL, $httponly = NULL, $samesite = NULL)
{
if (is_array($name))
{
@@ -398,9 +341,9 @@ class CI_Input {
? (bool) config_item('cookie_httponly')
: (bool) $httponly;
- if ( ! is_numeric($expire))
+ if ( ! is_numeric($expire) OR $expire < 0)
{
- $expire = time() - 86500;
+ $expire = 1;
}
else
{
@@ -621,7 +564,7 @@ class CI_Input {
*
* @return string|null User Agent string or NULL if it doesn't exist
*/
- public function user_agent($xss_clean = NULL)
+ public function user_agent($xss_clean = FALSE)
{
return $this->_fetch_from_array($_SERVER, 'HTTP_USER_AGENT', $xss_clean);
}
@@ -629,167 +572,6 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Sanitize Globals
- *
- * Internal method serving for the following purposes:
- *
- * - Unsets $_GET data, if query strings are not enabled
- * - Cleans POST, COOKIE and SERVER data
- * - Standardizes newline characters to PHP_EOL
- *
- * @return void
- */
- protected function _sanitize_globals()
- {
- // Is $_GET data allowed? If not we'll set the $_GET to an empty array
- if ($this->_allow_get_array === FALSE)
- {
- $_GET = array();
- }
- elseif (is_array($_GET))
- {
- foreach ($_GET as $key => $val)
- {
- $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
- }
-
- // Clean $_POST Data
- if (is_array($_POST))
- {
- foreach ($_POST as $key => $val)
- {
- $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
- }
-
- // Clean $_COOKIE Data
- if (is_array($_COOKIE))
- {
- // Also get rid of specially treated cookies that might be set by a server
- // or silly application, that are of no use to a CI application anyway
- // but that when present will trip our 'Disallowed Key Characters' alarm
- // http://www.ietf.org/rfc/rfc2109.txt
- // note that the key names below are single quoted strings, and are not PHP variables
- unset(
- $_COOKIE['$Version'],
- $_COOKIE['$Path'],
- $_COOKIE['$Domain']
- );
-
- foreach ($_COOKIE as $key => $val)
- {
- if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
- {
- $_COOKIE[$cookie_key] = $this->_clean_input_data($val);
- }
- else
- {
- unset($_COOKIE[$key]);
- }
- }
- }
-
- // Sanitize PHP_SELF
- $_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
-
- log_message('debug', 'Global POST, GET and COOKIE data sanitized');
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Clean Input Data
- *
- * Internal method that aids in escaping data and
- * standardizing newline characters to PHP_EOL.
- *
- * @param string|string[] $str Input string(s)
- * @return string
- */
- protected function _clean_input_data($str)
- {
- if (is_array($str))
- {
- $new_array = array();
- foreach (array_keys($str) as $key)
- {
- $new_array[$this->_clean_input_keys($key)] = $this->_clean_input_data($str[$key]);
- }
- return $new_array;
- }
-
- /* We strip slashes if magic quotes is on to keep things consistent
-
- NOTE: In PHP 5.4 get_magic_quotes_gpc() will always return 0 and
- it will probably not exist in future versions at all.
- */
- if ( ! is_php('5.4') && get_magic_quotes_gpc())
- {
- $str = stripslashes($str);
- }
-
- // Clean UTF-8 if supported
- if (UTF8_ENABLED === TRUE)
- {
- $str = $this->uni->clean_string($str);
- }
-
- // Remove control characters
- $str = remove_invisible_characters($str, FALSE);
-
- // Standardize newlines if needed
- if ($this->_standardize_newlines === TRUE)
- {
- return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
- }
-
- return $str;
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Clean Keys
- *
- * Internal method that helps to prevent malicious users
- * from trying to exploit keys we make sure that keys are
- * only named with alpha-numeric text and a few other items.
- *
- * @param string $str Input string
- * @param bool $fatal Whether to terminate script exection
- * or to return FALSE if an invalid
- * key is encountered
- * @return string|bool
- */
- protected function _clean_input_keys($str, $fatal = TRUE)
- {
- if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
- {
- if ($fatal === TRUE)
- {
- return FALSE;
- }
- else
- {
- set_status_header(503);
- echo 'Disallowed Key Characters.';
- exit(7); // EXIT_USER_INPUT
- }
- }
-
- // Clean UTF-8 if supported
- if (UTF8_ENABLED === TRUE)
- {
- return $this->uni->clean_string($str);
- }
-
- return $str;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Request Headers
*
* @param bool $xss_clean Whether to apply XSS filtering
@@ -881,21 +663,6 @@ class CI_Input {
// --------------------------------------------------------------------
/**
- * Is CLI request?
- *
- * Test to see if a request was made from the command line.
- *
- * @deprecated 3.0.0 Use is_cli() instead
- * @return bool
- */
- public function is_cli_request()
- {
- return is_cli();
- }
-
- // --------------------------------------------------------------------
-
- /**
* Get Request Method
*
* Return the request method
diff --git a/system/core/Loader.php b/system/core/Loader.php
index a70487e84..648b7cfc7 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -95,6 +95,13 @@ class CI_Loader {
protected $_ci_cached_vars = array();
/**
+ * Stack of variable arrays to provide nested _ci_load calls with all variables from parent calls
+ *
+ * @var array
+ */
+ protected $_ci_load_vars_stack = array();
+
+ /**
* List of loaded classes
*
* @var array
@@ -349,9 +356,10 @@ class CI_Loader {
throw new RuntimeException('Unable to locate the model you have specified: '.$model);
}
}
- elseif ( ! is_subclass_of($model, 'CI_Model'))
+
+ if ( ! is_subclass_of($model, 'CI_Model'))
{
- throw new RuntimeException("Class ".$model." already exists and doesn't extend CI_Model");
+ throw new RuntimeException("Class ".$model." doesn't extend CI_Model");
}
$this->_ci_models[] = $name;
@@ -368,19 +376,16 @@ class CI_Loader {
*
* @param mixed $params Database configuration options
* @param bool $return Whether to return the database object
- * @param bool $query_builder Whether to enable Query Builder
- * (overrides the configuration setting)
- *
* @return object|bool Database object if $return is set to TRUE,
* FALSE on failure, CI_Loader instance in any other case
*/
- public function database($params = '', $return = FALSE, $query_builder = NULL)
+ public function database($params = '', $return = FALSE)
{
// Grab the super object
$CI =& get_instance();
// Do we even need to load the database class?
- if ($return === FALSE && $query_builder === NULL && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
+ if ($return === FALSE && isset($CI->db) && is_object($CI->db) && ! empty($CI->db->conn_id))
{
return FALSE;
}
@@ -389,7 +394,7 @@ class CI_Loader {
if ($return === TRUE)
{
- return DB($params, $query_builder);
+ return DB($params);
}
// Initialize the db variable. Needed to prevent
@@ -397,7 +402,7 @@ class CI_Loader {
$CI->db = '';
// Load the DB class
- $CI->db =& DB($params, $query_builder);
+ $CI->db =& DB($params);
return $this;
}
@@ -934,17 +939,38 @@ class CI_Loader {
}
/*
- * Extract and cache variables
+ * Extract and stack variables
*
* You can either set variables using the dedicated $this->load->vars()
* function or via the second parameter of this function. We'll merge
- * the two types and cache them so that views that are embedded within
- * other views can have access to these variables.
+ * the two types so that loaded views and files have access to these
+ * variables.
+ * Additionally we want all subsequent nested _ci_load() calls embedded
+ * within the current file to 'inherit' all variables that are
+ * accessible to the current file. For this purpose we push the current
+ * variable configuration (_ci_vars) to the stack and remove it again
+ * after the file or view is completely loaded. Nested _ci_load() calls
+ * within the current file extend the stack with their variable
+ * configuration.
*/
- empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
- extract($this->_ci_cached_vars);
- /*
+ is_array($_ci_vars) OR $_ci_vars = array();
+
+ // Include the global cached vars into the current _ci_vars if needed
+ empty($this->_ci_cached_vars) OR $_ci_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
+
+ // Merge the last variable configuration from a parent _ci_load()
+ // call into the current _ci_vars
+ if ( ! empty($this->_ci_load_vars_stack))
+ {
+ $previous_variable_configuration = end($this->_ci_load_vars_stack);
+ $_ci_vars = array_merge($previous_variable_configuration, $_ci_vars);
+ }
+
+ array_push($this->_ci_load_vars_stack, $_ci_vars);
+ extract($_ci_vars);
+
+ /**
* Buffer the output
*
* We buffer the output for two reasons:
@@ -957,20 +983,12 @@ class CI_Loader {
*/
ob_start();
- // If the PHP installation does not support short tags we'll
- // do a little string replacement, changing the short tags
- // to standard PHP echo statements.
- if ( ! is_php('5.4') && ! ini_get('short_open_tag') && config_item('rewrite_short_tags') === TRUE)
- {
- echo eval('?>'.preg_replace('/;*\s*\?>/', '; ?>', str_replace('<?=', '<?php echo ', file_get_contents($_ci_path))));
- }
- else
- {
- include($_ci_path); // include() vs include_once() allows for multiple views with the same name
- }
-
+ include($_ci_path); // include() vs include_once() allows for multiple views with the same name
log_message('info', 'File loaded: '.$_ci_path);
+ // Remove current _ci_vars from stack
+ array_pop($this->_ci_load_vars_stack);
+
// Return the file data if requested
if ($_ci_return === TRUE)
{
diff --git a/system/core/Log.php b/system/core/Log.php
index ca3e38a7f..99642e0c6 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -57,6 +57,13 @@ class CI_Log {
protected $_log_path;
/**
+ * Log filename
+ *
+ * @var string
+ */
+ protected $_log_filename;
+
+ /**
* File permissions
*
* @var int
@@ -85,13 +92,6 @@ class CI_Log {
protected $_date_fmt = 'Y-m-d H:i:s';
/**
- * Filename extension
- *
- * @var string
- */
- protected $_file_ext;
-
- /**
* Whether or not the logger can write to the log files
*
* @var bool
@@ -125,9 +125,11 @@ class CI_Log {
isset(self::$func_overload) OR self::$func_overload = ( ! is_php('8.0') && extension_loaded('mbstring') && @ini_get('mbstring.func_overload'));
- $this->_log_path = ($config['log_path'] !== '') ? $config['log_path'] : APPPATH.'logs/';
- $this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '')
- ? ltrim($config['log_file_extension'], '.') : 'php';
+ $this->_log_path = ($config['log_path'] !== '')
+ ? rtrim($config['log_path'], '/\\').DIRECTORY_SEPARATOR : APPPATH.'logs'.DIRECTORY_SEPARATOR;
+
+ $this->_log_filename = (isset($config['log_filename']) && $config['log_filename'] !== '')
+ ? $config['log_filename'] : 'log-'.date('Y-m-d').'.php';
file_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE);
@@ -183,14 +185,14 @@ class CI_Log {
return FALSE;
}
- $filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext;
+ $filepath = $this->_log_path.$this->_log_filename;
$message = '';
if ( ! file_exists($filepath))
{
$newfile = TRUE;
// Only add protection to php files
- if ($this->_file_ext === 'php')
+ if (substr($this->_log_filename, -3, 3) === 'php')
{
$message .= "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\n";
}
@@ -284,9 +286,6 @@ class CI_Log {
{
if (self::$func_overload)
{
- // mb_substr($str, $start, null, '8bit') returns an empty
- // string on PHP 5.3
- isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
return mb_substr($str, $start, $length, '8bit');
}
diff --git a/system/core/Model.php b/system/core/Model.php
index b2bbbd4d4..1ba10fbb7 100644
--- a/system/core/Model.php
+++ b/system/core/Model.php
@@ -50,14 +50,6 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_Model {
/**
- * Class constructor
- *
- * @link https://github.com/bcit-ci/CodeIgniter/issues/5332
- * @return void
- */
- public function __construct() {}
-
- /**
* __get magic
*
* Allows models to access CI's loaded classes using the same
diff --git a/system/core/Output.php b/system/core/Output.php
index a629a09d8..02f3933f5 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -417,7 +417,7 @@ class CI_Output {
* @param string $output Output data override
* @return void
*/
- public function _display($output = '')
+ public function _display($output = NULL)
{
// Note: We use load_class() because we can't use $CI =& get_instance()
// since this function is sometimes called by the caching mechanism,
@@ -434,7 +434,7 @@ class CI_Output {
// --------------------------------------------------------------------
// Set the output data
- if ($output === '')
+ if ($output === NULL)
{
$output =& $this->final_output;
}
@@ -507,7 +507,7 @@ class CI_Output {
echo $output;
log_message('info', 'Final output sent to browser');
- log_message('debug', 'Total execution time: '.$elapsed);
+ log_message('info', 'Total execution time: '.$elapsed);
return;
}
@@ -544,7 +544,7 @@ class CI_Output {
}
log_message('info', 'Final output sent to browser');
- log_message('debug', 'Total execution time: '.$elapsed);
+ log_message('info', 'Total execution time: '.$elapsed);
}
// --------------------------------------------------------------------
@@ -559,7 +559,7 @@ class CI_Output {
{
$CI =& get_instance();
$path = $CI->config->item('cache_path');
- $cache_path = ($path === '') ? APPPATH.'cache/' : $path;
+ $cache_path = ($path === '') ? APPPATH.'cache'.DIRECTORY_SEPARATOR : rtrim($path, '/\\').DIRECTORY_SEPARATOR;
if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
{
@@ -568,7 +568,7 @@ class CI_Output {
}
$uri = $CI->config->item('base_url')
- .$CI->config->item('index_page')
+ .$CI->config->slash_item('index_page')
.$CI->uri->uri_string();
if (($cache_query_string = $CI->config->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
@@ -663,7 +663,7 @@ class CI_Output {
$cache_path = ($CFG->item('cache_path') === '') ? APPPATH.'cache/' : $CFG->item('cache_path');
// Build the file path. The file name is an MD5 hash of the full URI
- $uri = $CFG->item('base_url').$CFG->item('index_page').$URI->uri_string;
+ $uri = $CFG->item('base_url').$CFG->slash_item('index_page').$URI->uri_string;
if (($cache_query_string = $CFG->item('cache_query_string')) && ! empty($_SERVER['QUERY_STRING']))
{
@@ -766,7 +766,7 @@ class CI_Output {
}
}
- $cache_path .= md5($CI->config->item('base_url').$CI->config->item('index_page').ltrim($uri, '/'));
+ $cache_path .= md5($CI->config->item('base_url').$CI->config->slash_item('index_page').ltrim($uri, '/'));
if ( ! @unlink($cache_path))
{
@@ -834,9 +834,6 @@ class CI_Output {
{
if (self::$func_overload)
{
- // mb_substr($str, $start, null, '8bit') returns an empty
- // string on PHP 5.3
- isset($length) OR $length = ($start >= 0 ? self::strlen($str) - $start : -$start);
return mb_substr($str, $start, $length, '8bit');
}
diff --git a/system/core/Router.php b/system/core/Router.php
index ab1f44e0e..e15ceff71 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -440,19 +440,6 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Fetch the current class
- *
- * @deprecated 3.0.0 Read the 'class' property instead
- * @return string
- */
- public function fetch_class()
- {
- return $this->class;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Set method name
*
* @param string $method Method name
@@ -466,19 +453,6 @@ class CI_Router {
// --------------------------------------------------------------------
/**
- * Fetch the current method
- *
- * @deprecated 3.0.0 Read the 'method' property instead
- * @return string
- */
- public function fetch_method()
- {
- return $this->method;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Set directory name
*
* @param string $dir Directory name
@@ -496,21 +470,4 @@ class CI_Router {
$this->directory .= str_replace('.', '', trim($dir, '/')).'/';
}
}
-
- // --------------------------------------------------------------------
-
- /**
- * Fetch directory
- *
- * Feches the sub-directory (if any) that contains the requested
- * controller class.
- *
- * @deprecated 3.0.0 Read the 'directory' property instead
- * @return string
- */
- public function fetch_directory()
- {
- return $this->directory;
- }
-
}
diff --git a/system/core/Security.php b/system/core/Security.php
index e7772e03d..d3c8b976e 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -170,10 +170,12 @@ class CI_Security {
*
* @return void
*/
- public function __construct()
+ public function __construct($charset)
{
+ $this->charset = $charset;
+
// Is CSRF protection enabled?
- if (config_item('csrf_protection'))
+ if (config_item('csrf_protection') && ! is_cli())
{
// CSRF config
foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)
@@ -192,10 +194,9 @@ class CI_Security {
// Set the CSRF hash
$this->_csrf_set_hash();
+ $this->csrf_verify();
}
- $this->charset = strtoupper((string) config_item('charset'));
-
log_message('info', 'Security Class Initialized');
}
@@ -659,7 +660,7 @@ class CI_Security {
if (is_readable('/dev/urandom') && ($fp = fopen('/dev/urandom', 'rb')) !== FALSE)
{
// Try not to waste entropy ...
- is_php('5.4') && stream_set_chunk_size($fp, $length);
+ stream_set_chunk_size($fp, $length);
$output = fread($fp, $length);
fclose($fp);
if ($output !== FALSE)
@@ -689,7 +690,7 @@ class CI_Security {
* correctly. html_entity_decode() does not convert entities without
* semicolons, so we are left with our own little solution here. Bummer.
*
- * @link http://php.net/html-entity-decode
+ * @link https://secure.php.net/html-entity-decode
*
* @param string $str Input
* @param string $charset Character set
@@ -704,26 +705,8 @@ class CI_Security {
static $_entities;
- isset($charset) OR $charset = $this->charset;
- $flag = is_php('5.4')
- ? ENT_COMPAT | ENT_HTML5
- : ENT_COMPAT;
-
- if ( ! isset($_entities))
- {
- $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, $flag, $charset));
-
- // If we're not on PHP 5.4+, add the possibly dangerous HTML 5
- // entities to the array manually
- if ($flag === ENT_COMPAT)
- {
- $_entities[':'] = '&colon;';
- $_entities['('] = '&lpar;';
- $_entities[')'] = '&rpar;';
- $_entities["\n"] = '&NewLine;';
- $_entities["\t"] = '&Tab;';
- }
- }
+ isset($charset) OR $charset = $this->charset;
+ isset($_entities) OR $_entities = array_map('strtolower', get_html_translation_table(HTML_ENTITIES, ENT_COMPAT | ENT_HTML5, $charset));
do
{
@@ -748,14 +731,9 @@ class CI_Security {
// Decode numeric & UTF16 two byte entities
$str = html_entity_decode(
preg_replace('/(&#(?:x0*[0-9a-f]{2,5}(?![0-9a-f;])|(?:0*\d{2,4}(?![0-9;]))))/iS', '$1;', $str),
- $flag,
+ ENT_COMPAT | ENT_HTML5,
$charset
);
-
- if ($flag === ENT_COMPAT)
- {
- $str = str_replace(array_values($_entities), array_keys($_entities), $str);
- }
}
while ($str_compare !== $str);
return $str;
@@ -1107,5 +1085,4 @@ class CI_Security {
return $this->_csrf_hash;
}
-
}
diff --git a/system/core/URI.php b/system/core/URI.php
index 6a55439f7..1e9485883 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -97,45 +97,40 @@ class CI_URI {
*
* @return void
*/
- public function __construct()
+ public function __construct(CI_Config $config)
{
- $this->config =& load_class('Config', 'core');
+ $this->config = $config;
+ // If it's a CLI request, ignore the configuration
+ if (is_cli())
+ {
+ $this->_set_uri_string($this->_parse_argv(), TRUE);
+ }
// If query strings are enabled, we don't need to parse any segments.
- // However, they don't make sense under CLI.
- if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE)
+ elseif ($this->config->item('enable_query_strings') !== TRUE)
{
$this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');
+ $protocol = $this->config->item('uri_protocol');
+ empty($protocol) && $protocol = 'REQUEST_URI';
- // If it's a CLI request, ignore the configuration
- if (is_cli())
+ switch ($protocol)
{
- $uri = $this->_parse_argv();
+ case 'AUTO': // For BC purposes only
+ case 'REQUEST_URI':
+ $uri = $this->_parse_request_uri();
+ break;
+ case 'QUERY_STRING':
+ $uri = $this->_parse_query_string();
+ break;
+ case 'PATH_INFO':
+ default:
+ $uri = isset($_SERVER[$protocol])
+ ? $_SERVER[$protocol]
+ : $this->_parse_request_uri();
+ break;
}
- else
- {
- $protocol = $this->config->item('uri_protocol');
- empty($protocol) && $protocol = 'REQUEST_URI';
- switch ($protocol)
- {
- case 'AUTO': // For BC purposes only
- case 'REQUEST_URI':
- $uri = $this->_parse_request_uri();
- break;
- case 'QUERY_STRING':
- $uri = $this->_parse_query_string();
- break;
- case 'PATH_INFO':
- default:
- $uri = isset($_SERVER[$protocol])
- ? $_SERVER[$protocol]
- : $this->_parse_request_uri();
- break;
- }
- }
-
- $this->_set_uri_string($uri);
+ $this->_set_uri_string($uri, FALSE);
}
log_message('info', 'URI Class Initialized');
@@ -146,43 +141,66 @@ class CI_URI {
/**
* Set URI String
*
- * @param string $str
+ * @param string $str Input URI string
+ * @param bool $is_cli Whether the input comes from CLI
* @return void
*/
- protected function _set_uri_string($str)
+ protected function _set_uri_string($str, $is_cli = FALSE)
{
- // Filter out control characters and trim slashes
- $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
-
- if ($this->uri_string !== '')
+ // CLI requests have a bit simpler logic
+ if ($is_cli)
{
- // Remove the URL suffix, if present
- if (($suffix = (string) $this->config->item('url_suffix')) !== '')
+ if (($this->uri_string = trim($str, '/')) === '')
{
- $slen = strlen($suffix);
-
- if (substr($this->uri_string, -$slen) === $suffix)
- {
- $this->uri_string = substr($this->uri_string, 0, -$slen);
- }
+ return;
}
$this->segments[0] = NULL;
- // Populate the segments array
- foreach (explode('/', trim($this->uri_string, '/')) as $val)
+ foreach (explode('/', $this->uri_string) as $segment)
{
- $val = trim($val);
- // Filter segments for security
- $this->filter_uri($val);
-
- if ($val !== '')
+ if (($segment = trim($segment)) !== '')
{
- $this->segments[] = $val;
+ $this->segments[] = $segment;
}
}
unset($this->segments[0]);
+ return;
+ }
+
+ // Filter out control characters and trim slashes
+ $this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
+
+ if ($this->uri_string === '')
+ {
+ return;
}
+
+ // Remove the URL suffix, if present
+ if (($suffix = (string) $this->config->item('url_suffix')) !== '')
+ {
+ $slen = strlen($suffix);
+
+ if (substr($this->uri_string, -$slen) === $suffix)
+ {
+ $this->uri_string = substr($this->uri_string, 0, -$slen);
+ }
+ }
+
+ $this->segments[0] = NULL;
+ foreach (explode('/', trim($this->uri_string, '/')) as $segment)
+ {
+ $segment = trim($segment);
+ // Filter segments for security
+ $this->filter_uri($segment);
+
+ if ($segment !== '')
+ {
+ $this->segments[] = $segment;
+ }
+ }
+
+ unset($this->segments[0]);
}
// --------------------------------------------------------------------
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index 054722340..58cbb1334 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -58,21 +58,21 @@ class CI_Utf8 {
*
* @return void
*/
- public function __construct()
+ public function __construct($charset)
{
if (
- defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8
- && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) // iconv or mbstring must be installed
- && strtoupper(config_item('charset')) === 'UTF-8' // Application charset must be UTF-8
- )
+ defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8
+ && (ICONV_ENABLED === TRUE OR MB_ENABLED === TRUE) // iconv or mbstring must be installed
+ && $charset === 'UTF-8' // Application charset must be UTF-8
+ )
{
define('UTF8_ENABLED', TRUE);
- log_message('debug', 'UTF-8 Support Enabled');
+ log_message('info', 'UTF-8 Support Enabled');
}
else
{
define('UTF8_ENABLED', FALSE);
- log_message('debug', 'UTF-8 Support Disabled');
+ log_message('info', 'UTF-8 Support Disabled');
}
log_message('info', 'Utf8 Class Initialized');
diff --git a/system/core/compat/hash.php b/system/core/compat/hash.php
index 3fe3b85bc..8d03fa922 100644
--- a/system/core/compat/hash.php
+++ b/system/core/compat/hash.php
@@ -63,7 +63,7 @@ if ( ! function_exists('hash_equals'))
/**
* hash_equals()
*
- * @link http://php.net/hash_equals
+ * @link https://secure.php.net/hash_equals
* @param string $known_string
* @param string $user_string
* @return bool
@@ -109,7 +109,7 @@ if ( ! function_exists('hash_pbkdf2'))
/**
* hash_pbkdf2()
*
- * @link http://php.net/hash_pbkdf2
+ * @link https://secure.php.net/hash_pbkdf2
* @param string $algo
* @param string $password
* @param string $salt
@@ -206,8 +206,6 @@ if ( ! function_exists('hash_pbkdf2'))
'ripemd160' => 64,
'ripemd256' => 64,
'ripemd320' => 64,
- 'salsa10' => 64,
- 'salsa20' => 64,
'sha1' => 64,
'sha224' => 64,
'sha256' => 64,
diff --git a/system/core/compat/index.html b/system/core/compat/index.html
index b702fbc39..bcb7cae34 100644
--- a/system/core/compat/index.html
+++ b/system/core/compat/index.html
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
<title>403 Forbidden</title>
</head>
diff --git a/system/core/compat/mbstring.php b/system/core/compat/mbstring.php
index 1c49d189e..7ec598d68 100644
--- a/system/core/compat/mbstring.php
+++ b/system/core/compat/mbstring.php
@@ -66,7 +66,7 @@ if ( ! function_exists('mb_strlen'))
* WARNING: This function WILL fall-back to strlen()
* if iconv is not available!
*
- * @link http://php.net/mb_strlen
+ * @link https://secure.php.net/mb_strlen
* @param string $str
* @param string $encoding
* @return int
@@ -93,7 +93,7 @@ if ( ! function_exists('mb_strpos'))
* WARNING: This function WILL fall-back to strpos()
* if iconv is not available!
*
- * @link http://php.net/mb_strpos
+ * @link https://secure.php.net/mb_strpos
* @param string $haystack
* @param string $needle
* @param int $offset
@@ -122,7 +122,7 @@ if ( ! function_exists('mb_substr'))
* WARNING: This function WILL fall-back to substr()
* if iconv is not available.
*
- * @link http://php.net/mb_substr
+ * @link https://secure.php.net/mb_substr
* @param string $str
* @param int $start
* @param int $length
diff --git a/system/core/compat/password.php b/system/core/compat/password.php
index 9937a47e8..3aae48576 100644
--- a/system/core/compat/password.php
+++ b/system/core/compat/password.php
@@ -68,7 +68,7 @@ if ( ! function_exists('password_get_info'))
/**
* password_get_info()
*
- * @link http://php.net/password_get_info
+ * @link https://secure.php.net/password_get_info
* @param string $hash
* @return array
*/
@@ -87,7 +87,7 @@ if ( ! function_exists('password_hash'))
/**
* password_hash()
*
- * @link http://php.net/password_hash
+ * @link https://secure.php.net/password_hash
* @param string $password
* @param int $algo
* @param array $options
@@ -142,7 +142,7 @@ if ( ! function_exists('password_hash'))
}
// Try not to waste entropy ...
- is_php('5.4') && stream_set_chunk_size($fp, 16);
+ stream_set_chunk_size($fp, 16);
$options['salt'] = '';
for ($read = 0; $read < 16; $read = ($func_overload) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))
@@ -195,7 +195,7 @@ if ( ! function_exists('password_needs_rehash'))
/**
* password_needs_rehash()
*
- * @link http://php.net/password_needs_rehash
+ * @link https://secure.php.net/password_needs_rehash
* @param string $hash
* @param int $algo
* @param array $options
@@ -229,7 +229,7 @@ if ( ! function_exists('password_verify'))
/**
* password_verify()
*
- * @link http://php.net/password_verify
+ * @link https://secure.php.net/password_verify
* @param string $password
* @param string $hash
* @return bool
diff --git a/system/core/compat/standard.php b/system/core/compat/standard.php
index 18b1281ca..a6a1a9cee 100644
--- a/system/core/compat/standard.php
+++ b/system/core/compat/standard.php
@@ -62,7 +62,7 @@ if ( ! function_exists('array_column'))
/**
* array_column()
*
- * @link http://php.net/array_column
+ * @link https://secure.php.net/array_column
* @param array $array
* @param mixed $column_key
* @param mixed $index_key
@@ -133,51 +133,3 @@ if ( ! function_exists('array_column'))
return $result;
}
}
-
-// ------------------------------------------------------------------------
-
-if (is_php('5.4'))
-{
- return;
-}
-
-// ------------------------------------------------------------------------
-
-if ( ! function_exists('hex2bin'))
-{
- /**
- * hex2bin()
- *
- * @link http://php.net/hex2bin
- * @param string $data
- * @return string
- */
- function hex2bin($data)
- {
- if (in_array($type = gettype($data), array('array', 'double', 'object', 'resource'), TRUE))
- {
- if ($type === 'object' && method_exists($data, '__toString'))
- {
- $data = (string) $data;
- }
- else
- {
- trigger_error('hex2bin() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);
- return NULL;
- }
- }
-
- if (strlen($data) % 2 !== 0)
- {
- trigger_error('Hexadecimal input string must have an even length', E_USER_WARNING);
- return FALSE;
- }
- elseif ( ! preg_match('/^[0-9a-f]*$/i', $data))
- {
- trigger_error('Input string must be hexadecimal string', E_USER_WARNING);
- return FALSE;
- }
-
- return pack('H*', $data);
- }
-}
diff --git a/system/core/index.html b/system/core/index.html
index b702fbc39..bcb7cae34 100644
--- a/system/core/index.html
+++ b/system/core/index.html
@@ -1,5 +1,5 @@
<!DOCTYPE html>
-<html>
+<html lang="en">
<head>
<title>403 Forbidden</title>
</head>