summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
Diffstat (limited to 'system')
-rw-r--r--system/core/Input.php48
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php2
-rw-r--r--system/helpers/url_helper.php21
-rw-r--r--system/libraries/Email.php199
-rwxr-xr-xsystem/libraries/Session/drivers/Session_cookie.php49
-rwxr-xr-xsystem/libraries/Session/drivers/Session_native.php22
6 files changed, 168 insertions, 173 deletions
diff --git a/system/core/Input.php b/system/core/Input.php
index 82482f2aa..ec935d531 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -390,31 +390,32 @@ class CI_Input {
}
// Convert the REMOTE_ADDR IP address to binary, if needed
- if ( ! isset($ip, $convert_func))
+ if ( ! isset($ip, $sprintf))
{
if ($separator === ':')
{
// Make sure we're have the "full" IPv6 format
- $ip = str_replace('::', str_repeat(':', 9 - substr_count($this->ip_address, ':')), $this->ip_address);
- $convert_func = is_php('5.3')
- ? function ($value)
- {
- return str_pad(base_convert($value, 16, 2), 16, '0', STR_PAD_LEFT);
- }
- : create_function('$value', 'return str_pad(base_convert($value, 16, 2), 16, "0", STR_PAD_LEFT);');
+ $ip = explode(':',
+ str_replace('::',
+ str_repeat(':', 9 - substr_count($this->ip_address, ':')),
+ $this->ip_address
+ )
+ );
+
+ for ($i = 0; $i < 8; $i++)
+ {
+ $ip[$i] = intval($ip[$i], 16);
+ }
+
+ $sprintf = '%016b%016b%016b%016b%016b%016b%016b%016b';
}
else
{
- $ip = $this->ip_address;
- $convert_func = is_php('5.3')
- ? function ($value)
- {
- return str_pad(decbin($value), 8, '0', STR_PAD_LEFT);
- }
- : create_function('$value', 'return str_pad(decbin($value), 8, "0", STR_PAD_LEFT);');
+ $ip = explode('.', $this->ip_address);
+ $sprintf = '%08b%08b%08b%08b';
}
- $ip = implode(array_map($convert_func, explode($separator, $ip)));
+ $ip = vsprintf($sprintf, $ip);
}
// Split the netmask length off the network address
@@ -423,12 +424,19 @@ class CI_Input {
// Again, an IPv6 address is most likely in a compressed form
if ($separator === ':')
{
- $netaddr = str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr);
+ $netaddr = explode(':', str_replace('::', str_repeat(':', 9 - substr_count($netaddr, ':')), $netaddr));
+ for ($i = 0; $i < 8; $i++)
+ {
+ $netaddr[$i] = intval($netaddr[$i], 16);
+ }
+ }
+ else
+ {
+ $netaddr = explode('.', $netaddr);
}
- // Convert to a binary form and finally compare
- $netaddr = implode(array_map($convert_func, explode($separator, $netaddr)));
- if (strncmp($ip, $netaddr, $masklen) === 0)
+ // Convert to binary and finally compare
+ if (strncmp($ip, vsprintf($sprintf, $netaddr), $masklen) === 0)
{
$this->ip_address = $spoof;
break;
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index f77176c16..dc72ecc5f 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -69,7 +69,7 @@ class CI_DB_mysqli_driver extends CI_DB {
? 'p:'.$this->hostname : $this->hostname;
$port = empty($this->port) ? NULL : $this->port;
$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
- $mysqli = new mysqli();
+ $mysqli = mysqli_init();
return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags)
? $mysqli : FALSE;
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index b1f5eccf1..de5bdec31 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -388,40 +388,43 @@ if ( ! function_exists('auto_link'))
for ($i = 0, $c = count($matches[0]); $i < $c; $i++)
{
- if (preg_match('|\.$|', $matches[6][$i]))
+ if (preg_match('/(\.|\,)$/i', $matches[6][$i], $m))
{
- $period = '.';
+ $punct = $m[1];
$matches[6][$i] = substr($matches[6][$i], 0, -1);
}
else
{
- $period = '';
+ $punct = '';
}
$str = str_replace($matches[0][$i],
$matches[1][$i].'<a href="http'.$matches[4][$i].'://'
.$matches[5][$i].$matches[6][$i].'"'.$pop.'>http'
.$matches[4][$i].'://'.$matches[5][$i]
- .$matches[6][$i].'</a>'.$period,
+ .$matches[6][$i].'</a>'.$punct,
$str);
}
}
- if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]*)/i', $str, $matches))
+ if ($type !== 'url' && preg_match_all('/([a-zA-Z0-9_\.\-\+]+)@([a-zA-Z0-9\-]+)\.([a-zA-Z0-9\-\.]+)/i', $str, $matches))
{
for ($i = 0, $c = count($matches); $i < $c; $i++)
{
- if (preg_match('|\.$|', $matches[3][$i]))
+ if (preg_match('/(\.|\,)$/i', $matches[3][$i], $m))
{
- $period = '.';
+ $punct = $m[1];
$matches[3][$i] = substr($matches[3][$i], 0, -1);
}
else
{
- $period = '';
+ $punct = '';
}
- $str = str_replace($matches[0][$i], safe_mailto($matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]).$period, $str);
+ if (filter_var(($m = $matches[1][$i].'@'.$matches[2][$i].'.'.$matches[3][$i]), FILTER_VALIDATE_EMAIL) !== FALSE)
+ {
+ $str = str_replace($matches[0][$i], safe_mailto($m).$punct, $str);
+ }
}
}
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index fa1d5e9bf..c1130e915 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -98,7 +98,7 @@ class CI_Email {
*/
public function __construct($config = array())
{
- $this->charset = strtoupper(config_item('charset'));
+ $this->charset = config_item('charset');
if (count($config) > 0)
{
@@ -110,6 +110,8 @@ class CI_Email {
$this->_safe_mode = (bool) @ini_get('safe_mode');
}
+ $this->charset = strtoupper($this->charset);
+
log_message('debug', 'Email Class Initialized');
}
@@ -186,11 +188,11 @@ class CI_Email {
/**
* Set FROM
*
- * @param string
- * @param string
+ * @param string From
+ * @param string Return-Path
* @return object
*/
- public function from($from, $name = '', $return_path = '')
+ public function from($from, $name = '', $return_path = NULL)
{
if (preg_match('/\<(.*)\>/', $from, $match))
{
@@ -217,16 +219,13 @@ class CI_Email {
}
else
{
- $name = $this->_prep_q_encoding($name, TRUE);
+ $name = $this->_prep_q_encoding($name);
}
}
$this->set_header('From', $name.' <'.$from.'>');
- if( ! $return_path)
- {
- $return_path = $from;
- }
+ isset($return_path) OR $return_path = $from;
$this->set_header('Return-Path', '<'.$return_path.'>');
return $this;
@@ -292,16 +291,7 @@ class CI_Email {
$this->set_header('To', implode(', ', $to));
}
- switch ($this->_get_protocol())
- {
- case 'smtp':
- $this->_recipients = $to;
- break;
- case 'sendmail':
- case 'mail':
- $this->_recipients = implode(', ', $to);
- break;
- }
+ $this->_recipients = $to;
return $this;
}
@@ -752,8 +742,8 @@ class CI_Email {
/**
* Build alternative plain text message
*
- * This public function provides the raw message for use
- * in plain-text headers of HTML-formatted emails.
+ * Provides the raw message for use in plain-text headers of
+ * HTML-formatted emails.
* If the user hasn't specified his own alternative message
* it creates one by stripping the HTML
*
@@ -761,9 +751,11 @@ class CI_Email {
*/
protected function _get_alt_message()
{
- if ($this->alt_message !== '')
+ if ( ! empty($this->alt_message))
{
- return $this->word_wrap($this->alt_message, '76');
+ return ($this->wordwrap)
+ ? $this->word_wrap($this->alt_message, 76)
+ : $this->alt_message;
}
$body = preg_match('/\<body.*?\>(.*)\<\/body\>/si', $this->_body, $match) ? $match[1] : $this->_body;
@@ -774,7 +766,9 @@ class CI_Email {
$body = str_replace(str_repeat("\n", $i), "\n\n", $body);
}
- return $this->word_wrap($body, 76);
+ return ($this->wordwrap)
+ ? $this->word_wrap($body, 76)
+ : $body;
}
// --------------------------------------------------------------------
@@ -783,15 +777,15 @@ class CI_Email {
* Word Wrap
*
* @param string
- * @param int
+ * @param int line-length limit
* @return string
*/
- public function word_wrap($str, $charlim = '')
+ public function word_wrap($str, $charlim = NULL)
{
- // Se the character limit
- if ($charlim === '')
+ // Set the character limit, if not already present
+ if (empty($charlim))
{
- $charlim = ($this->wrapchars === '') ? 76 : $this->wrapchars;
+ $charlim = empty($this->wrapchars) ? 76 : $this->wrapchars;
}
// Reduce multiple spaces
@@ -1105,6 +1099,10 @@ class CI_Email {
*/
protected function _prep_quoted_printable($str)
{
+ // We are intentionally wrapping so mail servers will encode characters
+ // properly and MUAs will behave, so {unwrap} must go!
+ $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
+
// RFC 2045 specifies CRLF as "\r\n".
// However, many developers choose to override that and violate
// the RFC rules due to (apparently) a bug in MS Exchange,
@@ -1130,10 +1128,6 @@ class CI_Email {
$str = str_replace(array("\r\n", "\r"), "\n", $str);
}
- // We are intentionally wrapping so mail servers will encode characters
- // properly and MUAs will behave, so {unwrap} must go!
- $str = str_replace(array('{unwrap}', '{/unwrap}'), '', $str);
-
$escape = '=';
$output = '';
@@ -1186,66 +1180,75 @@ class CI_Email {
/**
* Prep Q Encoding
*
- * Performs "Q Encoding" on a string for use in email headers. It's related
- * but not identical to quoted-printable, so it has its own method
+ * Performs "Q Encoding" on a string for use in email headers.
+ * It's related but not identical to quoted-printable, so it has its
+ * own method.
*
* @param string
- * @param bool set to TRUE for processing From: headers
* @return string
*/
- protected function _prep_q_encoding($str, $from = FALSE)
+ protected function _prep_q_encoding($str)
{
- $str = str_replace(array("\r", "\n"), array('', ''), $str);
-
- // Line length must not exceed 76 characters, so we adjust for
- // a space, 7 extra characters =??Q??=, and the charset that we will add to each line
- $limit = 75 - 7 - strlen($this->charset);
-
- // these special characters must be converted too
- $convert = array('_', '=', '?');
+ $str = str_replace(array("\r", "\n"), '', $str);
- if ($from === TRUE)
+ if ($this->charset === 'UTF-8')
{
- $convert[] = ',';
- $convert[] = ';';
+ if (MB_ENABLED === TRUE)
+ {
+ return mb_encode_mimeheader($str, $this->charset, 'Q', $this->crlf);
+ }
+ elseif (extension_loaded('iconv'))
+ {
+ $output = @iconv_mime_encode('', $str,
+ array(
+ 'scheme' => 'Q',
+ 'line-length' => 76,
+ 'input-charset' => $this->charset,
+ 'output-charset' => $this->charset,
+ 'line-break-chars' => $this->crlf
+ )
+ );
+
+ // There are reports that iconv_mime_encode() might fail and return FALSE
+ if ($output !== FALSE)
+ {
+ // iconv_mime_encode() will always put a header field name.
+ // We've passed it an empty one, but it still prepends our
+ // encoded string with ': ', so we need to strip it.
+ return substr($output, 2);
+ }
+
+ $chars = iconv_strlen($str, 'UTF-8');
+ }
}
- $output = '';
- $temp = '';
+ // We might already have this set for UTF-8
+ isset($chars) OR $chars = strlen($str);
- for ($i = 0, $length = strlen($str); $i < $length; $i++)
+ $output = '=?'.$this->charset.'?Q?';
+ for ($i = 0, $length = strlen($output), $iconv = extension_loaded('iconv'); $i < $chars; $i++)
{
- // Grab the next character
- $char = $str[$i];
- $ascii = ord($char);
-
- // convert ALL non-printable ASCII characters and our specials
- if ($ascii < 32 OR $ascii > 126 OR in_array($char, $convert))
- {
- $char = '='.dechex($ascii);
- }
+ $chr = ($this->charset === 'UTF-8' && $iconv === TRUE)
+ ? '='.implode('=', str_split(strtoupper(bin2hex(iconv_substr($str, $i, 1, $this->charset))), 2))
+ : '='.strtoupper(bin2hex($str[$i]));
- // handle regular spaces a bit more compactly than =20
- if ($ascii === 32)
+ // RFC 2045 sets a limit of 76 characters per line.
+ // We'll append ?= to the end of each line though.
+ if ($length + ($l = strlen($chr)) > 74)
{
- $char = '_';
+ $output .= '?='.$this->crlf // EOL
+ .' =?'.$this->charset.'?Q?'.$chr; // New line
+ $length = 6 + strlen($this->charset) + $l; // Reset the length for the new line
}
-
- // If we're at the character limit, add the line to the output,
- // reset our temp variable, and keep on chuggin'
- if ((strlen($temp) + strlen($char)) >= $limit)
+ else
{
- $output .= $temp.$this->crlf;
- $temp = '';
+ $output .= $chr;
+ $length += $l;
}
-
- // Add the character to our temporary line
- $temp .= $char;
}
- // wrap each line with the shebang, charset, and transfer encoding
- // the preceding space on successive lines is required for header "folding"
- return trim(preg_replace('/^(.*?)(\r*)$/m', ' =?'.$this->charset.'?Q?$1?=$2', $output.$temp));
+ // End the header
+ return $output.'?=';
}
// --------------------------------------------------------------------
@@ -1408,6 +1411,11 @@ class CI_Email {
*/
protected function _send_with_mail()
{
+ if (is_array($this->_recipients))
+ {
+ $this->_recipients = implode(', ', $this->_recipients);
+ }
+
if ($this->_safe_mode === TRUE)
{
return mail($this->_recipients, $this->_subject, $this->_finalbody, $this->_header_str);
@@ -1754,47 +1762,6 @@ class CI_Email {
// --------------------------------------------------------------------
/**
- * Get IP
- *
- * @return string
- */
- protected function _get_ip()
- {
- if ($this->_IP !== FALSE)
- {
- return $this->_IP;
- }
-
- $cip = ( ! empty($_SERVER['HTTP_CLIENT_IP'])) ? $_SERVER['HTTP_CLIENT_IP'] : FALSE;
- $rip = ( ! empty($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : FALSE;
- if ($cip) $this->_IP = $cip;
- elseif ($rip) $this->_IP = $rip;
- else
- {
- $fip = ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : FALSE;
- if ($fip)
- {
- $this->_IP = $fip;
- }
- }
-
- if (strpos($this->_IP, ',') !== FALSE)
- {
- $x = explode(',', $this->_IP);
- $this->_IP = end($x);
- }
-
- if ( ! preg_match('/^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/', $this->_IP))
- {
- $this->_IP = '0.0.0.0';
- }
-
- return $this->_IP;
- }
-
- // --------------------------------------------------------------------
-
- /**
* Get Debug Message
*
* @return string
diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php
index fb62c7ec4..8617aec2d 100755
--- a/system/libraries/Session/drivers/Session_cookie.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -308,7 +308,7 @@ class CI_Session_cookie extends CI_Session_driver {
}
// Kill the cookie
- $this->_setcookie($this->sess_cookie_name, addslashes(serialize(array())), ($this->now - 31500000),
+ $this->_setcookie($this->sess_cookie_name, '', ($this->now - 31500000),
$this->cookie_path, $this->cookie_domain, 0);
// Kill session data
@@ -372,27 +372,31 @@ class CI_Session_cookie extends CI_Session_driver {
return FALSE;
}
+ $len = strlen($session) - 40;
+
+ if ($len < 0)
+ {
+ log_message('debug', 'The session cookie was not signed.');
+ return FALSE;
+ }
+
+ // Check cookie authentication
+ $hmac = substr($session, $len);
+ $session = substr($session, 0, $len);
+
+ if ($hmac !== hash_hmac('sha1', $session, $this->encryption_key))
+ {
+ log_message('error', 'The session cookie data did not match what was expected.');
+ $this->sess_destroy();
+ return FALSE;
+ }
+
// Check for encryption
if ($this->sess_encrypt_cookie === TRUE)
{
// Decrypt the cookie data
$session = $this->CI->encrypt->decode($session);
}
- else
- {
- // Encryption was not used, so we need to check the md5 hash in the last 32 chars
- $len = strlen($session)-32;
- $hash = substr($session, $len);
- $session = substr($session, 0, $len);
-
- // Does the md5 hash match? This is to prevent manipulation of session data in userspace
- if ($hash !== md5($session.$this->encryption_key))
- {
- log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.');
- $this->sess_destroy();
- return FALSE;
- }
- }
// Unserialize the session array
$session = $this->_unserialize($session);
@@ -405,7 +409,7 @@ class CI_Session_cookie extends CI_Session_driver {
}
// Is the session current?
- if (($session['last_activity'] + $this->sess_expiration) < $this->now)
+ if (($session['last_activity'] + $this->sess_expiration) < $this->now OR $session['last_activity'] > $this->now)
{
$this->sess_destroy();
return FALSE;
@@ -658,10 +662,13 @@ class CI_Session_cookie extends CI_Session_driver {
// Serialize the userdata for the cookie
$cookie_data = $this->_serialize($cookie_data);
- $cookie_data = ($this->sess_encrypt_cookie === TRUE)
- ? $this->CI->encrypt->encode($cookie_data)
- // if encryption is not used, we provide an md5 hash to prevent userside tampering
- : $cookie_data.md5($cookie_data.$this->encryption_key);
+ if ($this->sess_encrypt_cookie === TRUE)
+ {
+ $cookie_data = $this->CI->encrypt->encode($cookie_data);
+ }
+
+ // Require message authentication
+ $cookie_data .= hash_hmac('sha1', $cookie_data, $this->encryption_key);
$expire = ($this->sess_expire_on_close === TRUE) ? 0 : $this->sess_expiration + time();
diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php
index 8d5e51546..da744f39b 100755
--- a/system/libraries/Session/drivers/Session_native.php
+++ b/system/libraries/Session/drivers/Session_native.php
@@ -55,7 +55,9 @@ class CI_Session_native extends CI_Session_driver {
'sess_time_to_update',
'cookie_prefix',
'cookie_path',
- 'cookie_domain'
+ 'cookie_domain',
+ 'cookie_secure',
+ 'cookie_httponly'
);
foreach ($prefs as $key)
@@ -82,6 +84,9 @@ class CI_Session_native extends CI_Session_driver {
$expire = 7200;
$path = '/';
$domain = '';
+ $secure = (bool) $config['cookie_secure'];
+ $http_only = (bool) $config['cookie_httponly'];
+
if ($config['sess_expiration'] !== FALSE)
{
// Default to 2 years if expiration is "0"
@@ -99,7 +104,8 @@ class CI_Session_native extends CI_Session_driver {
// Use specified domain
$domain = $config['cookie_domain'];
}
- session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain);
+
+ session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain, $secure, $http_only);
// Start session
session_start();
@@ -107,7 +113,7 @@ class CI_Session_native extends CI_Session_driver {
// Check session expiration, ip, and agent
$now = time();
$destroy = FALSE;
- if (isset($_SESSION['last_activity']) && ($_SESSION['last_activity'] + $expire) < $now)
+ if (isset($_SESSION['last_activity']) && (($_SESSION['last_activity'] + $expire) < $now OR $_SESSION['last_activity'] > $now))
{
// Expired - destroy
$destroy = TRUE;
@@ -137,8 +143,12 @@ class CI_Session_native extends CI_Session_driver {
if ($config['sess_time_to_update'] && isset($_SESSION['last_activity'])
&& ($_SESSION['last_activity'] + $config['sess_time_to_update']) < $now)
{
- // Regenerate ID, but don't destroy session
- $this->sess_regenerate(FALSE);
+ // Changing the session ID amidst a series of AJAX calls causes problems
+ if( ! $this->CI->input->is_ajax_request())
+ {
+ // Regenerate ID, but don't destroy session
+ $this->sess_regenerate(FALSE);
+ }
}
// Set activity time
@@ -189,7 +199,7 @@ class CI_Session_native extends CI_Session_driver {
{
// Clear session cookie
$params = session_get_cookie_params();
- setcookie($name, '', time() - 42000, $params['path'], $params['domain']);
+ setcookie($name, '', time() - 42000, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
unset($_COOKIE[$name]);
}
session_destroy();