summaryrefslogtreecommitdiffstats
path: root/system/core
diff options
context:
space:
mode:
Diffstat (limited to 'system/core')
-rw-r--r--system/core/Benchmark.php10
-rw-r--r--system/core/CodeIgniter.php103
-rw-r--r--system/core/Common.php44
-rw-r--r--system/core/Config.php70
-rw-r--r--system/core/Controller.php10
-rw-r--r--system/core/Exceptions.php13
-rw-r--r--system/core/Hooks.php10
-rw-r--r--system/core/Input.php317
-rw-r--r--system/core/Lang.php10
-rw-r--r--system/core/Loader.php169
-rw-r--r--system/core/Log.php87
-rw-r--r--system/core/Model.php10
-rw-r--r--system/core/Output.php80
-rw-r--r--system/core/Router.php116
-rw-r--r--system/core/Security.php339
-rw-r--r--system/core/URI.php134
-rw-r--r--system/core/Utf8.php24
-rw-r--r--system/core/compat/hash.php14
-rw-r--r--system/core/compat/mbstring.php10
-rw-r--r--system/core/compat/password.php40
-rw-r--r--system/core/compat/standard.php267
21 files changed, 768 insertions, 1109 deletions
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php
index e420f62a1..b3ac79c62 100644
--- a/system/core/Benchmark.php
+++ b/system/core/Benchmark.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -47,7 +47,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/benchmark.html
+ * @link https://codeigniter.com/user_guide/libraries/benchmark.html
*/
class CI_Benchmark {
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index ddf322749..8eed52eb7 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Front-controller
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
*/
/**
@@ -55,7 +55,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @var string
*
*/
- define('CI_VERSION', '3.0.1-dev');
+ const CI_VERSION = '3.2.0-dev';
/*
* ------------------------------------------------------
@@ -67,7 +67,10 @@ defined('BASEPATH') OR exit('No direct script access allowed');
require_once(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
}
- require_once(APPPATH.'config/constants.php');
+ if (file_exists(APPPATH.'config/constants.php'))
+ {
+ require_once(APPPATH.'config/constants.php');
+ }
/*
* ------------------------------------------------------
@@ -76,57 +79,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
@@ -291,14 +243,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);
/*
* ------------------------------------------------------
@@ -329,14 +281,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);
/*
* ------------------------------------------------------
@@ -359,7 +311,7 @@ if ( ! is_php('5.4'))
*
* Returns current CI instance object
*
- * @return object
+ * @return CI_Controller
*/
function &get_instance()
{
@@ -416,14 +368,29 @@ if ( ! is_php('5.4'))
$params = array($method, array_slice($URI->rsegments, 2));
$method = '_remap';
}
- // WARNING: It appears that there are issues with is_callable() even in PHP 5.2!
- // Furthermore, there are bug reports and feature/change requests related to it
- // that make it unreliable to use in this context. Please, DO NOT change this
- // work-around until a better alternative is available.
- elseif ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))
+ elseif ( ! method_exists($class, $method))
{
$e404 = TRUE;
}
+ /**
+ * DO NOT CHANGE THIS, NOTHING ELSE WORKS!
+ *
+ * - method_exists() returns true for non-public methods, which passes the previous elseif
+ * - is_callable() returns false for PHP 4-style constructors, even if there's a __construct()
+ * - method_exists($class, '__construct') won't work because CI_Controller::__construct() is inherited
+ * - People will only complain if this doesn't work, even though it is documented that it shouldn't.
+ *
+ * ReflectionMethod::isConstructor() is the ONLY reliable check,
+ * knowing which method will be executed as a constructor.
+ */
+ elseif ( ! is_callable(array($class, $method)) && strcasecmp($class, $method) === 0)
+ {
+ $reflection = new ReflectionMethod($class, $method);
+ if ( ! $reflection->isPublic() OR $reflection->isConstructor())
+ {
+ $e404 = TRUE;
+ }
+ }
}
if ($e404)
diff --git a/system/core/Common.php b/system/core/Common.php
index ce324a1cc..2712df0e4 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Common Functions
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
*/
// ------------------------------------------------------------------------
@@ -81,8 +81,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
@@ -90,8 +89,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);
}
@@ -355,7 +354,7 @@ if ( ! function_exists('is_https'))
{
return TRUE;
}
- elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')
+ elseif (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && strtolower($_SERVER['HTTP_X_FORWARDED_PROTO']) === 'https')
{
return TRUE;
}
@@ -544,13 +543,18 @@ if ( ! function_exists('set_status_header'))
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'
+ 505 => 'HTTP Version Not Supported',
+ 511 => 'Network Authentication Required',
);
if (isset($stati[$code]))
@@ -598,7 +602,7 @@ if ( ! function_exists('_error_handler'))
*/
function _error_handler($severity, $message, $filepath, $line)
{
- $is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
+ $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.
@@ -656,6 +660,7 @@ if ( ! function_exists('_exception_handler'))
$_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')))
{
@@ -677,7 +682,7 @@ if ( ! function_exists('_shutdown_handler'))
* of CodeIgniter.php. The main reason we use this is to simulate
* a complete custom exception handler.
*
- * E_STRICT is purposivly neglected because such events may have
+ * 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
@@ -716,8 +721,8 @@ if ( ! function_exists('remove_invisible_characters'))
// 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[] = '/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]+/S'; // 00-08, 11, 12, 14-31, 127
@@ -752,7 +757,12 @@ if ( ! function_exists('html_escape'))
if (is_array($var))
{
- return array_map('html_escape', $var, array_fill(0, count($var), $double_encode));
+ foreach (array_keys($var) as $key)
+ {
+ $var[$key] = html_escape($var[$key], $double_encode);
+ }
+
+ return $var;
}
return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);
@@ -816,7 +826,7 @@ if ( ! function_exists('function_usable'))
* 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 commited for 0.9.34 on 2012-02-12,
+ * 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.
*
diff --git a/system/core/Config.php b/system/core/Config.php
index d07000ac9..d7236df1f 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/config.html
+ * @link https://codeigniter.com/user_guide/libraries/config.html
*/
class CI_Config {
@@ -88,11 +88,18 @@ class CI_Config {
// Set the base_url automatically if none was provided
if (empty($this->config['base_url']))
{
- // The regular expression is only a basic validation for a valid "Host" header.
- // It's not exhaustive, only checks for valid characters.
- if (isset($_SERVER['HTTP_HOST']) && preg_match('/^((\[[0-9a-f:]+\])|(\d{1,3}(\.\d{1,3}){3})|[a-z0-9\-\.]+)(:\d+)?$/i', $_SERVER['HTTP_HOST']))
+ if (isset($_SERVER['SERVER_ADDR']))
{
- $base_url = (is_https() ? 'https' : 'http').'://'.$_SERVER['HTTP_HOST']
+ if (strpos($_SERVER['SERVER_ADDR'], ':') !== FALSE)
+ {
+ $server_addr = '['.$_SERVER['SERVER_ADDR'].']';
+ }
+ else
+ {
+ $server_addr = $_SERVER['SERVER_ADDR'];
+ }
+
+ $base_url = (is_https() ? 'https' : 'http').'://'.$server_addr
.substr($_SERVER['SCRIPT_NAME'], 0, strpos($_SERVER['SCRIPT_NAME'], basename($_SERVER['SCRIPT_FILENAME'])));
}
else
@@ -162,7 +169,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);
}
}
@@ -238,7 +245,15 @@ class CI_Config {
if (isset($protocol))
{
- $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
}
if (empty($uri))
@@ -293,10 +308,18 @@ class CI_Config {
if (isset($protocol))
{
- $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ // For protocol-relative links
+ if ($protocol === '')
+ {
+ $base_url = substr($base_url, strpos($base_url, '//'));
+ }
+ else
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
}
- return $base_url.ltrim($this->_uri_string($uri), '/');
+ return $base_url.$this->_uri_string($uri);
}
// -------------------------------------------------------------
@@ -314,11 +337,8 @@ class CI_Config {
{
if ($this->item('enable_query_strings') === FALSE)
{
- if (is_array($uri))
- {
- $uri = implode('/', $uri);
- }
- return trim($uri, '/');
+ is_array($uri) && $uri = implode('/', $uri);
+ return ltrim($uri, '/');
}
elseif (is_array($uri))
{
@@ -331,20 +351,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/Controller.php b/system/core/Controller.php
index a0d97baa2..59a916734 100644
--- a/system/core/Controller.php
+++ b/system/core/Controller.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -47,7 +47,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/general/controllers.html
+ * @link https://codeigniter.com/user_guide/general/controllers.html
*/
class CI_Controller {
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index fc25f57e6..47d153f49 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Exceptions
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/exceptions.html
+ * @link https://codeigniter.com/user_guide/libraries/exceptions.html
*/
class CI_Exceptions {
@@ -187,7 +187,7 @@ class CI_Exceptions {
// --------------------------------------------------------------------
- public function show_exception(Exception $exception)
+ public function show_exception($exception)
{
$templates_path = config_item('error_views_path');
if (empty($templates_path))
@@ -207,7 +207,6 @@ class CI_Exceptions {
}
else
{
- set_status_header(500);
$templates_path .= 'html'.DIRECTORY_SEPARATOR;
}
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 3b4fb2250..f2d6f21ca 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/general/hooks.html
+ * @link https://codeigniter.com/user_guide/general/hooks.html
*/
class CI_Hooks {
diff --git a/system/core/Input.php b/system/core/Input.php
index e1319be8d..70a3c61ee 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Input
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/input.html
+ * @link https://codeigniter.com/user_guide/libraries/input.html
*/
class CI_Input {
@@ -58,45 +58,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
@@ -122,8 +83,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;
// --------------------------------------------------------------------
@@ -135,24 +103,9 @@ class CI_Input {
*
* @return void
*/
- public function __construct()
+ public function __construct(CI_Security &$security)
{
- $this->_allow_get_array = (config_item('allow_get_array') === TRUE);
- $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();
-
+ $this->security = $security;
log_message('info', 'Input Class Initialized');
}
@@ -168,10 +121,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);
@@ -231,7 +182,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);
}
@@ -245,7 +196,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);
}
@@ -259,7 +210,7 @@ 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)
@@ -275,7 +226,7 @@ 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)
@@ -291,7 +242,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);
}
@@ -305,7 +256,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);
}
@@ -321,7 +272,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.
@@ -353,7 +304,7 @@ class CI_Input {
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
* @return void
*/
- public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
+ public function set_cookie($name, $value = '', $expire = 0, $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
{
if (is_array($name))
{
@@ -392,9 +343,9 @@ class CI_Input {
$httponly = config_item('cookie_httponly');
}
- if ( ! is_numeric($expire))
+ if ( ! is_numeric($expire) OR $expire < 0)
{
- $expire = time() - 86500;
+ $expire = 1;
}
else
{
@@ -513,9 +464,9 @@ class CI_Input {
if ($separator === ':')
{
$netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
- for ($i = 0; $i < 8; $i++)
+ for ($j = 0; $j < 8; $j++)
{
- $netaddr[$i] = intval($netaddr[$i], 16);
+ $netaddr[$j] = intval($netaddr[$j], 16);
}
}
else
@@ -575,7 +526,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);
}
@@ -583,173 +534,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) && count($_GET) > 0)
- {
- foreach ($_GET as $key => $val)
- {
- $_GET[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
- }
-
- // Clean $_POST Data
- if (is_array($_POST) && count($_POST) > 0)
- {
- foreach ($_POST as $key => $val)
- {
- $_POST[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
- }
- }
-
- // Clean $_COOKIE Data
- if (is_array($_COOKIE) && count($_COOKIE) > 0)
- {
- // 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']);
-
- // CSRF Protection check
- if ($this->_enable_csrf === TRUE && ! is_cli())
- {
- $this->security->csrf_verify();
- }
-
- 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
@@ -760,30 +544,32 @@ class CI_Input {
// If header is already defined, return it immediately
if ( ! empty($this->headers))
{
- return $this->headers;
+ return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
}
// In Apache, you can simply call apache_request_headers()
if (function_exists('apache_request_headers'))
{
- return $this->headers = apache_request_headers();
+ $this->headers = apache_request_headers();
}
-
- $this->headers['Content-Type'] = isset($_SERVER['CONTENT_TYPE']) ? $_SERVER['CONTENT_TYPE'] : @getenv('CONTENT_TYPE');
-
- foreach ($_SERVER as $key => $val)
+ else
{
- if (sscanf($key, 'HTTP_%s', $header) === 1)
+ isset($_SERVER['CONTENT_TYPE']) && $this->headers['Content-Type'] = $_SERVER['CONTENT_TYPE'];
+
+ foreach ($_SERVER as $key => $val)
{
- // take SOME_HEADER and turn it into Some-Header
- $header = str_replace('_', ' ', strtolower($header));
- $header = str_replace(' ', '-', ucwords($header));
+ if (sscanf($key, 'HTTP_%s', $header) === 1)
+ {
+ // take SOME_HEADER and turn it into Some-Header
+ $header = str_replace('_', ' ', strtolower($header));
+ $header = str_replace(' ', '-', ucwords($header));
- $this->headers[$header] = $this->_fetch_from_array($_SERVER, $key, $xss_clean);
+ $this->headers[$header] = $_SERVER[$key];
+ }
}
}
- return $this->headers;
+ return $this->_fetch_from_array($this->headers, NULL, $xss_clean);
}
// --------------------------------------------------------------------
@@ -803,7 +589,7 @@ class CI_Input {
if ( ! isset($headers))
{
- empty($this->headers) OR $this->request_headers();
+ empty($this->headers) && $this->request_headers();
foreach ($this->headers as $key => $value)
{
$headers[strtolower($key)] = $value;
@@ -839,21 +625,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/Lang.php b/system/core/Lang.php
index deb955414..569b02368 100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Language
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/language.html
+ * @link https://codeigniter.com/user_guide/libraries/language.html
*/
class CI_Lang {
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 5de7a9483..7279e8833 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Loader
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/loader.html
+ * @link https://codeigniter.com/user_guide/libraries/loader.html
*/
class CI_Loader {
@@ -285,13 +285,43 @@ class CI_Loader {
$this->database($db_conn, FALSE, TRUE);
}
+ // Note: All of the code under this condition used to be just:
+ //
+ // load_class('Model', 'core');
+ //
+ // However, load_class() instantiates classes
+ // to cache them for later use and that prevents
+ // MY_Model from being an abstract class and is
+ // sub-optimal otherwise anyway.
if ( ! class_exists('CI_Model', FALSE))
{
- load_class('Model', 'core');
+ $app_path = APPPATH.'core'.DIRECTORY_SEPARATOR;
+ if (file_exists($app_path.'Model.php'))
+ {
+ require_once($app_path.'Model.php');
+ if ( ! class_exists('CI_Model', FALSE))
+ {
+ throw new RuntimeException($app_path."Model.php exists, but doesn't declare class CI_Model");
+ }
+ }
+ elseif ( ! class_exists('CI_Model', FALSE))
+ {
+ require_once(BASEPATH.'core'.DIRECTORY_SEPARATOR.'Model.php');
+ }
+
+ $class = config_item('subclass_prefix').'Model';
+ if (file_exists($app_path.$class.'.php'))
+ {
+ require_once($app_path.$class.'.php');
+ if ( ! class_exists($class, FALSE))
+ {
+ throw new RuntimeException($app_path.$class.".php exists, but doesn't declare class ".$class);
+ }
+ }
}
- $model = ucfirst(strtolower($model));
- if ( ! class_exists($model))
+ $model = ucfirst($model);
+ if ( ! class_exists($model, FALSE))
{
foreach ($this->_ci_model_paths as $mod_path)
{
@@ -456,7 +486,7 @@ class CI_Loader {
*/
public function view($view, $vars = array(), $return = FALSE)
{
- return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_object_to_array($vars), '_ci_return' => $return));
+ return $this->_ci_load(array('_ci_view' => $view, '_ci_vars' => $this->_ci_prepare_view_vars($vars), '_ci_return' => $return));
}
// --------------------------------------------------------------------
@@ -489,19 +519,13 @@ class CI_Loader {
*/
public function vars($vars, $val = '')
{
- if (is_string($vars))
- {
- $vars = array($vars => $val);
- }
-
- $vars = $this->_ci_object_to_array($vars);
+ $vars = is_string($vars)
+ ? array($vars => $val)
+ : $this->_ci_prepare_view_vars($vars);
- if (is_array($vars) && count($vars) > 0)
+ foreach ($vars as $key => $val)
{
- foreach ($vars as $key => $val)
- {
- $this->_ci_cached_vars[$key] = $val;
- }
+ $this->_ci_cached_vars[$key] = $val;
}
return $this;
@@ -561,15 +585,21 @@ class CI_Loader {
*/
public function helper($helpers = array())
{
- foreach ($this->_ci_prep_filename($helpers, '_helper') as $helper)
+ is_array($helpers) OR $helpers = array($helpers);
+ foreach ($helpers as &$helper)
{
+ $filename = basename($helper);
+ $filepath = ($filename === $helper) ? '' : substr($helper, 0, strlen($helper) - strlen($filename));
+ $filename = strtolower(preg_replace('#(_helper)?(\.php)?$#i', '', $filename)).'_helper';
+ $helper = $filepath.$filename;
+
if (isset($this->_ci_helpers[$helper]))
{
continue;
}
// Is this a helper extension request?
- $ext_helper = config_item('subclass_prefix').$helper;
+ $ext_helper = config_item('subclass_prefix').$filename;
$ext_loaded = FALSE;
foreach ($this->_ci_helper_paths as $path)
{
@@ -688,9 +718,16 @@ class CI_Loader {
{
if (is_array($library))
{
- foreach ($library as $driver)
+ foreach ($library as $key => $value)
{
- $this->driver($driver);
+ if (is_int($key))
+ {
+ $this->driver($value, $params);
+ }
+ else
+ {
+ $this->driver($key, $params, $value);
+ }
}
return $this;
@@ -897,13 +934,10 @@ class CI_Loader {
* the two types and cache them so that views that are embedded within
* other views can have access to these variables.
*/
- if (is_array($_ci_vars))
- {
- $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
- }
+ empty($_ci_vars) OR $this->_ci_cached_vars = array_merge($this->_ci_cached_vars, $_ci_vars);
extract($this->_ci_cached_vars);
- /*
+ /**
* Buffer the output
*
* We buffer the output for two reasons:
@@ -916,18 +950,7 @@ 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);
// Return the file data if requested
@@ -1061,7 +1084,7 @@ class CI_Loader {
* @used-by CI_Loader::_ci_load_library()
* @uses CI_Loader::_ci_init_library()
*
- * @param string $library Library name to load
+ * @param string $library_name Library name to load
* @param string $file_path Path to the library filename, relative to libraries/
* @param mixed $params Optional parameters to pass to the class constructor
* @param string $object_name Optional object name to assign to
@@ -1304,10 +1327,7 @@ class CI_Loader {
// Autoload drivers
if (isset($autoload['drivers']))
{
- foreach ($autoload['drivers'] as $item)
- {
- $this->driver($item);
- }
+ $this->driver($autoload['drivers']);
}
// Load libraries
@@ -1334,17 +1354,32 @@ class CI_Loader {
// --------------------------------------------------------------------
/**
- * CI Object to Array translator
+ * Prepare variables for _ci_vars, to be later extract()-ed inside views
*
- * Takes an object as input and converts the class variables to
- * an associative array with key/value pairs.
+ * Converts objects to associative arrays and filters-out internal
+ * variable names (i.e. keys prefixed with '_ci_').
*
- * @param object $object Object data to translate
+ * @param mixed $vars
* @return array
*/
- protected function _ci_object_to_array($object)
+ protected function _ci_prepare_view_vars($vars)
{
- return is_object($object) ? get_object_vars($object) : $object;
+ if ( ! is_array($vars))
+ {
+ $vars = is_object($vars)
+ ? get_object_vars($vars)
+ : array();
+ }
+
+ foreach (array_keys($vars) as $key)
+ {
+ if (strncmp($key, '_ci_', 4) === 0)
+ {
+ unset($vars[$key]);
+ }
+ }
+
+ return $vars;
}
// --------------------------------------------------------------------
@@ -1362,34 +1397,4 @@ class CI_Loader {
$CI =& get_instance();
return $CI->$component;
}
-
- // --------------------------------------------------------------------
-
- /**
- * Prep filename
- *
- * This function prepares filenames of various items to
- * make their loading more reliable.
- *
- * @param string|string[] $filename Filename(s)
- * @param string $extension Filename extension
- * @return array
- */
- protected function _ci_prep_filename($filename, $extension)
- {
- if ( ! is_array($filename))
- {
- return array(strtolower(str_replace(array($extension, '.php'), '', $filename).$extension));
- }
- else
- {
- foreach ($filename as $key => $val)
- {
- $filename[$key] = strtolower(str_replace(array($extension, '.php'), '', $val).$extension);
- }
-
- return $filename;
- }
- }
-
}
diff --git a/system/core/Log.php b/system/core/Log.php
index e8cb401f5..5be7baea8 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Logging
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/general/errors.html
+ * @link https://codeigniter.com/user_guide/general/errors.html
*/
class CI_Log {
@@ -104,6 +104,13 @@ class CI_Log {
*/
protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+ /**
+ * mbstring.func_override flag
+ *
+ * @var bool
+ */
+ protected static $func_override;
+
// --------------------------------------------------------------------
/**
@@ -115,6 +122,8 @@ class CI_Log {
{
$config =& get_config();
+ isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+
$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';
@@ -154,8 +163,8 @@ class CI_Log {
*
* Generally this function will be called using the global log_message() function
*
- * @param string the error level: 'error', 'debug' or 'info'
- * @param string the error message
+ * @param string $level The error level: 'error', 'debug' or 'info'
+ * @param string $msg The error message
* @return bool
*/
public function write_log($level, $msg)
@@ -191,6 +200,8 @@ class CI_Log {
return FALSE;
}
+ flock($fp, LOCK_EX);
+
// Instantiating DateTime with microseconds appended to initial date is needed for proper support of this format
if (strpos($this->_date_fmt, 'u') !== FALSE)
{
@@ -204,13 +215,11 @@ class CI_Log {
$date = date($this->_date_fmt);
}
- $message .= $level.' - '.$date.' --> '.$msg."\n";
-
- flock($fp, LOCK_EX);
+ $message .= $this->_format_line($level, $date, $msg);
- for ($written = 0, $length = strlen($message); $written < $length; $written += $result)
+ for ($written = 0, $length = self::strlen($message); $written < $length; $written += $result)
{
- if (($result = fwrite($fp, substr($message, $written))) === FALSE)
+ if (($result = fwrite($fp, self::substr($message, $written))) === FALSE)
{
break;
}
@@ -227,4 +236,58 @@ class CI_Log {
return is_int($result);
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Format the log line.
+ *
+ * This is for extensibility of log formatting
+ * If you want to change the log format, extend the CI_Log class and override this method
+ *
+ * @param string $level The error level
+ * @param string $date Formatted date string
+ * @param string $message The log message
+ * @return string Formatted log line with a new line character '\n' at the end
+ */
+ protected function _format_line($level, $date, $message)
+ {
+ return $level.' - '.$date.' --> '.$message."\n";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe strlen()
+ *
+ * @param string $str
+ * @return int
+ */
+ protected static function strlen($str)
+ {
+ return (self::$func_override)
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe substr()
+ *
+ * @param string $str
+ * @param int $start
+ * @param int $length
+ * @return string
+ */
+ protected static function substr($str, $start, $length = NULL)
+ {
+ if (self::$func_override)
+ {
+ return mb_substr($str, $start, $length, '8bit');
+ }
+
+ return isset($length)
+ ? substr($str, $start, $length)
+ : substr($str, $start);
+ }
}
diff --git a/system/core/Model.php b/system/core/Model.php
index a0469de11..c809e7b84 100644
--- a/system/core/Model.php
+++ b/system/core/Model.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/config.html
+ * @link https://codeigniter.com/user_guide/libraries/config.html
*/
class CI_Model {
diff --git a/system/core/Output.php b/system/core/Output.php
index 76c1329d2..0887717d9 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Output
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/output.html
+ * @link https://codeigniter.com/user_guide/libraries/output.html
*/
class CI_Output {
@@ -123,6 +123,13 @@ class CI_Output {
public $parse_exec_vars = TRUE;
/**
+ * mbstring.func_override flag
+ *
+ * @var bool
+ */
+ protected static $func_override;
+
+ /**
* Class constructor
*
* Determines whether zLib output compression will be used.
@@ -138,6 +145,8 @@ class CI_Output {
&& extension_loaded('zlib')
);
+ isset(self::$func_override) OR self::$func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+
// Get mime types for later
$this->mimes =& get_mimes();
@@ -285,7 +294,7 @@ class CI_Output {
/**
* Get Header
*
- * @param string $header_name
+ * @param string $header
* @return string
*/
public function get_header($header)
@@ -302,11 +311,12 @@ class CI_Output {
return NULL;
}
- for ($i = 0, $c = count($headers); $i < $c; $i++)
+ // Count backwards, in order to get the last matching header
+ for ($c = count($headers) - 1; $c > -1; $c--)
{
- if (strncasecmp($header, $headers[$i], $l = strlen($header)) === 0)
+ if (strncasecmp($header, $headers[$c], $l = self::strlen($header)) === 0)
{
- return trim(substr($headers[$i], $l+1));
+ return trim(self::substr($headers[$c], $l+1));
}
}
@@ -377,7 +387,7 @@ class CI_Output {
/**
* Set Cache
*
- * @param int $time Cache expiration time in seconds
+ * @param int $time Cache expiration time in minutes
* @return CI_Output
*/
public function cache($time)
@@ -480,19 +490,19 @@ class CI_Output {
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
{
header('Content-Encoding: gzip');
- header('Content-Length: '.strlen($output));
+ header('Content-Length: '.self::strlen($output));
}
else
{
// User agent doesn't support gzip compression,
// so we'll have to decompress our cache
- $output = gzinflate(substr($output, 10, -8));
+ $output = gzinflate(self::substr($output, 10, -8));
}
}
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;
}
@@ -529,7 +539,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);
}
// --------------------------------------------------------------------
@@ -601,9 +611,9 @@ class CI_Output {
$output = $cache_info.'ENDCI--->'.$output;
- for ($written = 0, $length = strlen($output); $written < $length; $written += $result)
+ for ($written = 0, $length = self::strlen($output); $written < $length; $written += $result)
{
- if (($result = fwrite($fp, substr($output, $written))) === FALSE)
+ if (($result = fwrite($fp, self::substr($output, $written))) === FALSE)
{
break;
}
@@ -711,7 +721,7 @@ class CI_Output {
}
// Display the cache
- $this->_display(substr($cache, strlen($match[0])));
+ $this->_display(self::substr($cache, self::strlen($match[0])));
log_message('debug', 'Cache file is current. Sending it to browser.');
return TRUE;
}
@@ -797,4 +807,40 @@ class CI_Output {
}
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe strlen()
+ *
+ * @param string $str
+ * @return int
+ */
+ protected static function strlen($str)
+ {
+ return (self::$func_override)
+ ? mb_strlen($str, '8bit')
+ : strlen($str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Byte-safe substr()
+ *
+ * @param string $str
+ * @param int $start
+ * @param int $length
+ * @return string
+ */
+ protected static function substr($str, $start, $length = NULL)
+ {
+ if (self::$func_override)
+ {
+ return mb_substr($str, $start, $length, '8bit');
+ }
+
+ return isset($length)
+ ? substr($str, $start, $length)
+ : substr($str, $start);
+ }
}
diff --git a/system/core/Router.php b/system/core/Router.php
index 0c793e418..e92a8f540 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Libraries
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/general/routing.html
+ * @link https://codeigniter.com/user_guide/general/routing.html
*/
class CI_Router {
@@ -118,6 +118,7 @@ class CI_Router {
*
* Runs the route mapping function.
*
+ * @param array $routing
* @return void
*/
public function __construct($routing = NULL)
@@ -153,6 +154,28 @@ class CI_Router {
*/
protected function _set_routing()
{
+ // Load the routes.php file. It would be great if we could
+ // skip this for enable_query_strings = TRUE, but then
+ // default_controller would be empty ...
+ if (file_exists(APPPATH.'config/routes.php'))
+ {
+ include(APPPATH.'config/routes.php');
+ }
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
+ }
+
+ // Validate & get reserved routes
+ if (isset($route) && is_array($route))
+ {
+ isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
+ isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
+ unset($route['default_controller'], $route['translate_uri_dashes']);
+ $this->routes = $route;
+ }
+
// Are query strings enabled in the config file? Normally CI doesn't utilize query strings
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
@@ -199,26 +222,6 @@ class CI_Router {
return;
}
- // Load the routes.php file.
- if (file_exists(APPPATH.'config/routes.php'))
- {
- include(APPPATH.'config/routes.php');
- }
-
- if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
- }
-
- // Validate & get reserved routes
- if (isset($route) && is_array($route))
- {
- isset($route['default_controller']) && $this->default_controller = $route['default_controller'];
- isset($route['translate_uri_dashes']) && $this->translate_uri_dashes = $route['translate_uri_dashes'];
- unset($route['default_controller'], $route['translate_uri_dashes']);
- $this->routes = $route;
- }
-
// Is there anything to parse?
if ($this->uri->uri_string !== '')
{
@@ -372,26 +375,6 @@ class CI_Router {
// Get HTTP verb
$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
- // Is there a literal match? If so we're done
- if (isset($this->routes[$uri]))
- {
- // Is it an HTTP verb-based route?
- if (is_array($this->routes[$uri]))
- {
- $route = array_change_key_case($this->routes[$uri], CASE_LOWER);
- if (isset($route[$http_verb]))
- {
- $this->_set_request(explode('/', $route[$http_verb]));
- return;
- }
- }
- else
- {
- $this->_set_request(explode('/', $this->routes[$uri]));
- return;
- }
- }
-
// Loop through the route array looking for wildcards
foreach ($this->routes as $key => $val)
{
@@ -456,19 +439,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
@@ -482,19 +452,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
@@ -512,21 +469,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 7c5199255..4ad550fff 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category Security
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/security.html
+ * @link https://codeigniter.com/user_guide/libraries/security.html
*/
class CI_Security {
@@ -133,15 +133,16 @@ class CI_Security {
* @var array
*/
protected $_never_allowed_str = array(
- 'document.cookie' => '[removed]',
- 'document.write' => '[removed]',
- '.parentNode' => '[removed]',
- '.innerHTML' => '[removed]',
- '-moz-binding' => '[removed]',
- '<!--' => '&lt;!--',
- '-->' => '--&gt;',
- '<![CDATA[' => '&lt;![CDATA[',
- '<comment>' => '&lt;comment&gt;'
+ 'document.cookie' => '[removed]',
+ 'document.write' => '[removed]',
+ '.parentNode' => '[removed]',
+ '.innerHTML' => '[removed]',
+ '-moz-binding' => '[removed]',
+ '<!--' => '&lt;!--',
+ '-->' => '--&gt;',
+ '<![CDATA[' => '&lt;![CDATA[',
+ '<comment>' => '&lt;comment&gt;',
+ '<%' => '&lt;&#37;'
);
/**
@@ -166,10 +167,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)
@@ -188,10 +191,9 @@ class CI_Security {
// Set the CSRF hash
$this->_csrf_set_hash();
+ $this->csrf_verify();
}
- $this->charset = strtoupper(config_item('charset'));
-
log_message('info', 'Security Class Initialized');
}
@@ -223,14 +225,11 @@ class CI_Security {
}
}
- // Do the tokens exist in both the _POST and _COOKIE arrays?
- if ( ! isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
- OR $_POST[$this->_csrf_token_name] !== $_COOKIE[$this->_csrf_cookie_name]) // Do the tokens match?
- {
- $this->csrf_show_error();
- }
+ // Check CSRF token validity, but don't error on mismatch just yet - we'll want to regenerate
+ $valid = isset($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name])
+ && hash_equals($_POST[$this->_csrf_token_name], $_COOKIE[$this->_csrf_cookie_name]);
- // We kill this since we're done and we don't want to polute the _POST array
+ // We kill this since we're done and we don't want to pollute the _POST array
unset($_POST[$this->_csrf_token_name]);
// Regenerate on every submission?
@@ -244,6 +243,11 @@ class CI_Security {
$this->_csrf_set_hash();
$this->csrf_set_cookie();
+ if ($valid !== TRUE)
+ {
+ $this->csrf_show_error();
+ }
+
log_message('info', 'CSRF token verified');
return $this;
}
@@ -371,11 +375,17 @@ class CI_Security {
*
* Note: Use rawurldecode() so it does not remove plus signs
*/
- do
+ if (stripos($str, '%') !== false)
{
- $str = rawurldecode($str);
+ do
+ {
+ $oldstr = $str;
+ $str = rawurldecode($str);
+ $str = preg_replace_callback('#%(?:\s*[0-9a-f]){2,}#i', array($this, '_urldecodespaces'), $str);
+ }
+ while ($oldstr !== $str);
+ unset($oldstr);
}
- while (preg_match('/%[0-9a-f]{2,}/i', $str));
/*
* Convert character entities to ASCII
@@ -436,7 +446,7 @@ class CI_Security {
$words = array(
'javascript', 'expression', 'vbscript', 'jscript', 'wscript',
'vbs', 'script', 'base64', 'applet', 'alert', 'document',
- 'write', 'cookie', 'window', 'confirm', 'prompt'
+ 'write', 'cookie', 'window', 'confirm', 'prompt', 'eval'
);
foreach ($words as $word)
@@ -466,7 +476,7 @@ class CI_Security {
if (preg_match('/<a/i', $str))
{
- $str = preg_replace_callback('#<a[^a-z0-9>]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
+ $str = preg_replace_callback('#<a(?:rea)?[^a-z0-9>]+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
}
if (preg_match('/<img/i', $str))
@@ -480,12 +490,8 @@ class CI_Security {
}
}
while ($original !== $str);
-
unset($original);
- // Remove evil attributes such as style, onclick and xmlns
- $str = $this->_remove_evil_attributes($str, $is_image);
-
/*
* Sanitize naughty HTML elements
*
@@ -495,8 +501,29 @@ class CI_Security {
* So this: <blink>
* Becomes: &lt;blink&gt;
*/
- $naughty = 'alert|prompt|confirm|applet|audio|basefont|base|behavior|bgsound|blink|body|embed|expression|form|frameset|frame|head|html|ilayer|iframe|input|button|select|isindex|layer|link|meta|keygen|object|plaintext|style|script|textarea|title|math|video|svg|xml|xss';
- $str = preg_replace_callback('#<(/*\s*)('.$naughty.')([^><]*)([><]*)#is', array($this, '_sanitize_naughty_html'), $str);
+ $pattern = '#'
+ .'<((?<slash>/*\s*)((?<tagName>[a-z0-9]+)(?=[^a-z0-9]|$)|.+)' // tag start and name, followed by a non-tag character
+ .'[^\s\042\047a-z0-9>/=]*' // a valid attribute character immediately after the tag would count as a separator
+ // optional attributes
+ .'(?<attributes>(?:[\s\042\047/=]*' // non-attribute characters, excluding > (tag close) for obvious reasons
+ .'[^\s\042\047>/=]+' // attribute characters
+ // optional attribute-value
+ .'(?:\s*=' // attribute-value separator
+ .'(?:[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*))' // single, double or non-quoted value
+ .')?' // end optional attribute-value group
+ .')*)' // end optional attributes group
+ .'[^>]*)(?<closeTag>\>)?#isS';
+
+ // Note: It would be nice to optimize this for speed, BUT
+ // only matching the naughty elements here results in
+ // false positives and in turn - vulnerabilities!
+ do
+ {
+ $old_str = $str;
+ $str = preg_replace_callback($pattern, array($this, '_sanitize_naughty_html'), $str);
+ }
+ while ($old_str !== $str);
+ unset($old_str);
/*
* Sanitize naughty scripting elements
@@ -510,9 +537,11 @@ class CI_Security {
* For example: eval('some code')
* Becomes: eval&#40;'some code'&#41;
*/
- $str = preg_replace('#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si',
- '\\1\\2&#40;\\3&#41;',
- $str);
+ $str = preg_replace(
+ '#(alert|prompt|confirm|cmd|passthru|eval|exec|expression|system|fopen|fsockopen|file|file_get_contents|readfile|unlink)(\s*)\((.*?)\)#si',
+ '\\1\\2&#40;\\3&#41;',
+ $str
+ );
// Final clean up
// This adds a bit of extra precaution in case
@@ -574,6 +603,22 @@ class CI_Security {
return FALSE;
}
+ if (function_exists('random_bytes'))
+ {
+ try
+ {
+ // The cast is required to avoid TypeError
+ return random_bytes((int) $length);
+ }
+ catch (Exception $e)
+ {
+ // If random_bytes() can't do the job, we can't either ...
+ // There's no point in using fallbacks.
+ log_message('error', $e->getMessage());
+ return FALSE;
+ }
+ }
+
// Unfortunately, none of the following PRNGs is guaranteed to exist ...
if (defined('MCRYPT_DEV_URANDOM') && ($output = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM)) !== FALSE)
{
@@ -584,7 +629,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)
@@ -629,10 +674,8 @@ class CI_Security {
static $_entities;
- isset($charset) OR $charset = $this->charset;
- $flag = is_php('5.4')
- ? ENT_COMPAT | ENT_HTML5
- : ENT_COMPAT;
+ 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
{
@@ -641,27 +684,6 @@ class CI_Security {
// Decode standard entities, avoiding false positives
if (preg_match_all('/&[a-z]{2,}(?![a-z;])/i', $str, $matches))
{
- if ( ! isset($_entities))
- {
- $_entities = array_map(
- 'strtolower',
- is_php('5.3.4')
- ? get_html_translation_table(HTML_ENTITIES, $flag, $charset)
- : get_html_translation_table(HTML_ENTITIES, $flag)
- );
-
- // 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;';
- }
- }
-
$replace = array();
$matches = array_unique(array_map('strtolower', $matches[0]));
foreach ($matches as &$match)
@@ -672,13 +694,13 @@ class CI_Security {
}
}
- $str = str_ireplace(array_keys($replace), array_values($replace), $str);
+ $str = str_replace(array_keys($replace), array_values($replace), $str);
}
// 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
);
}
@@ -727,7 +749,32 @@ class CI_Security {
*/
public function strip_image_tags($str)
{
- return preg_replace(array('#<img[\s/]+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img[\s/]+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
+ return preg_replace(
+ array(
+ '#<img[\s/]+.*?src\s*=\s*(["\'])([^\\1]+?)\\1.*?\>#i',
+ '#<img[\s/]+.*?src\s*=\s*?(([^\s"\'=<>`]+)).*?\>#i'
+ ),
+ '\\2',
+ $str
+ );
+ }
+
+ // ----------------------------------------------------------------
+
+ /**
+ * URL-decode taking spaces into account
+ *
+ * @see https://github.com/bcit-ci/CodeIgniter/issues/4877
+ * @param array $matches
+ * @return string
+ */
+ protected function _urldecodespaces($matches)
+ {
+ $input = $matches[0];
+ $nospaces = preg_replace('#\s+#', '', $input);
+ return ($nospaces === $input)
+ ? $input
+ : rawurldecode($nospaces);
}
// ----------------------------------------------------------------
@@ -750,71 +797,92 @@ class CI_Security {
// --------------------------------------------------------------------
/**
- * Remove Evil HTML Attributes (like event handlers and style)
- *
- * It removes the evil attribute and either:
- *
- * - Everything up until a space. For example, everything between the pipes:
- *
- * <code>
- * <a |style=document.write('hello');alert('world');| class=link>
- * </code>
- *
- * - Everything inside the quotes. For example, everything between the pipes:
+ * Sanitize Naughty HTML
*
- * <code>
- * <a |style="document.write('hello'); alert('world');"| class="link">
- * </code>
+ * Callback method for xss_clean() to remove naughty HTML elements.
*
- * @param string $str The string to check
- * @param bool $is_image Whether the input is an image
- * @return string The string with the evil attributes removed
+ * @used-by CI_Security::xss_clean()
+ * @param array $matches
+ * @return string
*/
- protected function _remove_evil_attributes($str, $is_image)
+ protected function _sanitize_naughty_html($matches)
{
- $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime');
+ static $naughty_tags = array(
+ 'alert', 'area', 'prompt', 'confirm', 'applet', 'audio', 'basefont', 'base', 'behavior', 'bgsound',
+ 'blink', 'body', 'embed', 'expression', 'form', 'frameset', 'frame', 'head', 'html', 'ilayer',
+ 'iframe', 'input', 'button', 'select', 'isindex', 'layer', 'link', 'meta', 'keygen', 'object',
+ 'plaintext', 'style', 'script', 'textarea', 'title', 'math', 'video', 'svg', 'xml', 'xss'
+ );
- if ($is_image === TRUE)
+ static $evil_attributes = array(
+ 'on\w+', 'style', 'xmlns', 'formaction', 'form', 'xlink:href', 'FSCommand', 'seekSegmentTime'
+ );
+
+ // First, escape unclosed tags
+ if (empty($matches['closeTag']))
+ {
+ return '&lt;'.$matches[1];
+ }
+ // Is the element that we caught naughty? If so, escape it
+ elseif (in_array(strtolower($matches['tagName']), $naughty_tags, TRUE))
{
- /*
- * Adobe Photoshop puts XML metadata into JFIF images,
- * including namespacing, so we have to allow this for images.
- */
- unset($evil_attributes[array_search('xmlns', $evil_attributes)]);
+ return '&lt;'.$matches[1].'&gt;';
}
+ // For other tags, see if their attributes are "evil" and strip those
+ elseif (isset($matches['attributes']))
+ {
+ // We'll store the already fitlered attributes here
+ $attributes = array();
- do {
- $count = $temp_count = 0;
+ // Attribute-catching pattern
+ $attributes_pattern = '#'
+ .'(?<name>[^\s\042\047>/=]+)' // attribute characters
+ // optional attribute-value
+ .'(?:\s*=(?<value>[^\s\042\047=><`]+|\s*\042[^\042]*\042|\s*\047[^\047]*\047|\s*(?U:[^\s\042\047=><`]*)))' // attribute-value separator
+ .'#i';
- // replace occurrences of illegal attribute strings with quotes (042 and 047 are octal quotes)
- $str = preg_replace('/(<[^>]+)(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*(\042|\047)([^\\2]*?)(\\2)/is', '$1[removed]', $str, -1, $temp_count);
- $count += $temp_count;
+ // Blacklist pattern for evil attribute names
+ $is_evil_pattern = '#^('.implode('|', $evil_attributes).')$#i';
- // find occurrences of illegal attribute strings without quotes
- $str = preg_replace('/(<[^>]+)(?<!\w)('.implode('|', $evil_attributes).')\s*=\s*([^\s>]*)/is', '$1[removed]', $str, -1, $temp_count);
- $count += $temp_count;
- }
- while ($count);
+ // Each iteration filters a single attribute
+ do
+ {
+ // Strip any non-alpha characters that may precede an attribute.
+ // Browsers often parse these incorrectly and that has been a
+ // of numerous XSS issues we've had.
+ $matches['attributes'] = preg_replace('#^[^a-z]+#i', '', $matches['attributes']);
- return $str;
- }
+ if ( ! preg_match($attributes_pattern, $matches['attributes'], $attribute, PREG_OFFSET_CAPTURE))
+ {
+ // No (valid) attribute found? Discard everything else inside the tag
+ break;
+ }
- // --------------------------------------------------------------------
+ if (
+ // Is it indeed an "evil" attribute?
+ preg_match($is_evil_pattern, $attribute['name'][0])
+ // Or does it have an equals sign, but no value and not quoted? Strip that too!
+ OR (trim($attribute['value'][0]) === '')
+ )
+ {
+ $attributes[] = 'xss=removed';
+ }
+ else
+ {
+ $attributes[] = $attribute[0][0];
+ }
- /**
- * Sanitize Naughty HTML
- *
- * Callback method for xss_clean() to remove naughty HTML elements.
- *
- * @used-by CI_Security::xss_clean()
- * @param array $matches
- * @return string
- */
- protected function _sanitize_naughty_html($matches)
- {
- return '&lt;'.$matches[1].$matches[2].$matches[3] // encode opening brace
- // encode captured opening or closing brace to prevent recursive vectors:
- .str_replace(array('>', '<'), array('&gt;', '&lt;'), $matches[4]);
+ $matches['attributes'] = substr($matches['attributes'], $attribute[0][1] + strlen($attribute[0][0]));
+ }
+ while ($matches['attributes'] !== '');
+
+ $attributes = empty($attributes)
+ ? ''
+ : ' '.implode(' ', $attributes);
+ return '<'.$matches['slash'].$matches['tagName'].$attributes.'>';
+ }
+
+ return $matches[0];
}
// --------------------------------------------------------------------
@@ -834,12 +902,15 @@ class CI_Security {
*/
protected function _js_link_removal($match)
{
- return str_replace($match[1],
- preg_replace('#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
- '',
- $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
- ),
- $match[0]);
+ return str_replace(
+ $match[1],
+ preg_replace(
+ '#href=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|d\s*a\s*t\s*a\s*:)#si',
+ '',
+ $this->_filter_attributes($match[1])
+ ),
+ $match[0]
+ );
}
// --------------------------------------------------------------------
@@ -859,12 +930,15 @@ class CI_Security {
*/
protected function _js_img_removal($match)
{
- return str_replace($match[1],
- preg_replace('#src=.*?(?:(?:alert|prompt|confirm)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
- '',
- $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
- ),
- $match[0]);
+ return str_replace(
+ $match[1],
+ preg_replace(
+ '#src=.*?(?:(?:alert|prompt|confirm|eval)(?:\(|&\#40;)|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+ '',
+ $this->_filter_attributes($match[1])
+ ),
+ $match[0]
+ );
}
// --------------------------------------------------------------------
@@ -980,5 +1054,4 @@ class CI_Security {
return $this->_csrf_hash;
}
-
}
diff --git a/system/core/URI.php b/system/core/URI.php
index 5b658f679..275c07900 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 1.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category URI
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/uri.html
+ * @link https://codeigniter.com/user_guide/libraries/uri.html
*/
class CI_URI {
@@ -96,45 +96,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');
@@ -145,43 +140,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]);
}
// --------------------------------------------------------------------
@@ -294,7 +312,7 @@ class CI_URI {
*
* Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
*
- * @param string $url
+ * @param string $uri
* @return string
*/
protected function _remove_relative_directory($uri)
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index 9d8ac41e1..1aafbf3a3 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 2.0.0
* @filesource
*/
@@ -46,7 +46,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage Libraries
* @category UTF-8
* @author EllisLab Dev Team
- * @link http://codeigniter.com/user_guide/libraries/utf8.html
+ * @link https://codeigniter.com/user_guide/libraries/utf8.html
*/
class CI_Utf8 {
@@ -57,21 +57,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 15954559c..c0eab4909 100644
--- a/system/core/compat/hash.php
+++ b/system/core/compat/hash.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
* @link http://php.net/hash
*/
@@ -119,7 +119,7 @@ if ( ! function_exists('hash_pbkdf2'))
*/
function hash_pbkdf2($algo, $password, $salt, $iterations, $length = 0, $raw_output = FALSE)
{
- if ( ! in_array($algo, hash_algos(), TRUE))
+ if ( ! in_array(strtolower($algo), hash_algos(), TRUE))
{
trigger_error('hash_pbkdf2(): Unknown hashing algorithm: '.$algo, E_USER_WARNING);
return FALSE;
@@ -203,8 +203,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/mbstring.php b/system/core/compat/mbstring.php
index e335c85f7..f466e1c34 100644
--- a/system/core/compat/mbstring.php
+++ b/system/core/compat/mbstring.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
* @link http://php.net/mbstring
*/
diff --git a/system/core/compat/password.php b/system/core/compat/password.php
index 7b933aa04..84be66738 100644
--- a/system/core/compat/password.php
+++ b/system/core/compat/password.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,13 +44,13 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
* @link http://php.net/password
*/
// ------------------------------------------------------------------------
-if (is_php('5.5') OR ! is_php('5.3.7') OR ! defined('CRYPT_BLOWFISH') OR CRYPT_BLOWFISH !== 1 OR defined('HHVM_VERSION'))
+if (is_php('5.5') OR ! defined('CRYPT_BLOWFISH') OR CRYPT_BLOWFISH !== 1 OR defined('HHVM_VERSION'))
{
return;
}
@@ -116,13 +116,21 @@ if ( ! function_exists('password_hash'))
}
elseif ( ! isset($options['salt']))
{
- if (defined('MCRYPT_DEV_URANDOM'))
+ if (function_exists('random_bytes'))
{
- $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
+ try
+ {
+ $options['salt'] = random_bytes(16);
+ }
+ catch (Exception $e)
+ {
+ log_message('error', 'compat/password: Error while trying to use random_bytes(): '.$e->getMessage());
+ return FALSE;
+ }
}
- elseif (function_exists('openssl_random_pseudo_bytes'))
+ elseif (defined('MCRYPT_DEV_URANDOM'))
{
- $options['salt'] = openssl_random_pseudo_bytes(16);
+ $options['salt'] = mcrypt_create_iv(16, MCRYPT_DEV_URANDOM);
}
elseif (DIRECTORY_SEPARATOR === '/' && (is_readable($dev = '/dev/arandom') OR is_readable($dev = '/dev/urandom')))
{
@@ -133,7 +141,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_override) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))
@@ -148,6 +156,16 @@ if ( ! function_exists('password_hash'))
fclose($fp);
}
+ elseif (function_exists('openssl_random_pseudo_bytes'))
+ {
+ $is_secure = NULL;
+ $options['salt'] = openssl_random_pseudo_bytes(16, $is_secure);
+ if ($is_secure !== TRUE)
+ {
+ log_message('error', 'compat/password: openssl_random_pseudo_bytes() set the $cryto_strong flag to FALSE');
+ return FALSE;
+ }
+ }
else
{
log_message('error', 'compat/password: No CSPRNG available.');
diff --git a/system/core/compat/standard.php b/system/core/compat/standard.php
index 5a428c114..6fd292a26 100644
--- a/system/core/compat/standard.php
+++ b/system/core/compat/standard.php
@@ -6,7 +6,7 @@
*
* This content is released under the MIT License (MIT)
*
- * Copyright (c) 2014 - 2015, British Columbia Institute of Technology
+ * 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
@@ -28,10 +28,10 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2014, EllisLab, Inc. (http://ellislab.com/)
- * @copyright Copyright (c) 2014 - 2015, British Columbia Institute of Technology (http://bcit.ca/)
+ * @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 http://codeigniter.com
+ * @link https://codeigniter.com
* @since Version 3.0.0
* @filesource
*/
@@ -44,7 +44,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
- * @link http://codeigniter.com/user_guide/
+ * @link https://codeigniter.com/user_guide/
*/
// ------------------------------------------------------------------------
@@ -62,7 +62,7 @@ if ( ! function_exists('array_column'))
* array_column()
*
* @link http://php.net/array_column
- * @param string $array
+ * @param array $array
* @param mixed $column_key
* @param mixed $index_key
* @return array
@@ -132,258 +132,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'), 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);
- }
-}
-
-// ------------------------------------------------------------------------
-
-if (is_php('5.3'))
-{
- return;
-}
-
-// ------------------------------------------------------------------------
-
-if ( ! function_exists('array_replace'))
-{
- /**
- * array_replace()
- *
- * @link http://php.net/array_replace
- * @return array
- */
- function array_replace()
- {
- $arrays = func_get_args();
-
- if (($c = count($arrays)) === 0)
- {
- trigger_error('array_replace() expects at least 1 parameter, 0 given', E_USER_WARNING);
- return NULL;
- }
- elseif ($c === 1)
- {
- if ( ! is_array($arrays[0]))
- {
- trigger_error('array_replace(): Argument #1 is not an array', E_USER_WARNING);
- return NULL;
- }
-
- return $arrays[0];
- }
-
- $array = array_shift($arrays);
- $c--;
-
- for ($i = 0; $i < $c; $i++)
- {
- if ( ! is_array($arrays[$i]))
- {
- trigger_error('array_replace(): Argument #'.($i + 2).' is not an array', E_USER_WARNING);
- return NULL;
- }
- elseif (empty($arrays[$i]))
- {
- continue;
- }
-
- foreach (array_keys($arrays[$i]) as $key)
- {
- $array[$key] = $arrays[$i][$key];
- }
- }
-
- return $array;
- }
-}
-
-// ------------------------------------------------------------------------
-
-if ( ! function_exists('array_replace_recursive'))
-{
- /**
- * array_replace_recursive()
- *
- * @link http://php.net/array_replace_recursive
- * @return array
- */
- function array_replace_recursive()
- {
- $arrays = func_get_args();
-
- if (($c = count($arrays)) === 0)
- {
- trigger_error('array_replace_recursive() expects at least 1 parameter, 0 given', E_USER_WARNING);
- return NULL;
- }
- elseif ($c === 1)
- {
- if ( ! is_array($arrays[0]))
- {
- trigger_error('array_replace_recursive(): Argument #1 is not an array', E_USER_WARNING);
- return NULL;
- }
-
- return $arrays[0];
- }
-
- $array = array_shift($arrays);
- $c--;
-
- for ($i = 0; $i < $c; $i++)
- {
- if ( ! is_array($arrays[$i]))
- {
- trigger_error('array_replace_recursive(): Argument #'.($i + 2).' is not an array', E_USER_WARNING);
- return NULL;
- }
- elseif (empty($arrays[$i]))
- {
- continue;
- }
-
- foreach (array_keys($arrays[$i]) as $key)
- {
- $array[$key] = (is_array($arrays[$i][$key]) && isset($array[$key]) && is_array($array[$key]))
- ? array_replace_recursive($array[$key], $arrays[$i][$key])
- : $arrays[$i][$key];
- }
- }
-
- return $array;
- }
-}
-
-// ------------------------------------------------------------------------
-
-if ( ! function_exists('quoted_printable_encode'))
-{
- /**
- * quoted_printable_encode()
- *
- * @link http://php.net/quoted_printable_encode
- * @param string $str
- * @return string
- */
- function quoted_printable_encode($str)
- {
- if (strlen($str) === 0)
- {
- return '';
- }
- elseif (in_array($type = gettype($str), array('array', 'object'), TRUE))
- {
- if ($type === 'object' && method_exists($str, '__toString'))
- {
- $str = (string) $str;
- }
- else
- {
- trigger_error('quoted_printable_encode() expects parameter 1 to be string, '.$type.' given', E_USER_WARNING);
- return NULL;
- }
- }
-
- if (function_exists('imap_8bit'))
- {
- return imap_8bit($str);
- }
-
- $i = $lp = 0;
- $output = '';
- $hex = '0123456789ABCDEF';
- $length = (extension_loaded('mbstring') && ini_get('mbstring.func_overload'))
- ? mb_strlen($str, '8bit')
- : strlen($str);
-
- while ($length--)
- {
- if ((($c = $str[$i++]) === "\015") && isset($str[$i]) && ($str[$i] === "\012") && $length > 0)
- {
- $output .= "\015".$str[$i++];
- $length--;
- $lp = 0;
- continue;
- }
-
- if (
- ctype_cntrl($c)
- OR (ord($c) === 0x7f)
- OR (ord($c) & 0x80)
- OR ($c === '=')
- OR ($c === ' ' && isset($str[$i]) && $str[$i] === "\015")
- )
- {
- if (
- (($lp += 3) > 75 && ord($c) <= 0x7f)
- OR (ord($c) > 0x7f && ord($c) <= 0xdf && ($lp + 3) > 75)
- OR (ord($c) > 0xdf && ord($c) <= 0xef && ($lp + 6) > 75)
- OR (ord($c) > 0xef && ord($c) <= 0xf4 && ($lp + 9) > 75)
- )
- {
- $output .= "=\015\012";
- $lp = 3;
- }
-
- $output .= '='.$hex[ord($c) >> 4].$hex[ord($c) & 0xf];
- continue;
- }
-
- if ((++$lp) > 75)
- {
- $output .= "=\015\012";
- $lp = 1;
- }
-
- $output .= $c;
- }
-
- return $output;
- }
-}