summaryrefslogtreecommitdiffstats
path: root/system/core
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-10-05 23:04:19 +0200
committerAndrey Andreev <narf@devilix.net>2014-10-05 23:04:19 +0200
commit4a485a73d64a8bebc7625aabc5fdc361d5e7dc56 (patch)
treecb18690c4de1c6ca008227260f9dd0cd2b9279d2 /system/core
parent39ec29585b7cdca7edc1a0757c913a13a2ee4f85 (diff)
parentd444d445ed0458a352ecb9ff79ffd158677ee805 (diff)
Merge branch 'develop' into feature/session
Diffstat (limited to 'system/core')
-rw-r--r--system/core/CodeIgniter.php19
-rw-r--r--system/core/Common.php20
-rw-r--r--system/core/Config.php3
-rw-r--r--system/core/Exceptions.php16
-rw-r--r--system/core/Hooks.php2
-rw-r--r--system/core/Input.php4
-rw-r--r--system/core/Log.php30
-rw-r--r--system/core/Output.php2
-rwxr-xr-xsystem/core/Security.php84
-rw-r--r--system/core/compat/password.php17
-rw-r--r--system/core/compat/standard.php (renamed from system/core/compat/array.php)143
11 files changed, 286 insertions, 54 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 1c6e76b4f..5ff788ae3 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -249,7 +249,7 @@ if ( ! is_php('5.4'))
require_once(BASEPATH.'core/compat/mbstring.php');
require_once(BASEPATH.'core/compat/hash.php');
require_once(BASEPATH.'core/compat/password.php');
- require_once(BASEPATH.'core/compat/array.php');
+ require_once(BASEPATH.'core/compat/standard.php');
/*
* ------------------------------------------------------
@@ -449,6 +449,23 @@ if ( ! is_php('5.4'))
/*
* ------------------------------------------------------
+ * Should we use a Composer autoloader?
+ * ------------------------------------------------------
+ */
+ if (($composer_autoload = config_item('composer_autoload')) !== FALSE)
+ {
+ if ($composer_autoload === TRUE && file_exists(APPPATH.'vendor/autoload.php'))
+ {
+ require_once(APPPATH.'vendor/autoload.php');
+ }
+ elseif (file_exists($composer_autoload))
+ {
+ require_once($composer_autoload);
+ }
+ }
+
+/*
+ * ------------------------------------------------------
* Is there a "pre_controller" hook?
* ------------------------------------------------------
*/
diff --git a/system/core/Common.php b/system/core/Common.php
index 752a2e7f1..504e22571 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -289,7 +289,7 @@ if ( ! function_exists('config_item'))
$_config[0] =& get_config();
}
- return isset($_config[0][$item]) ? $_config[0][$item] : FALSE;
+ return isset($_config[0][$item]) ? $_config[0][$item] : NULL;
}
}
@@ -690,16 +690,20 @@ if ( ! function_exists('remove_invisible_characters'))
if ( ! function_exists('html_escape'))
{
/**
- * Returns HTML escaped variable
+ * Returns HTML escaped variable.
*
- * @param mixed
- * @return mixed
+ * @param mixed $var The input string or array of strings to be escaped.
+ * @param bool $double_encode $double_encode set to FALSE prevents escaping twice.
+ * @return mixed The escaped string or array of strings as a result.
*/
- function html_escape($var)
+ function html_escape($var, $double_encode = TRUE)
{
- return is_array($var)
- ? array_map('html_escape', $var)
- : htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
+ if (is_array($var))
+ {
+ return array_map('html_escape', $var, array_fill(0, count($var), $double_encode));
+ }
+
+ return htmlspecialchars($var, ENT_QUOTES, config_item('charset'), $double_encode);
}
}
diff --git a/system/core/Config.php b/system/core/Config.php
index ad0e5f981..db406dfde 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -104,10 +104,11 @@ class CI_Config {
public function load($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
{
$file = ($file === '') ? 'config' : str_replace('.php', '', $file);
- $found = $loaded = FALSE;
+ $loaded = FALSE;
foreach ($this->_config_paths as $path)
{
+ $found = FALSE;
foreach (array(ENVIRONMENT.'/'.$file, $file) as $location)
{
$file_path = $path.'config/'.$location.'.php';
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index cb4bc3cd6..49c2217c9 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -145,9 +145,11 @@ class CI_Exceptions {
*/
public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
- $templates_path = config_item('error_views_path')
- ? config_item('error_views_path')
- : VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ $templates_path = config_item('error_views_path');
+ if (empty($templates_path))
+ {
+ $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ }
if (is_cli())
{
@@ -185,9 +187,11 @@ class CI_Exceptions {
*/
public function show_php_error($severity, $message, $filepath, $line)
{
- $templates_path = config_item('error_views_path')
- ? config_item('error_views_path')
- : VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ $templates_path = config_item('error_views_path');
+ if (empty($templates_path))
+ {
+ $templates_path = VIEWPATH.'errors'.DIRECTORY_SEPARATOR;
+ }
$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index fd1a2ba11..26ced0894 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -127,7 +127,7 @@ class CI_Hooks {
return FALSE;
}
- if (is_array($this->hooks[$which]))
+ if (is_array($this->hooks[$which]) && ! isset($this->hooks[$which]['function']))
{
foreach ($this->hooks[$which] as $val)
{
diff --git a/system/core/Input.php b/system/core/Input.php
index 544b7c08b..9ae2f6d6f 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -353,7 +353,7 @@ class CI_Input {
$path = config_item('cookie_path');
}
- if ($secure === FALSE && config_item('cookie_secure') !== FALSE)
+ if ($secure === FALSE && config_item('cookie_secure') === TRUE)
{
$secure = config_item('cookie_secure');
}
@@ -766,7 +766,7 @@ class CI_Input {
*
* @param string $index Header name
* @param bool $xss_clean Whether to apply XSS filtering
- * @return string|bool The requested header on success or FALSE on failure
+ * @return string|null The requested header on success or NULL on failure
*/
public function get_request_header($index, $xss_clean = FALSE)
{
diff --git a/system/core/Log.php b/system/core/Log.php
index a949c3f39..1dca1bf3b 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -45,32 +45,39 @@ class CI_Log {
protected $_log_path;
/**
+ * File permissions
+ *
+ * @var int
+ */
+ protected $_file_permissions = 0644;
+
+ /**
* Level of logging
*
* @var int
*/
- protected $_threshold = 1;
+ protected $_threshold = 1;
/**
* Highest level of logging
*
* @var int
*/
- protected $_threshold_max = 0;
+ protected $_threshold_max = 0;
/**
* Array of threshold levels to log
*
* @var array
*/
- protected $_threshold_array = array();
+ protected $_threshold_array = array();
/**
* Format of timestamp for log files
*
* @var string
*/
- protected $_date_fmt = 'Y-m-d H:i:s';
+ protected $_date_fmt = 'Y-m-d H:i:s';
/**
* Filename extension
@@ -84,14 +91,14 @@ class CI_Log {
*
* @var bool
*/
- protected $_enabled = TRUE;
+ protected $_enabled = TRUE;
/**
* Predefined logging levels
*
* @var array
*/
- protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+ protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
// --------------------------------------------------------------------
@@ -108,7 +115,7 @@ class CI_Log {
$this->_file_ext = (isset($config['log_file_extension']) && $config['log_file_extension'] !== '')
? ltrim($config['log_file_extension'], '.') : 'php';
- file_exists($this->_log_path) OR mkdir($this->_log_path, 0777, TRUE);
+ file_exists($this->_log_path) OR mkdir($this->_log_path, 0755, TRUE);
if ( ! is_dir($this->_log_path) OR ! is_really_writable($this->_log_path))
{
@@ -125,10 +132,15 @@ class CI_Log {
$this->_threshold_array = array_flip($config['log_threshold']);
}
- if ($config['log_date_format'] !== '')
+ if ( ! empty($config['log_date_format']))
{
$this->_date_fmt = $config['log_date_format'];
}
+
+ if ( ! empty($config['log_file_permissions']) && is_int($config['log_file_permissions']))
+ {
+ $this->_file_permissions = $config['log_file_permissions'];
+ }
}
// --------------------------------------------------------------------
@@ -192,7 +204,7 @@ class CI_Log {
if (isset($newfile) && $newfile === TRUE)
{
- @chmod($filepath, 0666);
+ chmod($filepath, $this->_file_permissions);
}
return is_int($result);
diff --git a/system/core/Output.php b/system/core/Output.php
index 238d223e2..de07125ad 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -606,7 +606,7 @@ class CI_Output {
if (is_int($result))
{
- @chmod($cache_path, 0666);
+ chmod($cache_path, 0640);
log_message('debug', 'Cache file written: '.$cache_path);
// Send HTTP cache-control headers to browser to match file cache settings.
diff --git a/system/core/Security.php b/system/core/Security.php
index 2cf214b18..cffdb9ad9 100755
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -77,7 +77,7 @@ class CI_Security {
*
* @var string
*/
- protected $_xss_hash = '';
+ protected $_xss_hash;
/**
* CSRF Hash
@@ -86,7 +86,7 @@ class CI_Security {
*
* @var string
*/
- protected $_csrf_hash = '';
+ protected $_csrf_hash;
/**
* CSRF Expire time
@@ -158,7 +158,7 @@ class CI_Security {
public function __construct()
{
// Is CSRF protection enabled?
- if (config_item('csrf_protection') === TRUE)
+ if (config_item('csrf_protection'))
{
// CSRF config
foreach (array('csrf_expire', 'csrf_token_name', 'csrf_cookie_name') as $key)
@@ -170,9 +170,9 @@ class CI_Security {
}
// Append application specific cookie prefix
- if (config_item('cookie_prefix'))
+ if ($cookie_prefix = config_item('cookie_prefix'))
{
- $this->_csrf_cookie_name = config_item('cookie_prefix').$this->_csrf_cookie_name;
+ $this->_csrf_cookie_name = $cookie_prefix.$this->_csrf_cookie_name;
}
// Set the CSRF hash
@@ -203,9 +203,12 @@ class CI_Security {
if ($exclude_uris = config_item('csrf_exclude_uris'))
{
$uri = load_class('URI', 'core');
- if (in_array($uri->uri_string(), $exclude_uris))
+ foreach ($exclude_uris as $excluded)
{
- return $this;
+ if (preg_match('#^'.$excluded.'$#i'.(UTF8_ENABLED ? 'u' : ''), $uri->uri_string()))
+ {
+ return $this;
+ }
}
}
@@ -224,7 +227,7 @@ class CI_Security {
{
// Nothing should last forever
unset($_COOKIE[$this->_csrf_cookie_name]);
- $this->_csrf_hash = '';
+ $this->_csrf_hash = NULL;
}
$this->_csrf_set_hash();
@@ -275,7 +278,7 @@ class CI_Security {
*/
public function csrf_show_error()
{
- show_error('The action you have requested is not allowed.');
+ show_error('The action you have requested is not allowed.', 403);
}
// --------------------------------------------------------------------
@@ -370,7 +373,7 @@ class CI_Security {
* We only convert entities that are within tags since
* these are the ones that will pose security problems.
*/
- $str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
+ $str = preg_replace_callback("/[^a-z0-9>]+[a-z0-9]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
$str = preg_replace_callback('/<\w+.*/si', array($this, '_decode_entity'), $str);
// Remove Invisible Characters Again!
@@ -436,7 +439,7 @@ class CI_Security {
/*
* Remove disallowed Javascript in links or img tags
- * We used to do some version comparisons and use of stripos for PHP5,
+ * We used to do some version comparisons and use of stripos(),
* but it is dog slow compared to these simplified non-capturing
* preg_match(), especially if the pattern exists in the string
*
@@ -535,9 +538,12 @@ class CI_Security {
*/
public function xss_hash()
{
- if ($this->_xss_hash === '')
+ if ($this->_xss_hash === NULL)
{
- $this->_xss_hash = md5(uniqid(mt_rand()));
+ $rand = $this->get_random_bytes(16);
+ $this->_xss_hash = ($rand === FALSE)
+ ? md5(uniqid(mt_rand(), TRUE))
+ : bin2hex($rand);
}
return $this->_xss_hash;
@@ -546,6 +552,48 @@ class CI_Security {
// --------------------------------------------------------------------
/**
+ * Get random bytes
+ *
+ * @param int $length Output length
+ * @return string
+ */
+ public function get_random_bytes($length)
+ {
+ if (empty($length) OR ! ctype_digit((string) $length))
+ {
+ 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)
+ {
+ return $output;
+ }
+
+
+ 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);
+ $output = fread($fp, $length);
+ fclose($fp);
+ if ($output !== FALSE)
+ {
+ return $output;
+ }
+ }
+
+ if (function_exists('openssl_random_pseudo_bytes'))
+ {
+ return openssl_random_pseudo_bytes($length);
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* HTML Entities Decode
*
* A replacement for html_entity_decode()
@@ -605,7 +653,7 @@ class CI_Security {
{
if (($char = array_search($matches[$i].';', $_entities, TRUE)) !== FALSE)
{
- $replace[$matches[$i]] = $character;
+ $replace[$matches[$i]] = $char;
}
}
@@ -912,7 +960,7 @@ class CI_Security {
*/
protected function _csrf_set_hash()
{
- if ($this->_csrf_hash === '')
+ if ($this->_csrf_hash === NULL)
{
// If the cookie exists we will use its value.
// We don't necessarily want to regenerate it with
@@ -924,8 +972,10 @@ class CI_Security {
return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
}
- $this->_csrf_hash = md5(uniqid(mt_rand(), TRUE));
- $this->csrf_set_cookie();
+ $rand = $this->get_random_bytes(16);
+ $this->_csrf_hash = ($rand === FALSE)
+ ? md5(uniqid(mt_rand(), TRUE))
+ : bin2hex($rand);
}
return $this->_csrf_hash;
diff --git a/system/core/compat/password.php b/system/core/compat/password.php
index a9355d5d0..1f67a5269 100644
--- a/system/core/compat/password.php
+++ b/system/core/compat/password.php
@@ -83,6 +83,9 @@ if ( ! function_exists('password_hash'))
*/
function password_hash($password, $algo, array $options = array())
{
+ static $func_override;
+ isset($func_override) OR $func_override = (extension_loaded('mbstring') && ini_get('mbstring.func_override'));
+
if ($algo !== 1)
{
trigger_error('password_hash(): Unknown hashing algorithm: '.(int) $algo, E_USER_WARNING);
@@ -95,9 +98,9 @@ if ( ! function_exists('password_hash'))
return NULL;
}
- if (isset($options['salt']) && strlen($options['salt']) < 22)
+ if (isset($options['salt']) && ($saltlen = ($func_override ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))) < 22)
{
- trigger_error('password_hash(): Provided salt is too short: '.strlen($options['salt']).' expecting 22', E_USER_WARNING);
+ trigger_error('password_hash(): Provided salt is too short: '.$saltlen.' expecting 22', E_USER_WARNING);
return NULL;
}
elseif ( ! isset($options['salt']))
@@ -118,8 +121,11 @@ if ( ! function_exists('password_hash'))
return FALSE;
}
+ // Try not to waste entropy ...
+ is_php('5.4') && stream_set_chunk_size($fp, 16);
+
$options['salt'] = '';
- for ($read = 0; $read < 16; $read = strlen($options['salt']))
+ for ($read = 0; $read < 16; $read = ($func_override) ? mb_strlen($options['salt'], '8bit') : strlen($options['salt']))
{
if (($read = fread($fp, 16 - $read)) === FALSE)
{
@@ -145,7 +151,10 @@ if ( ! function_exists('password_hash'))
}
isset($options['cost']) OR $options['cost'] = 10;
- return crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']));
+
+ return (strlen($password = crypt($password, sprintf('$2y$%02d$%s', $options['cost'], $options['salt']))) === 60)
+ ? $password
+ : FALSE;
}
}
diff --git a/system/core/compat/array.php b/system/core/compat/standard.php
index 07dae21c2..afe9e9852 100644
--- a/system/core/compat/array.php
+++ b/system/core/compat/standard.php
@@ -27,14 +27,13 @@
defined('BASEPATH') OR exit('No direct script access allowed');
/**
- * PHP ext/standard/array compatibility package
+ * PHP ext/standard compatibility package
*
* @package CodeIgniter
* @subpackage CodeIgniter
* @category Compatibility
* @author Andrey Andreev
* @link http://codeigniter.com/user_guide/
- * @link http://php.net/book.array
*/
// ------------------------------------------------------------------------
@@ -125,6 +124,54 @@ if ( ! function_exists('array_column'))
// ------------------------------------------------------------------------
+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;
@@ -242,5 +289,93 @@ if ( ! function_exists('array_replace_recursive'))
}
}
-/* End of file array.php */
-/* Location: ./system/core/compat/array.php */ \ No newline at end of file
+// ------------------------------------------------------------------------
+
+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;
+ }
+}
+
+/* End of file standard.php */
+/* Location: ./system/core/compat/standard.php */ \ No newline at end of file