From 82d2cf17e77d0ca5ffdcaafb72ca2d3dc82dc142 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 13 Oct 2012 12:38:42 +0300 Subject: Fix CI_Input::ip_address() subnet detection --- system/core/Input.php | 48 ++++++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 20 deletions(-) (limited to 'system') 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; -- cgit v1.2.3-24-g4f1b From 37c85d73c4428bd19fafbba33992649fc29946d5 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Sat, 13 Oct 2012 17:08:45 +0300 Subject: Apparently not all PHP builds consider mysqli::__construct() with no parameters to be the same as mysqli_init() --- system/database/drivers/mysqli/mysqli_driver.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') 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; -- cgit v1.2.3-24-g4f1b From 02117680c8a3a4c7da2b10e25fc6c29fd5fa9bd2 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 15 Oct 2012 11:12:37 +0300 Subject: Partially fix #1702 --- system/libraries/Session/drivers/Session_cookie.php | 2 +- system/libraries/Session/drivers/Session_native.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php index fb62c7ec4..5bb1f7aa6 100755 --- a/system/libraries/Session/drivers/Session_cookie.php +++ b/system/libraries/Session/drivers/Session_cookie.php @@ -405,7 +405,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; diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php index 8d5e51546..6529d4c36 100755 --- a/system/libraries/Session/drivers/Session_native.php +++ b/system/libraries/Session/drivers/Session_native.php @@ -107,7 +107,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; -- cgit v1.2.3-24-g4f1b From c7719284833f211984474623832b96707173e02d Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 15 Oct 2012 14:12:22 +0300 Subject: Remove CI_Email::_get_ip() --- system/libraries/Email.php | 41 ----------------------------------------- 1 file changed, 41 deletions(-) (limited to 'system') diff --git a/system/libraries/Email.php b/system/libraries/Email.php index fa1d5e9bf..08057f2f7 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -1753,47 +1753,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 * -- cgit v1.2.3-24-g4f1b From 19cd88799f27bef8d502250c86eddcd72789bdb3 Mon Sep 17 00:00:00 2001 From: GDmac Date: Tue, 16 Oct 2012 14:19:57 +0200 Subject: Session Native, respect cookie settings Respect config settings for cookie_secure and cookie_httponly Signed-off-by: GDmac --- .../libraries/Session/drivers/Session_native.php | 24 +++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php index 6529d4c36..d7b9e8410 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 = FALSE; + $http_only = FALSE; + if ($config['sess_expiration'] !== FALSE) { // Default to 2 years if expiration is "0" @@ -99,7 +104,20 @@ 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); + + if ($config['cookie_secure']) + { + // Send over SSL / HTTPS only? + $secure = $config['cookie_secure']; + } + + if ($config['cookie_httponly']) + { + // only available to HTTP(S)? + $http_only = $config['http_only']; + } + + session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain, $secure, $http_only); // Start session session_start(); @@ -189,7 +207,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(); -- cgit v1.2.3-24-g4f1b From 28616da32bcf72f37c0e61e304a1799b90ceec3f Mon Sep 17 00:00:00 2001 From: GDmac Date: Tue, 16 Oct 2012 15:01:14 +0200 Subject: Native PHP Session, don't regenerate session_id during ajax Signed-off-by: GDmac --- system/libraries/Session/drivers/Session_native.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php index d7b9e8410..fb3b638a0 100755 --- a/system/libraries/Session/drivers/Session_native.php +++ b/system/libraries/Session/drivers/Session_native.php @@ -155,8 +155,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 -- cgit v1.2.3-24-g4f1b From f69f0e8f02815d44e218b013c8da92cebabbdcb1 Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Tue, 16 Oct 2012 11:54:49 -0400 Subject: Updating the cookie driver to use HMAC authentication on all cookie data. Signed-off-by: Pascal Kriete --- .../libraries/Session/drivers/Session_cookie.php | 45 +++++++++++++--------- 1 file changed, 26 insertions(+), 19 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php index 5bb1f7aa6..b44c8330e 100755 --- a/system/libraries/Session/drivers/Session_cookie.php +++ b/system/libraries/Session/drivers/Session_cookie.php @@ -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 could be a possible hacking attempt.'); + $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); @@ -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) + { + $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(); -- cgit v1.2.3-24-g4f1b From ff5ffdf7fa3b458510a95788ac3baa6fba3178cc Mon Sep 17 00:00:00 2001 From: GDmac Date: Tue, 16 Oct 2012 19:22:12 +0200 Subject: session native, fix cookie settings Signed-off-by: GDmac --- system/libraries/Session/drivers/Session_native.php | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_native.php b/system/libraries/Session/drivers/Session_native.php index fb3b638a0..da744f39b 100755 --- a/system/libraries/Session/drivers/Session_native.php +++ b/system/libraries/Session/drivers/Session_native.php @@ -84,8 +84,8 @@ class CI_Session_native extends CI_Session_driver { $expire = 7200; $path = '/'; $domain = ''; - $secure = FALSE; - $http_only = FALSE; + $secure = (bool) $config['cookie_secure']; + $http_only = (bool) $config['cookie_httponly']; if ($config['sess_expiration'] !== FALSE) { @@ -105,18 +105,6 @@ class CI_Session_native extends CI_Session_driver { $domain = $config['cookie_domain']; } - if ($config['cookie_secure']) - { - // Send over SSL / HTTPS only? - $secure = $config['cookie_secure']; - } - - if ($config['cookie_httponly']) - { - // only available to HTTP(S)? - $http_only = $config['http_only']; - } - session_set_cookie_params($config['sess_expire_on_close'] ? 0 : $expire, $path, $domain, $secure, $http_only); // Start session -- cgit v1.2.3-24-g4f1b From 8a7078b65dc387c8d74f963b80a7559bd094458a Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Wed, 17 Oct 2012 10:52:49 +0300 Subject: Fix issue #1897 --- system/libraries/Email.php | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) (limited to 'system') diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 08057f2f7..5b17edf9b 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -292,16 +292,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; } @@ -1408,6 +1399,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); -- cgit v1.2.3-24-g4f1b From 28dc2023d32e1d997e2b90052f1960f98a255d2c Mon Sep 17 00:00:00 2001 From: Pascal Kriete Date: Wed, 17 Oct 2012 11:27:29 -0400 Subject: Changing session error logging verbiage to be a little less unsettling. Signed-off-by: Pascal Kriete --- system/libraries/Session/drivers/Session_cookie.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php index b44c8330e..51d94da4e 100755 --- a/system/libraries/Session/drivers/Session_cookie.php +++ b/system/libraries/Session/drivers/Session_cookie.php @@ -386,7 +386,7 @@ class CI_Session_cookie extends CI_Session_driver { if ($hmac !== hash_hmac('sha1', $session, $this->encryption_key)) { - log_message('error', 'The session cookie data did not match what was expected. This could be a possible hacking attempt.'); + log_message('error', 'The session cookie data did not match what was expected.'); $this->sess_destroy(); return FALSE; } -- cgit v1.2.3-24-g4f1b From 00ea2a9a3a6451d106ed3f083716f59e84d5f656 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 18 Oct 2012 14:59:29 +0300 Subject: Remove {unwrap}{/unwrap} markers when quoted_printable_encode() or imap_8bit() is used --- system/libraries/Email.php | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'system') diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 5b17edf9b..bc9d62eb4 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -754,7 +754,7 @@ class CI_Email { { if ($this->alt_message !== '') { - return $this->word_wrap($this->alt_message, '76'); + return $this->word_wrap($this->alt_message, 76); } $body = preg_match('/\(.*)\<\/body\>/si', $this->_body, $match) ? $match[1] : $this->_body; @@ -777,12 +777,12 @@ class CI_Email { * @param int * @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 @@ -1096,6 +1096,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, @@ -1121,10 +1125,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 = ''; -- cgit v1.2.3-24-g4f1b From cf264e0d165647f30efdef1b2d944849bebf4c72 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Thu, 18 Oct 2012 16:14:51 +0300 Subject: Fix Session cookies not being encrypted on creation and sess_destroy() not actually deleting cookies --- system/libraries/Session/drivers/Session_cookie.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php index 51d94da4e..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 @@ -664,7 +664,7 @@ class CI_Session_cookie extends CI_Session_driver { if ($this->sess_encrypt_cookie === TRUE) { - $this->CI->encrypt->encode($cookie_data); + $cookie_data = $this->CI->encrypt->encode($cookie_data); } // Require message authentication -- cgit v1.2.3-24-g4f1b From 929e1241879c94bff85203d2e00623284d72dc87 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 19 Oct 2012 10:09:28 +0300 Subject: Manually apply an improved version of PR #1797 (auto_link() URL helper) --- system/helpers/url_helper.php | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'system') 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].'http' .$matches[4][$i].'://'.$matches[5][$i] - .$matches[6][$i].''.$period, + .$matches[6][$i].''.$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); + } } } -- cgit v1.2.3-24-g4f1b From 925dd9030db7a5a47d8a79f94b35827b14b9b685 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 19 Oct 2012 11:06:31 +0300 Subject: Fix issue #1409 --- system/libraries/Email.php | 110 ++++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 51 deletions(-) (limited to 'system') diff --git a/system/libraries/Email.php b/system/libraries/Email.php index bc9d62eb4..795db2043 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; @@ -1177,66 +1176,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); + $str = str_replace(array("\r", "\n"), '', $str); - // these special characters must be converted too - $convert = array('_', '=', '?'); - - 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.'?='; } // -------------------------------------------------------------------- -- cgit v1.2.3-24-g4f1b From 8df1ae2d7e0fd441f7a1fc481c76c5c1edfadf23 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Fri, 19 Oct 2012 11:20:54 +0300 Subject: Fix another mailing issue (based on #1281) --- system/libraries/Email.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) (limited to 'system') diff --git a/system/libraries/Email.php b/system/libraries/Email.php index 795db2043..c1130e915 100644 --- a/system/libraries/Email.php +++ b/system/libraries/Email.php @@ -742,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 * @@ -751,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\>/si', $this->_body, $match) ? $match[1] : $this->_body; @@ -764,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; } // -------------------------------------------------------------------- @@ -773,7 +777,7 @@ class CI_Email { * Word Wrap * * @param string - * @param int + * @param int line-length limit * @return string */ public function word_wrap($str, $charlim = NULL) -- cgit v1.2.3-24-g4f1b From e66d6243aaf13053631641973a0beff656a94510 Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 22 Oct 2012 16:39:12 +0300 Subject: Fix issues #1476, #1909 --- system/libraries/Pagination.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php index e1e729bb0..36b57b332 100644 --- a/system/libraries/Pagination.php +++ b/system/libraries/Pagination.php @@ -157,7 +157,7 @@ class CI_Pagination { // See if we are using a prefix or suffix on links if ($this->prefix !== '' OR $this->suffix !== '') { - $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->segment($this->uri_segment)); + $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->rsegment($this->uri_segment)); } if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE) @@ -169,7 +169,7 @@ class CI_Pagination { } elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page) { - $this->cur_page = (int) $CI->uri->segment($this->uri_segment); + $this->cur_page = (int) $CI->uri->rsegment($this->uri_segment); } // Set current page to 1 if it's not valid or if using page numbers instead of offset -- cgit v1.2.3-24-g4f1b From 3fb026713013b60845c4cfe633a8a59a30b9c7dd Mon Sep 17 00:00:00 2001 From: Andrey Andreev Date: Mon, 22 Oct 2012 16:48:01 +0300 Subject: Add is_https() as a common function --- system/core/Common.php | 18 ++++++++++++++++++ system/core/Config.php | 2 +- system/core/Security.php | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) (limited to 'system') diff --git a/system/core/Common.php b/system/core/Common.php index 341402c6b..2dd31d3e9 100644 --- a/system/core/Common.php +++ b/system/core/Common.php @@ -330,6 +330,24 @@ if ( ! function_exists('get_mimes')) // ------------------------------------------------------------------------ +if ( ! function_exists('is_https')) +{ + /** + * Is HTTPS? + * + * Determines if the application is accessed via an encrypted + * (HTTPS) connection. + * + * @return bool + */ + function is_https() + { + return ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off'); + } +} + +// ------------------------------------------------------------------------ + if ( ! function_exists('show_error')) { /** diff --git a/system/core/Config.php b/system/core/Config.php index 8e4f998ef..e78128c76 100644 --- a/system/core/Config.php +++ b/system/core/Config.php @@ -75,7 +75,7 @@ class CI_Config { { if (isset($_SERVER['HTTP_HOST'])) { - $base_url = ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off') ? 'https' : 'http'; + $base_url = is_https() ? 'https' : 'http'; $base_url .= '://'.$_SERVER['HTTP_HOST'] .str_replace(basename($_SERVER['SCRIPT_NAME']), '', $_SERVER['SCRIPT_NAME']); } diff --git a/system/core/Security.php b/system/core/Security.php index b22d2cf19..2fbc5b34c 100644 --- a/system/core/Security.php +++ b/system/core/Security.php @@ -198,7 +198,7 @@ class CI_Security { $expire = time() + $this->_csrf_expire; $secure_cookie = (bool) config_item('cookie_secure'); - if ($secure_cookie && (empty($_SERVER['HTTPS']) OR strtolower($_SERVER['HTTPS']) === 'off')) + if ($secure_cookie && ! is_https()) { return FALSE; } -- cgit v1.2.3-24-g4f1b