summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Hunsaker <danhunsaker@gmail.com>2013-02-22 21:49:33 +0100
committerDaniel Hunsaker <danhunsaker@gmail.com>2013-02-22 21:49:33 +0100
commit44a6d1da2be916fe0f23a3ea4d5fcb391d7f65dd (patch)
tree31549ebf6ea5ea98e4347eb640d1caa685316f3e
parent353f9834adf3f44c6c7a0f924089bb2b43360404 (diff)
parenteb291c1d1e1116a4420fa30e587adeea0451eeb7 (diff)
Merge branch 'develop' of github.com:EllisLab/CodeIgniter into feature/exit-status
-rw-r--r--.travis.yml3
-rw-r--r--application/config/config.php14
-rw-r--r--application/config/mimes.php9
-rw-r--r--composer.json7
-rw-r--r--system/core/CodeIgniter.php8
-rw-r--r--system/core/Common.php16
-rw-r--r--system/core/Config.php6
-rw-r--r--system/core/Hooks.php7
-rw-r--r--system/core/Input.php4
-rw-r--r--system/core/Loader.php158
-rw-r--r--system/core/Log.php25
-rw-r--r--system/core/Output.php2
-rw-r--r--system/core/Router.php9
-rw-r--r--system/core/Security.php10
-rw-r--r--system/core/URI.php2
-rw-r--r--system/database/DB.php6
-rw-r--r--system/database/DB_driver.php4
-rw-r--r--system/database/DB_query_builder.php3
-rw-r--r--system/database/drivers/mssql/mssql_result.php1
-rw-r--r--system/database/drivers/mysql/mysql_result.php1
-rw-r--r--system/database/drivers/mysqli/mysqli_result.php1
-rw-r--r--system/database/drivers/pdo/pdo_driver.php7
-rw-r--r--system/helpers/captcha_helper.php6
-rw-r--r--system/helpers/download_helper.php2
-rw-r--r--system/helpers/form_helper.php9
-rw-r--r--system/helpers/html_helper.php20
-rw-r--r--system/helpers/smiley_helper.php28
-rw-r--r--system/helpers/text_helper.php22
-rw-r--r--system/helpers/url_helper.php19
-rw-r--r--system/language/english/form_validation_lang.php1
-rw-r--r--system/language/english/profiler_lang.php1
-rw-r--r--system/libraries/Cache/drivers/Cache_memcached.php4
-rw-r--r--system/libraries/Cart.php4
-rw-r--r--system/libraries/Driver.php19
-rw-r--r--system/libraries/Email.php55
-rw-r--r--system/libraries/Form_validation.php21
-rw-r--r--system/libraries/Image_lib.php2
-rw-r--r--system/libraries/Javascript.php2
-rw-r--r--system/libraries/Javascript/Jquery.php (renamed from system/libraries/javascript/Jquery.php)0
-rw-r--r--system/libraries/Javascript/index.html (renamed from system/libraries/javascript/index.html)0
-rw-r--r--system/libraries/Migration.php6
-rw-r--r--system/libraries/Pagination.php198
-rw-r--r--system/libraries/Profiler.php3
-rw-r--r--system/libraries/Session/drivers/Session_cookie.php5
-rw-r--r--system/libraries/Upload.php51
-rw-r--r--system/libraries/User_agent.php13
-rw-r--r--system/libraries/Xmlrpcs.php2
-rw-r--r--tests/Bootstrap.php1
-rw-r--r--tests/codeigniter/core/Input_test.php25
-rw-r--r--tests/codeigniter/core/Loader_test.php18
-rw-r--r--tests/codeigniter/core/Output_test.php35
-rw-r--r--tests/codeigniter/core/URI_test.php2
-rw-r--r--tests/codeigniter/core/Utf8_test.php20
-rw-r--r--tests/codeigniter/helpers/form_helper_test.php2
-rw-r--r--tests/codeigniter/helpers/url_helper_test.php11
-rw-r--r--tests/codeigniter/libraries/Upload_test.php6
-rwxr-xr-xtests/mocks/database/ci_test.sqlitebin19456 -> 19456 bytes
-rw-r--r--tests/mocks/libraries/session.php4
-rw-r--r--user_guide_src/source/changelog.rst47
-rw-r--r--user_guide_src/source/database/call_function.rst2
-rw-r--r--user_guide_src/source/general/controllers.rst4
-rw-r--r--user_guide_src/source/general/routing.rst6
-rw-r--r--user_guide_src/source/installation/upgrade_300.rst61
-rw-r--r--user_guide_src/source/libraries/email.rst1
-rw-r--r--user_guide_src/source/libraries/form_validation.rst4
-rw-r--r--user_guide_src/source/libraries/loader.rst146
-rw-r--r--user_guide_src/source/libraries/migration.rst2
-rw-r--r--user_guide_src/source/tutorial/news_section.rst8
68 files changed, 710 insertions, 491 deletions
diff --git a/.travis.yml b/.travis.yml
index 070b23c8a..ab0aa5616 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,8 +14,7 @@ env:
- DB=pdo/sqlite
before_script:
- - curl -s http://getcomposer.org/installer | php
- - php composer.phar install
+ - composer install --dev --no-progress
- sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS ci_test;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ] || [ '$DB' = 'pdo/pgsql' ]; then psql -c 'create database ci_test;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ] || [ '$DB' = 'mysqli' ] || [ '$DB' = 'pdo/mysql' ]; then mysql -e 'create database IF NOT EXISTS ci_test;'; fi"
diff --git a/application/config/config.php b/application/config/config.php
index 415474e06..0608348c6 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -226,6 +226,20 @@ $config['log_path'] = '';
/*
|--------------------------------------------------------------------------
+| Log File Extension
+|--------------------------------------------------------------------------
+|
+| The default filename extension for log files. The default 'php' allows for
+| protecting the log files via basic scripting, when they are to be stored
+| under a publicly accessible directory.
+|
+| Note: Leaving it blank will default to 'php'.
+|
+*/
+$config['log_file_extension'] = '';
+
+/*
+|--------------------------------------------------------------------------
| Date Format for Logs
|--------------------------------------------------------------------------
|
diff --git a/application/config/mimes.php b/application/config/mimes.php
index 124e4a436..5b8ceff2e 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -44,13 +44,13 @@ return array(
'lzh' => 'application/octet-stream',
'exe' => array('application/octet-stream', 'application/x-msdownload'),
'class' => 'application/octet-stream',
- 'psd' => 'application/x-photoshop',
+ 'psd' => array('application/x-photoshop', 'image/vnd.adobe.photoshop'),
'so' => 'application/octet-stream',
'sea' => 'application/octet-stream',
'dll' => 'application/octet-stream',
'oda' => 'application/oda',
'pdf' => array('application/pdf', 'application/x-download', 'binary/octet-stream'),
- 'ai' => 'application/postscript',
+ 'ai' => array('application/pdf', 'application/postscript'),
'eps' => 'application/postscript',
'ps' => 'application/postscript',
'smi' => 'application/smil',
@@ -123,7 +123,7 @@ return array(
'avi' => array('video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'),
'movie' => 'video/x-sgi-movie',
'doc' => array('application/msword', 'application/vnd.ms-office'),
- 'docx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword'),
+ 'docx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword', 'application/x-zip'),
'dot' => array('application/msword', 'application/vnd.ms-office'),
'dotx' => array('application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/zip', 'application/msword'),
'xlsx' => array('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'application/zip', 'application/vnd.ms-excel', 'application/msword'),
@@ -154,12 +154,13 @@ return array(
'mp4' => 'video/mp4',
'm4a' => 'audio/x-m4a',
'f4v' => 'video/mp4',
+ 'webm' => 'video/webm',
'aac' => 'audio/x-acc',
'm4u' => 'application/vnd.mpegurl',
'm3u' => 'text/plain',
'xspf' => 'application/xspf+xml',
'vlc' => 'application/videolan',
- 'wmv' => 'video/x-ms-wmv',
+ 'wmv' => array('video/x-ms-wmv', 'video/x-ms-asf'),
'au' => 'audio/x-au',
'ac3' => 'audio/ac3',
'flac' => 'audio/x-flac',
diff --git a/composer.json b/composer.json
index 7d60020c3..e21aaed2e 100644
--- a/composer.json
+++ b/composer.json
@@ -1,8 +1,9 @@
{
+ "name" : "ellislab/codeigniter",
"require": {
- "mikey179/vfsStream": "*"
+ "php": ">=5.2.4"
},
"require-dev": {
- "phpunit/phpunit": "*"
- }
+ "mikey179/vfsStream": "*"
+ }
} \ No newline at end of file
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index 13826c328..5a872ef21 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -58,7 +58,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* Load the framework constants
* ------------------------------------------------------
*/
- if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
{
require(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
}
@@ -263,7 +263,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
$class = $RTR->fetch_class();
$method = $RTR->fetch_method();
- if ( ! class_exists($class) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
+ if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
{
if ( ! empty($RTR->routes['404_override']))
{
@@ -272,7 +272,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
$method = 'index';
}
- if ( ! class_exists($class))
+ if ( ! class_exists($class, FALSE))
{
if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
{
@@ -310,7 +310,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
$method = 'index';
}
- if ( ! class_exists($class))
+ if ( ! class_exists($class, FALSE))
{
if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
{
diff --git a/system/core/Common.php b/system/core/Common.php
index d6387209b..3cd97dc2e 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -150,7 +150,7 @@ if ( ! function_exists('load_class'))
{
$name = $prefix.$class;
- if (class_exists($name) === FALSE)
+ if (class_exists($name, FALSE) === FALSE)
{
require_once($path.$directory.'/'.$class.'.php');
}
@@ -164,7 +164,7 @@ if ( ! function_exists('load_class'))
{
$name = config_item('subclass_prefix').$class;
- if (class_exists($name) === FALSE)
+ if (class_exists($name, FALSE) === FALSE)
{
require_once(APPPATH.$directory.'/'.config_item('subclass_prefix').$class.'.php');
}
@@ -243,7 +243,7 @@ if ( ! function_exists('get_config'))
}
// Is the config file in the environment folder?
- if (defined('ENVIRONMENT') && file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
{
require($file_path);
}
@@ -320,11 +320,11 @@ if ( ! function_exists('get_mimes'))
{
static $_mimes = array();
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
$_mimes = include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
}
- elseif (is_file(APPPATH.'config/mimes.php'))
+ elseif (file_exists(APPPATH.'config/mimes.php'))
{
$_mimes = include(APPPATH.'config/mimes.php');
}
@@ -347,7 +347,7 @@ if ( ! function_exists('is_https'))
*/
function is_https()
{
- return ( ! empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) !== 'off');
+ return (isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) === 'on');
}
}
@@ -429,7 +429,7 @@ if ( ! function_exists('log_message'))
function log_message($level = 'error', $message, $php_error = FALSE)
{
static $_log, $_log_threshold;
-
+
if ($_log_threshold === NULL)
{
$_log_threshold = config_item('log_threshold');
@@ -444,7 +444,7 @@ if ( ! function_exists('log_message'))
{
$_log =& load_class('Log', 'core');
}
-
+
$_log->write_log($level, $message, $php_error);
}
}
diff --git a/system/core/Config.php b/system/core/Config.php
index 0160d1a15..7e64444bc 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -106,13 +106,9 @@ class CI_Config {
$file = ($file === '') ? 'config' : str_replace('.php', '', $file);
$found = $loaded = FALSE;
- $check_locations = defined('ENVIRONMENT')
- ? array(ENVIRONMENT.'/'.$file, $file)
- : array($file);
-
foreach ($this->_config_paths as $path)
{
- foreach ($check_locations as $location)
+ foreach (array(ENVIRONMENT.'/'.$file, $file) as $location)
{
$file_path = $path.'config/'.$location.'.php';
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index 2cb416c0c..b3b111991 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -81,11 +81,12 @@ class CI_Hooks {
}
// Grab the "hooks" definition file.
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/hooks.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/hooks.php');
}
- elseif (is_file(APPPATH.'config/hooks.php'))
+
+ if (file_exists(APPPATH.'config/hooks.php'))
{
include(APPPATH.'config/hooks.php');
}
@@ -194,7 +195,7 @@ class CI_Hooks {
// Call the requested class and/or function
if ($class !== FALSE)
{
- if ( ! class_exists($class))
+ if ( ! class_exists($class, FALSE))
{
require($filepath);
}
diff --git a/system/core/Input.php b/system/core/Input.php
index 8f37e4464..904f4d6e9 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -720,9 +720,9 @@ class CI_Input {
}
// Standardize newlines if needed
- if ($this->_standardize_newlines === TRUE && strpos($str, "\r") !== FALSE)
+ if ($this->_standardize_newlines === TRUE)
{
- return str_replace(array("\r\n", "\r", "\r\n\n"), PHP_EOL, $str);
+ return preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $str);
}
return $str;
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 1ad07f1fa..6e5b58ba7 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -97,13 +97,6 @@ class CI_Loader {
protected $_ci_classes = array();
/**
- * List of loaded files
- *
- * @var array
- */
- protected $_ci_loaded_files = array();
-
- /**
* List of loaded models
*
* @var array
@@ -277,7 +270,7 @@ class CI_Loader {
continue;
}
- if ($db_conn !== FALSE && ! class_exists('CI_DB'))
+ if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
{
if ($db_conn === TRUE)
{
@@ -287,7 +280,7 @@ class CI_Loader {
$CI->load->database($db_conn, FALSE, TRUE);
}
- if ( ! class_exists('CI_Model'))
+ if ( ! class_exists('CI_Model', FALSE))
{
load_class('Model', 'core');
}
@@ -943,7 +936,6 @@ class CI_Loader {
// Was the path included with the class name?
// We look for a slash to determine this
- $subdir = '';
if (($last_slash = strrpos($class, '/')) !== FALSE)
{
// Extract the path
@@ -952,108 +944,92 @@ class CI_Loader {
// Get the filename from the path
$class = substr($class, $last_slash);
}
+ else
+ {
+ $subdir = '';
+ }
+
+ $class = ucfirst($class);
+ $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
- // We'll test for both lowercase and capitalized versions of the file name
- foreach (array(ucfirst($class), strtolower($class)) as $class)
+ // Is this a class extension request?
+ if (file_exists($subclass))
{
- $subclass = APPPATH.'libraries/'.$subdir.config_item('subclass_prefix').$class.'.php';
+ $baseclass = BASEPATH.'libraries/'.$class.'.php';
- // Is this a class extension request?
- if (file_exists($subclass))
+ if ( ! file_exists($baseclass))
{
- $baseclass = BASEPATH.'libraries/'.ucfirst($class).'.php';
-
- if ( ! file_exists($baseclass))
- {
- log_message('error', 'Unable to load the requested class: '.$class);
- show_error('Unable to load the requested class: '.$class);
- }
+ log_message('error', 'Unable to load the requested class: '.$class);
+ show_error('Unable to load the requested class: '.$class);
+ }
- // Safety: Was the class already loaded by a previous call?
- if (in_array($subclass, $this->_ci_loaded_files))
+ // Safety: Was the class already loaded by a previous call?
+ if (class_exists(config_item('subclass_prefix').$class, FALSE))
+ {
+ // Before we deem this to be a duplicate request, let's see
+ // if a custom object name is being supplied. If so, we'll
+ // return a new instance of the object
+ if ($object_name !== NULL)
{
- // Before we deem this to be a duplicate request, let's see
- // if a custom object name is being supplied. If so, we'll
- // return a new instance of the object
- if ($object_name !== NULL)
+ $CI =& get_instance();
+ if ( ! isset($CI->$object_name))
{
- $CI =& get_instance();
- if ( ! isset($CI->$object_name))
- {
- return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
- }
+ return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
}
-
- $is_duplicate = TRUE;
- log_message('debug', $class.' class already loaded. Second attempt ignored.');
- return;
}
- include_once($baseclass);
- include_once($subclass);
- $this->_ci_loaded_files[] = $subclass;
-
- return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
+ log_message('debug', $class.' class already loaded. Second attempt ignored.');
+ return;
}
- // Lets search for the requested library file and load it.
- $is_duplicate = FALSE;
- foreach ($this->_ci_library_paths as $path)
- {
- $filepath = $path.'libraries/'.$subdir.$class.'.php';
+ include_once($baseclass);
+ include_once($subclass);
- // Does the file exist? No? Bummer...
- if ( ! file_exists($filepath))
- {
- continue;
- }
+ return $this->_ci_init_class($class, config_item('subclass_prefix'), $params, $object_name);
+ }
+
+ // Let's search for the requested library file and load it.
+ foreach ($this->_ci_library_paths as $path)
+ {
+ $filepath = $path.'libraries/'.$subdir.$class.'.php';
- // Safety: Was the class already loaded by a previous call?
- if (in_array($filepath, $this->_ci_loaded_files))
+ // Safety: Was the class already loaded by a previous call?
+ if (class_exists($class, FALSE))
+ {
+ // Before we deem this to be a duplicate request, let's see
+ // if a custom object name is being supplied. If so, we'll
+ // return a new instance of the object
+ if ($object_name !== NULL)
{
- // Before we deem this to be a duplicate request, let's see
- // if a custom object name is being supplied. If so, we'll
- // return a new instance of the object
- if ($object_name !== NULL)
+ $CI =& get_instance();
+ if ( ! isset($CI->$object_name))
{
- $CI =& get_instance();
- if ( ! isset($CI->$object_name))
- {
- return $this->_ci_init_class($class, '', $params, $object_name);
- }
+ return $this->_ci_init_class($class, '', $params, $object_name);
}
-
- $is_duplicate = TRUE;
- log_message('debug', $class.' class already loaded. Second attempt ignored.');
- return;
}
- include_once($filepath);
- $this->_ci_loaded_files[] = $filepath;
- return $this->_ci_init_class($class, '', $params, $object_name);
+ log_message('debug', $class.' class already loaded. Second attempt ignored.');
+ return;
+ }
+ // Does the file exist? No? Bummer...
+ elseif ( ! file_exists($filepath))
+ {
+ continue;
}
- } // END FOREACH
+
+ include_once($filepath);
+ return $this->_ci_init_class($class, '', $params, $object_name);
+ }
// One last attempt. Maybe the library is in a subdirectory, but it wasn't specified?
if ($subdir === '')
{
- $path = strtolower($class).'/'.$class;
- return $this->_ci_load_class($path, $params, $object_name);
- }
- elseif (ucfirst($subdir) != $subdir)
- {
- // Lowercase subdir failed - retry capitalized
- $path = ucfirst($subdir).$class;
- return $this->_ci_load_class($path, $params, $object_name);
+ return $this->_ci_load_class($class.'/'.$class, $params, $object_name);
}
// If we got this far we were unable to find the requested class.
- // We do not issue errors if the load call failed due to a duplicate request
- if ($is_duplicate === FALSE)
- {
- log_message('error', 'Unable to load the requested class: '.$class);
- show_error('Unable to load the requested class: '.$class);
- }
+ log_message('error', 'Unable to load the requested class: '.$class);
+ show_error('Unable to load the requested class: '.$class);
}
// --------------------------------------------------------------------
@@ -1089,12 +1065,12 @@ class CI_Loader {
// We test for both uppercase and lowercase, for servers that
// are case-sensitive with regard to file names. Check for environment
// first, global next
- if (defined('ENVIRONMENT') && file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
+ if (file_exists($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
{
include($path.'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
break;
}
- elseif (defined('ENVIRONMENT') && file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
+ elseif (file_exists($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
{
include($path.'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
break;
@@ -1115,11 +1091,11 @@ class CI_Loader {
if ($prefix === '')
{
- if (class_exists('CI_'.$class))
+ if (class_exists('CI_'.$class, FALSE))
{
$name = 'CI_'.$class;
}
- elseif (class_exists(config_item('subclass_prefix').$class))
+ elseif (class_exists(config_item('subclass_prefix').$class, FALSE))
{
$name = config_item('subclass_prefix').$class;
}
@@ -1134,7 +1110,7 @@ class CI_Loader {
}
// Is the class name valid?
- if ( ! class_exists($name))
+ if ( ! class_exists($name, FALSE))
{
log_message('error', 'Non-existent class: '.$name);
show_error('Non-existent class: '.$name);
@@ -1180,7 +1156,7 @@ class CI_Loader {
*/
protected function _ci_autoloader()
{
- if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
}
diff --git a/system/core/Log.php b/system/core/Log.php
index cd3c17e1e..a84d3dc22 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -73,6 +73,13 @@ class CI_Log {
protected $_date_fmt = 'Y-m-d H:i:s';
/**
+ * Filename extension
+ *
+ * @var string
+ */
+ protected $_file_ext;
+
+ /**
* Whether or not the logger can write to the log files
*
* @var bool
@@ -86,8 +93,10 @@ class CI_Log {
*/
protected $_levels = array('ERROR' => 1, 'DEBUG' => 2, 'INFO' => 3, 'ALL' => 4);
+ // --------------------------------------------------------------------
+
/**
- * Initialize Logging class
+ * Class constructor
*
* @return void
*/
@@ -96,6 +105,8 @@ class CI_Log {
$config =& get_config();
$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';
file_exists($this->_log_path) OR mkdir($this->_log_path, DIR_WRITE_MODE, TRUE);
@@ -147,13 +158,17 @@ class CI_Log {
return FALSE;
}
- $filepath = $this->_log_path.'log-'.date('Y-m-d').'.php';
- $message = '';
+ $filepath = $this->_log_path.'log-'.date('Y-m-d').'.'.$this->_file_ext;
+ $message = '';
if ( ! file_exists($filepath))
{
$newfile = TRUE;
- $message .= '<'."?php defined('BASEPATH') OR exit('No direct script access allowed'); ?".">\n\n";
+ // Only add protection to php files
+ if ($this->_file_ext === 'php')
+ {
+ $message .= "<?php defined('BASEPATH') OR exit('No direct script access allowed'); ?>\n\n";
+ }
}
if ( ! $fp = @fopen($filepath, FOPEN_WRITE_CREATE))
@@ -179,4 +194,4 @@ class CI_Log {
}
/* End of file Log.php */
-/* Location: ./system/libraries/Log.php */ \ No newline at end of file
+/* Location: ./system/core/Log.php */ \ No newline at end of file
diff --git a/system/core/Output.php b/system/core/Output.php
index 7898d1972..d4abe871d 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -395,7 +395,7 @@ class CI_Output {
global $BM, $CFG;
// Grab the super object if we can.
- if (class_exists('CI_Controller'))
+ if (class_exists('CI_Controller', FALSE))
{
$CI =& get_instance();
}
diff --git a/system/core/Router.php b/system/core/Router.php
index f284e29cc..bb0ce16bd 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -133,13 +133,14 @@ class CI_Router {
}
// Load the routes.php file.
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
+ if (file_exists(APPPATH.'config/routes.php'))
{
- include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
+ include(APPPATH.'config/routes.php');
}
- elseif (is_file(APPPATH.'config/routes.php'))
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/routes.php'))
{
- include(APPPATH.'config/routes.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/routes.php');
}
$this->routes = (empty($route) OR ! is_array($route)) ? array() : $route;
diff --git a/system/core/Security.php b/system/core/Security.php
index a6cd14a5f..7aae54efc 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -576,7 +576,15 @@ class CI_Security {
}
$str = remove_invisible_characters($str, FALSE);
- return stripslashes(str_replace($bad, '', $str));
+
+ do
+ {
+ $old = $str;
+ $str = str_replace($bad, '', $str);
+ }
+ while ($old !== $str);
+
+ return stripslashes($str);
}
// ----------------------------------------------------------------
diff --git a/system/core/URI.php b/system/core/URI.php
index 9b31a646b..b2286f032 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -126,7 +126,7 @@ class CI_URI {
return;
}
- // As a last ditch effort lets try using the $_GET array
+ // As a last ditch effort let's try using the $_GET array
if (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
{
$this->_set_uri_string(key($_GET));
diff --git a/system/database/DB.php b/system/database/DB.php
index f94685c51..83d973304 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -43,7 +43,7 @@ function &DB($params = '', $query_builder_override = NULL)
if (is_string($params) && strpos($params, '://') === FALSE)
{
// Is the config file in the environment folder?
- if (( ! defined('ENVIRONMENT') OR ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database.php'))
+ if ( ! file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/database.php')
&& ! file_exists($file_path = APPPATH.'config/database.php'))
{
show_error('The configuration file database.php does not exist.');
@@ -149,7 +149,7 @@ function &DB($params = '', $query_builder_override = NULL)
if ( ! isset($query_builder) OR $query_builder === TRUE)
{
require_once(BASEPATH.'database/DB_query_builder.php');
- if ( ! class_exists('CI_DB'))
+ if ( ! class_exists('CI_DB', FALSE))
{
/**
* CI_DB
@@ -162,7 +162,7 @@ function &DB($params = '', $query_builder_override = NULL)
class CI_DB extends CI_DB_query_builder { }
}
}
- elseif ( ! class_exists('CI_DB'))
+ elseif ( ! class_exists('CI_DB', FALSE))
{
/**
* @ignore
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index cb2ef4ac8..6ae1d524d 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -625,7 +625,7 @@ abstract class CI_DB_driver {
// if transactions are enabled. If we don't call this here
// the error message will trigger an exit, causing the
// transactions to remain in limbo.
- $this->trans_complete();
+ $this->_trans_depth > 0 && $this->trans_complete();
// Display errors
return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql));
@@ -1560,7 +1560,7 @@ abstract class CI_DB_driver {
*/
protected function _cache_init()
{
- if (class_exists('CI_DB_Cache'))
+ if (class_exists('CI_DB_Cache', FALSE))
{
if (is_object($this->CACHE))
{
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index ac377d996..85a233b50 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -937,7 +937,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->qb_where[] = array('condition' => $like_statement, 'escape' => $escape);
if ($this->qb_caching === TRUE)
{
- $this->qb_cache_where[] = $like_statement;
+ $this->qb_cache_where[] = array('condition' => $like_statement, 'escape' => $escape);
$this->qb_cache_exists[] = 'where';
}
}
@@ -2627,6 +2627,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$this->_reset_run(array(
'qb_set' => array(),
'qb_from' => array(),
+ 'qb_join' => array(),
'qb_where' => array(),
'qb_orderby' => array(),
'qb_keys' => array(),
diff --git a/system/database/drivers/mssql/mssql_result.php b/system/database/drivers/mssql/mssql_result.php
index ea3f8e4d1..b6e5f2b17 100644
--- a/system/database/drivers/mssql/mssql_result.php
+++ b/system/database/drivers/mssql/mssql_result.php
@@ -74,6 +74,7 @@ class CI_DB_mssql_result extends CI_DB_result {
public function list_fields()
{
$field_names = array();
+ mssql_field_seek($this->result_id, 0);
while ($field = mssql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 1ed2759b6..a2affcb58 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -89,6 +89,7 @@ class CI_DB_mysql_result extends CI_DB_result {
public function list_fields()
{
$field_names = array();
+ mysql_field_seek($this->result_id, 0);
while ($field = mysql_fetch_field($this->result_id))
{
$field_names[] = $field->name;
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index 4105f99f6..3fe05f9c5 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -74,6 +74,7 @@ class CI_DB_mysqli_result extends CI_DB_result {
public function list_fields()
{
$field_names = array();
+ $this->result_id->field_seek(0);
while ($field = $this->result_id->fetch_field())
{
$field_names[] = $field->name;
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index 34adf0f86..fa89661b1 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -49,13 +49,6 @@ class CI_DB_pdo_driver extends CI_DB {
public $dbdriver = 'pdo';
/**
- * Transaction enabled flag
- *
- * @var bool
- */
- public $trans_enabled = FALSE;
-
- /**
* PDO Options
*
* @var array
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 83783324b..78e255a15 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -93,7 +93,7 @@ if ( ! function_exists('create_captcha'))
// Do we have a "word" yet?
// -----------------------------------
- if ($word === '')
+ if (empty($word))
{
$pool = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$word = '';
@@ -102,6 +102,10 @@ if ( ! function_exists('create_captcha'))
$word .= $pool[mt_rand(0, $mt_rand_max)];
}
}
+ elseif ( ! is_string($word))
+ {
+ $word = (string) $word;
+ }
// -----------------------------------
// Determine angle and position
diff --git a/system/helpers/download_helper.php b/system/helpers/download_helper.php
index d7691cb61..daf59f51b 100644
--- a/system/helpers/download_helper.php
+++ b/system/helpers/download_helper.php
@@ -58,7 +58,7 @@ if ( ! function_exists('force_download'))
}
elseif ($data === NULL)
{
- if (@is_file($filename) && @file_exists($filename) && ($filesize = @filesize($filename)) !== FALSE)
+ if (@is_file($filename) && ($filesize = @filesize($filename)) !== FALSE)
{
$filepath = $filename;
$filename = explode('/', str_replace(DIRECTORY_SEPARATOR, '/', $filename));
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index f343b6c71..692909c79 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -228,13 +228,10 @@ if ( ! function_exists('form_upload'))
*/
function form_upload($data = '', $value = '', $extra = '')
{
- if ( ! is_array($data))
- {
- $data = array('name' => $data);
- }
-
+ $defaults = array('type' => 'file', 'name' => '');
+ is_array($data) OR $data = array('name' => $data);
$data['type'] = 'file';
- return form_input($data, $value, $extra);
+ return '<input '._parse_form_attributes($data, $defaults).$extra." />\n";
}
}
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index 2d474169b..80a27876f 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -238,26 +238,30 @@ if ( ! function_exists('doctype'))
*/
function doctype($type = 'xhtml1-strict')
{
- global $_doctypes;
+ static $doctypes;
- if ( ! is_array($_doctypes))
+ if ( ! is_array($doctypes))
{
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php'))
+ if (file_exists(APPPATH.'config/doctypes.php'))
{
- include(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php');
+ include(APPPATH.'config/doctypes.php');
}
- elseif (is_file(APPPATH.'config/doctypes.php'))
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php'))
{
- include(APPPATH.'config/doctypes.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/doctypes.php');
}
- if ( ! is_array($_doctypes))
+ if (empty($_doctypes) OR ! is_array($_doctypes))
{
+ $doctypes = array();
return FALSE;
}
+
+ $doctypes = $_doctypes;
}
- return isset($_doctypes[$type]) ? $_doctypes[$type] : FALSE;
+ return isset($doctypes[$type]) ? $doctypes[$type] : FALSE;
}
}
diff --git a/system/helpers/smiley_helper.php b/system/helpers/smiley_helper.php
index 186b24ce9..d9a693493 100644
--- a/system/helpers/smiley_helper.php
+++ b/system/helpers/smiley_helper.php
@@ -213,16 +213,30 @@ if ( ! function_exists('_get_smiley_array'))
*/
function _get_smiley_array()
{
- if (defined('ENVIRONMENT') && file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'))
- {
- include(APPPATH.'config/'.ENVIRONMENT.'/smileys.php');
- }
- elseif (file_exists(APPPATH.'config/smileys.php'))
+ static $_smileys;
+
+ if ( ! is_array($smileys))
{
- include(APPPATH.'config/smileys.php');
+ if (file_exists(APPPATH.'config/smileys.php'))
+ {
+ include(APPPATH.'config/smileys.php');
+ }
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/smileys.php'))
+ {
+ include(APPPATH.'config/'.ENVIRONMENT.'/smileys.php');
+ }
+
+ if (empty($smileys) OR ! is_array($smileys))
+ {
+ $_smileys = array();
+ return FALSE;
+ }
+
+ $_smileys = $smileys;
}
- return (isset($smileys) && is_array($smileys)) ? $smileys : FALSE;
+ return $_smileys;
}
}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index 1c7eeaf5f..54db14f94 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -358,31 +358,35 @@ if ( ! function_exists('convert_accented_characters'))
/**
* Convert Accented Foreign Characters to ASCII
*
- * @param string the text string
+ * @param string $str Input string
* @return string
*/
function convert_accented_characters($str)
{
- global $foreign_characters;
+ static $_foreign_characters;
- if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
+ if ( ! is_array($_foreign_characters))
{
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
+ if (file_exists(APPPATH.'config/foreign_chars.php'))
{
- include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
+ include(APPPATH.'config/foreign_chars.php');
}
- elseif (is_file(APPPATH.'config/foreign_chars.php'))
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php'))
{
- include(APPPATH.'config/foreign_chars.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/foreign_chars.php');
}
- if ( ! isset($foreign_characters) OR ! is_array($foreign_characters))
+ if (empty($foreign_characters) OR ! is_array($foreign_characters))
{
+ $_foreign_characters = array();
return $str;
}
+
+ $_foreign_characters = $foreign_characters;
}
- return preg_replace(array_keys($foreign_characters), array_values($foreign_characters), $str);
+ return preg_replace(array_keys($_foreign_characters), array_values($_foreign_characters), $str);
}
}
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index 9a0153542..d6bf7e2c9 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -384,22 +384,23 @@ if ( ! function_exists('auto_link'))
function auto_link($str, $type = 'both', $popup = FALSE)
{
// Find and replace any URLs.
- if ($type !== 'email' && preg_match_all('#\b(([\w-]+://?|www\.)[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))#', $str, $matches, PREG_OFFSET_CAPTURE))
+ if ($type !== 'email' && preg_match_all('#(\w*://|www\.)[^\s()<>;]+\w#i', $str, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER))
{
// Set our target HTML if using popup links.
- $target = ($popup) ? 'target="_blank"' : '';
+ $target = ($popup) ? ' target="_blank"' : '';
// We process the links in reverse order (last -> first) so that
// the returned string offsets from preg_match_all() are not
// moved as we add more HTML.
- foreach (array_reverse($matches[0]) as $match)
+ foreach (array_reverse($matches) as $match)
{
- // $match is an array generated by the PREG_OFFSET_CAPTURE flag.
- // $match[0] is the matched string, $match[1] is the string offset.
-
- $anchor = anchor($match[0], '', $target);
-
- $str = substr_replace($str, $anchor, $match[1], strlen($match[0]));
+ // $match[0] is the matched string/link
+ // $match[1] is either a protocol prefix or 'www.'
+ //
+ // With PREG_OFFSET_CAPTURE, both of the above is an array,
+ // where the actual value is held in [0] and its offset at the [1] index.
+ $a = '<a href="'.(strpos($match[1][0], '/') ? '' : 'http://').$match[0][0].'"'.$target.'>'.$match[0][0].'</a>';
+ $str = substr_replace($str, $a, $match[0][1], strlen($match[0][0]));
}
}
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 3fb007dd2..7c0277c25 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -37,6 +37,7 @@ $lang['form_validation_max_length'] = 'The {field} field cannot exceed {param}
$lang['form_validation_exact_length'] = 'The {field} field must be exactly {param} characters in length.';
$lang['form_validation_alpha'] = 'The {field} field may only contain alphabetical characters.';
$lang['form_validation_alpha_numeric'] = 'The {field} field may only contain alpha-numeric characters.';
+$lang['form_validation_alpha_numeric_spaces'] = 'The {field} field may only contain alpha-numeric characters and spaces.';
$lang['form_validation_alpha_dash'] = 'The {field} field may only contain alpha-numeric characters, underscores, and dashes.';
$lang['form_validation_numeric'] = 'The {field} field must contain only numbers.';
$lang['form_validation_is_numeric'] = 'The {field} field must contain only numeric characters.';
diff --git a/system/language/english/profiler_lang.php b/system/language/english/profiler_lang.php
index dfe034e79..0ed5f4cb0 100644
--- a/system/language/english/profiler_lang.php
+++ b/system/language/english/profiler_lang.php
@@ -46,6 +46,7 @@ $lang['profiler_no_memory'] = 'Memory Usage Unavailable';
$lang['profiler_no_profiles'] = 'No Profile data - all Profiler sections have been disabled.';
$lang['profiler_section_hide'] = 'Hide';
$lang['profiler_section_show'] = 'Show';
+$lang['profiler_seconds'] = 'seconds';
/* End of file profiler_lang.php */
/* Location: ./system/language/english/profiler_lang.php */ \ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index 8096b2650..246a7a264 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -182,11 +182,11 @@ class CI_Cache_memcached extends CI_Driver {
}
}
- if (class_exists('Memcached'))
+ if (class_exists('Memcached', FALSE))
{
$this->_memcached = new Memcached();
}
- elseif (class_exists('Memcache'))
+ elseif (class_exists('Memcache', FALSE))
{
$this->_memcached = new Memcache();
}
diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php
index 8734d7774..b7b0697fb 100644
--- a/system/libraries/Cart.php
+++ b/system/libraries/Cart.php
@@ -95,7 +95,7 @@ class CI_Cart {
$config = is_array($params) ? $params : array();
// Load the Sessions class
- $this->CI->load->library('session', $config);
+ $this->CI->load->driver('session', $config);
// Grab the shopping cart array from the session table
$this->_cart_contents = $this->CI->session->userdata('cart_contents');
@@ -365,7 +365,7 @@ class CI_Cart {
*/
protected function _save_cart()
{
- // Lets add up the individual prices and set the cart sub-total
+ // Let's add up the individual prices and set the cart sub-total
$this->_cart_contents['total_items'] = $this->_cart_contents['cart_total'] = 0;
foreach ($this->_cart_contents as $key => $val)
{
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index bb7318991..ba15f81df 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -80,8 +80,7 @@ class CI_Driver_Library {
public function load_driver($child)
{
// Get CodeIgniter instance and subclass prefix
- $CI = get_instance();
- $prefix = (string) $CI->config->item('subclass_prefix');
+ $prefix = config_item('subclass_prefix');
if ( ! isset($this->lib_name))
{
@@ -102,11 +101,12 @@ class CI_Driver_Library {
}
// Get package paths and filename case variations to search
+ $CI = get_instance();
$paths = $CI->load->get_package_paths(TRUE);
// Is there an extension?
$class_name = $prefix.$child_name;
- $found = class_exists($class_name);
+ $found = class_exists($class_name, FALSE);
if ( ! $found)
{
// Check for subclass file
@@ -126,8 +126,8 @@ class CI_Driver_Library {
}
// Include both sources and mark found
- include($basepath);
- include($file);
+ include_once($basepath);
+ include_once($file);
$found = TRUE;
break;
}
@@ -139,8 +139,7 @@ class CI_Driver_Library {
{
// Use standard class name
$class_name = 'CI_'.$child_name;
- $found = class_exists($class_name);
- if ( ! $found)
+ if ( ! class_exists($class_name, FALSE))
{
// Check package paths
foreach ($paths as $path)
@@ -150,7 +149,7 @@ class CI_Driver_Library {
if (file_exists($file))
{
// Include source
- include($file);
+ include_once($file);
break;
}
}
@@ -158,9 +157,9 @@ class CI_Driver_Library {
}
// Did we finally find the class?
- if ( ! class_exists($class_name))
+ if ( ! class_exists($class_name, FALSE))
{
- if (class_exists($child_name))
+ if (class_exists($child_name, FALSE))
{
$class_name = $child_name;
}
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 997757b0a..daa38484b 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -96,6 +96,13 @@ class CI_Email {
public $smtp_timeout = 5;
/**
+ * SMTP persistent connection
+ *
+ * @var bool
+ */
+ public $smtp_keepalive = FALSE;
+
+ /**
* SMTP Encryption
*
* @var string NULL, 'tls' or 'ssl'
@@ -403,6 +410,21 @@ class CI_Email {
// --------------------------------------------------------------------
/**
+ * Destructor - Releases Resources
+ *
+ * @return void
+ */
+ public function __destruct()
+ {
+ if (is_resource($this->_smtp_connect))
+ {
+ $this->_send_command('quit');
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Initialize preferences
*
* @param array
@@ -1183,8 +1205,11 @@ class CI_Email {
{
if ($this->protocol === 'mail')
{
- $this->_subject = $this->_headers['Subject'];
- unset($this->_headers['Subject']);
+ if (isset($this->_headers['Subject']))
+ {
+ $this->_subject = $this->_headers['Subject'];
+ unset($this->_headers['Subject']);
+ }
}
reset($this->_headers);
@@ -1824,7 +1849,15 @@ class CI_Email {
return FALSE;
}
- $this->_send_command('quit');
+ if ($this->smtp_keepalive)
+ {
+ $this->_send_command('reset');
+ }
+ else
+ {
+ $this->_send_command('quit');
+ }
+
return TRUE;
}
@@ -1837,6 +1870,11 @@ class CI_Email {
*/
protected function _smtp_connect()
{
+ if (is_resource($this->_smtp_connect))
+ {
+ return TRUE;
+ }
+
$ssl = ($this->smtp_crypto === 'ssl') ? 'ssl://' : NULL;
$this->_smtp_connect = fsockopen($ssl.$this->smtp_host,
@@ -1851,6 +1889,7 @@ class CI_Email {
return FALSE;
}
+ stream_set_timeout($this->_smtp_connect, $this->smtp_timeout);
$this->_set_error_message($this->_get_smtp_data());
if ($this->smtp_crypto === 'tls')
@@ -1924,6 +1963,11 @@ class CI_Email {
$this->_send_data('DATA');
$resp = 354;
break;
+ case 'reset':
+
+ $this->_send_data('RSET');
+ $resp = 250;
+ break;
case 'quit' :
$this->_send_data('QUIT');
@@ -1973,6 +2017,11 @@ class CI_Email {
$reply = $this->_get_smtp_data();
+ if (strpos($reply, '503') !== 0) // Already authenticated
+ {
+ return TRUE;
+ }
+
if (strpos($reply, '334') !== 0)
{
$this->_set_error_message('lang:email_failed_smtp_login', $reply);
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index bbd0b523e..172e799f6 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -356,7 +356,7 @@ class CI_Form_validation {
*/
public function error_string($prefix = '', $suffix = '')
{
- // No errrors, validation passes!
+ // No errors, validation passes!
if (count($this->_error_array) === 0)
{
return '';
@@ -517,7 +517,7 @@ class CI_Form_validation {
{
if (isset($_POST[$row['field']]))
{
- $_POST[$row['field']] = $this->prep_for_form($row['postdata']);
+ $_POST[$row['field']] = $row['postdata'];
}
}
else
@@ -543,14 +543,14 @@ class CI_Form_validation {
$array = array();
foreach ($row['postdata'] as $k => $v)
{
- $array[$k] = $this->prep_for_form($v);
+ $array[$k] = $v;
}
$post_ref = $array;
}
else
{
- $post_ref = $this->prep_for_form($row['postdata']);
+ $post_ref = $row['postdata'];
}
}
}
@@ -1232,6 +1232,19 @@ class CI_Form_validation {
// --------------------------------------------------------------------
/**
+ * Alpha-numeric w/ spaces
+ *
+ * @param string
+ * @return bool
+ */
+ public function alpha_numeric_spaces($str)
+ {
+ return (bool) preg_match('/^[A-Z0-9 ]+$/i', $str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Alpha-numeric with underscores and dashes
*
* @param string
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 6d5493696..0cec43fc4 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -810,7 +810,7 @@ class CI_Image_lib {
imagedestroy($dst_img);
imagedestroy($src_img);
- // Set the file to 777
+ // Set the file to 666
@chmod($this->full_dst_path, FILE_WRITE_MODE);
return TRUE;
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index 7f1d85511..773a58384 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -69,7 +69,7 @@ class CI_Javascript {
$this->CI =& get_instance();
// load the requested js library
- $this->CI->load->library('javascript/'.$js_library_driver, array('autoload' => $autoload));
+ $this->CI->load->library('Javascript/'.$js_library_driver, array('autoload' => $autoload));
// make js to refer to current library
$this->js =& $this->CI->$js_library_driver;
diff --git a/system/libraries/javascript/Jquery.php b/system/libraries/Javascript/Jquery.php
index b6e0434b2..b6e0434b2 100644
--- a/system/libraries/javascript/Jquery.php
+++ b/system/libraries/Javascript/Jquery.php
diff --git a/system/libraries/javascript/index.html b/system/libraries/Javascript/index.html
index c942a79ce..c942a79ce 100644
--- a/system/libraries/javascript/index.html
+++ b/system/libraries/Javascript/index.html
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
index fd915c382..cc6fe48f0 100644
--- a/system/libraries/Migration.php
+++ b/system/libraries/Migration.php
@@ -104,8 +104,8 @@ class CI_Migration {
*/
public function __construct($config = array())
{
- # Only run this constructor on main library load
- if (get_parent_class($this) !== FALSE)
+ // Only run this constructor on main library load
+ if ( ! in_array(get_class($this), array('CI_Migration', config_item('subclass_prefix').'Migration'), TRUE))
{
return;
}
@@ -228,7 +228,7 @@ class CI_Migration {
$class = 'Migration_'.ucfirst(strtolower($this->_get_migration_name(basename($file, '.php'))));
// Validate the migration file structure
- if ( ! class_exists($class))
+ if ( ! class_exists($class, FALSE))
{
$this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
return FALSE;
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index d139980d8..10fb29dbd 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -133,7 +133,7 @@ class CI_Pagination {
*
* @var int
*/
- protected $uri_segment = 3;
+ protected $uri_segment = 0;
/**
* Full tag open
@@ -318,11 +318,9 @@ class CI_Pagination {
*/
public function initialize($params = array())
{
- $attributes = array();
-
if (isset($params['attributes']) && is_array($params['attributes']))
{
- $attributes = $params['attributes'];
+ $this->_parse_attributes($params['attributes']);
unset($params['attributes']);
}
@@ -334,8 +332,6 @@ class CI_Pagination {
unset($params['anchor_class']);
}
- $this->_parse_attributes($attributes);
-
if (count($params) > 0)
{
foreach ($params as $key => $val)
@@ -372,45 +368,119 @@ class CI_Pagination {
return '';
}
- // Set the base page index for starting page number
- $base_page = ($this->use_page_numbers) ? 1 : 0;
+ // Check the user defined number of links.
+ $this->num_links = (int) $this->num_links;
+
+ if ($this->num_links < 1)
+ {
+ show_error('Your number of links must be a positive number.');
+ }
- // Determine the current page number.
$CI =& get_instance();
- // See if we are using a prefix or suffix on links
- if ($this->prefix !== '' OR $this->suffix !== '')
+ // Keep any existing query string items.
+ // Note: Has nothing to do with any other query string option.
+ if ($this->reuse_query_string === TRUE)
{
- $this->cur_page = (int) str_replace(array($this->prefix, $this->suffix), '', $CI->uri->rsegment($this->uri_segment));
+ $get = $CI->input->get();
+
+ // Unset the controll, method, old-school routing options
+ unset($get['c'], $get['m'], $get[$this->query_string_segment]);
+ }
+ else
+ {
+ $get = array();
}
+ // Put together our base and first URLs.
+ $this->base_url = trim($this->base_url);
+
+ $query_string = '';
+ $query_string_sep = (strpos($this->base_url, '?') === FALSE) ? '?' : '&amp;';
+
+ // Are we using query strings?
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
- if ($CI->input->get($this->query_string_segment) != $base_page)
+ // If a custom first_url hasn't been specified, we'll create one from
+ // the base_url, but without the page item.
+ if ($this->first_url === '')
{
- $this->cur_page = (int) $CI->input->get($this->query_string_segment);
+ $this->first_url = $this->base_url;
+
+ // If we saved any GET items earlier, make sure they're appended.
+ if ( ! empty($get))
+ {
+ $this->first_url .= $query_string_sep.http_build_query($get);
+ }
}
+
+ // Add the page segment to the end of the query string, where the
+ // page number will be appended.
+ $this->base_url .= $query_string_sep.http_build_query(array_merge($get, array($this->query_string_segment => '')));
}
- elseif ( ! $this->cur_page && $CI->uri->segment($this->uri_segment) !== $base_page)
+ else
{
- $this->cur_page = (int) $CI->uri->rsegment($this->uri_segment);
+ // Standard segment mode.
+ // Generate our saved query string to append later after the page number.
+ if ( ! empty($get))
+ {
+ $query_string = $query_string_sep.http_build_query($get);
+ $this->suffix .= $query_string;
+ }
+
+ // Does the base_url have the query string in it?
+ // If we're supposed to save it, remove it so we can append it later.
+ if ($this->reuse_query_string === TRUE && ($base_query_pos = strpos($this->base_url, '?')) !== FALSE)
+ {
+ $this->base_url = substr($this->base_url, 0, $base_query_pos);
+ }
+
+ if ($this->first_url === '')
+ {
+ $this->first_url = $this->base_url.$query_string;
+ }
+
+ $this->base_url = rtrim($this->base_url, '/').'/';
}
- // Set current page to 1 if it's not valid or if using page numbers instead of offset
- if ( ! is_numeric($this->cur_page) OR ($this->use_page_numbers && $this->cur_page === 0))
+ // Determine the current page number.
+ $base_page = ($this->use_page_numbers) ? 1 : 0;
+
+ // Are we using query strings?
+ if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
- $this->cur_page = $base_page;
+ $this->cur_page = $CI->input->get($this->query_string_segment);
}
+ else
+ {
+ // Default to the last segment number if one hasn't been defined.
+ if ($this->uri_segment === 0)
+ {
+ $this->uri_segment = count($CI->uri->segment_array());
+ }
- $this->num_links = (int) $this->num_links;
+ $this->cur_page = $CI->uri->segment($this->uri_segment);
- if ($this->num_links < 1)
+ // Remove any specified prefix/suffix from the segment.
+ if ($this->prefix !== '' OR $this->suffix !== '')
+ {
+ $this->cur_page = str_replace(array($this->prefix, $this->suffix), '', $this->cur_page);
+ }
+ }
+
+ // If something isn't quite right, back to the default base page.
+ if ( ! ctype_digit($this->cur_page) OR ($this->use_page_numbers && (int) $this->cur_page === 0))
{
- show_error('Your number of links must be a positive number.');
+ $this->cur_page = $base_page;
+ }
+ else
+ {
+ // Make sure we're using integers for comparisons later.
+ $this->cur_page = (int) $this->cur_page;
}
// Is the page number beyond the result range?
- // If so we show the last page
+ // If so, we show the last page.
if ($this->use_page_numbers)
{
if ($this->cur_page > $num_pages)
@@ -425,80 +495,47 @@ class CI_Pagination {
$uri_page_number = $this->cur_page;
+ // If we're using offset instead of page numbers, convert it
+ // to a page number, so we can generate the surrounding number links.
if ( ! $this->use_page_numbers)
{
$this->cur_page = (int) floor(($this->cur_page/$this->per_page) + 1);
}
// Calculate the start and end numbers. These determine
- // which number to start and end the digit links with
+ // which number to start and end the digit links with.
$start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
$end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;
- // Is pagination being used over GET or POST? If get, add a per_page query
- // string. If post, add a trailing slash to the base URL if needed
- if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
- {
- $segment = (strpos($this->base_url, '?')) ? '&amp;' : '?';
- $this->base_url = rtrim($this->base_url).$segment.$this->query_string_segment.'=';
- }
- else
- {
- $this->base_url = rtrim($this->base_url, '/') .'/';
- }
-
// And here we go...
$output = '';
- $query_string = '';
-
- // Add anything in the query string back to the links
- // Note: Nothing to do with query_string_segment or any other query string options
- if ($this->reuse_query_string === TRUE)
- {
- $get = $CI->input->get();
-
- // Unset the controll, method, old-school routing options
- unset($get['c'], $get['m'], $get[$this->query_string_segment]);
- if ( ! empty($get))
- {
- // Put everything else onto the end
- $query_string = (strpos($this->base_url, '?') !== FALSE ? '&amp;' : '?')
- .http_build_query($get, '', '&amp;');
-
- // Add this after the suffix to put it into more links easily
- $this->suffix .= $query_string;
- }
- }
-
- // Render the "First" link
+ // Render the "First" link.
if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1))
{
- $first_url = ($this->first_url === '') ? $this->base_url : $this->first_url;
-
- // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
+ // Take the general parameters, and squeeze this pagination-page attr in for JS frameworks.
$attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, 1);
- $output .= $this->first_tag_open.'<a href="'.$first_url.'"'.$attributes.$this->_attr_rel('start').'>'
+ $output .= $this->first_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('start').'>'
.$this->first_link.'</a>'.$this->first_tag_close;
}
- // Render the "previous" link
+ // Render the "Previous" link.
if ($this->prev_link !== FALSE && $this->cur_page !== 1)
{
$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
- // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
$attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
- if ($i === $base_page && $this->first_url !== '')
+ if ($i === $base_page)
{
- $output .= $this->prev_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$attributes.$this->_attr_rel('prev').'>'
+ // First page
+ $output .= $this->prev_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('prev').'>'
.$this->prev_link.'</a>'.$this->prev_tag_close;
}
else
{
- $append = ($i === $base_page) ? $query_string : $this->prefix.$i.$this->suffix;
+ $append = $this->prefix.$i.$this->suffix;
$output .= $this->prev_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('prev').'>'
.$this->prev_link.'</a>'.$this->prev_tag_close;
}
@@ -513,29 +550,26 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $loop : ($loop * $this->per_page) - $this->per_page;
- // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
$attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
if ($i >= $base_page)
{
if ($this->cur_page === $loop)
{
- $output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
+ // Current page
+ $output .= $this->cur_tag_open.$loop.$this->cur_tag_close;
+ }
+ elseif ($i === $base_page)
+ {
+ // First page
+ $output .= $this->num_tag_open.'<a href="'.$this->first_url.'"'.$attributes.$this->_attr_rel('start').'>'
+ .$loop.'</a>'.$this->num_tag_close;
}
else
{
- $n = ($i === $base_page) ? '' : $i;
- if ($n === '' && ! empty($this->first_url))
- {
- $output .= $this->num_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$attributes.$this->_attr_rel('start').'>'
- .$loop.'</a>'.$this->num_tag_close;
- }
- else
- {
- $append = ($n === '') ? $query_string : $this->prefix.$n.$this->suffix;
- $output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('start').'>'
- .$loop.'</a>'.$this->num_tag_close;
- }
+ $append = $this->prefix.$i.$this->suffix;
+ $output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$attributes.$this->_attr_rel('start').'>'
+ .$loop.'</a>'.$this->num_tag_close;
}
}
}
@@ -546,7 +580,6 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $this->cur_page + 1 : $this->cur_page * $this->per_page;
- // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
$attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
$output .= $this->next_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes
@@ -558,7 +591,6 @@ class CI_Pagination {
{
$i = ($this->use_page_numbers) ? $num_pages : ($num_pages * $this->per_page) - $this->per_page;
- // Take the general parameters, and squeeze this pagination-page attr in there for JS fw's
$attributes = sprintf('%s %s="%d"', $this->_attributes, $this->data_page_attr, (int) $i);
$output .= $this->last_tag_open.'<a href="'.$this->base_url.$this->prefix.$i.$this->suffix.'"'.$attributes.'>'
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index e93239901..470688fdc 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -238,6 +238,7 @@ class CI_Profiler {
foreach ($dbs as $name => $db)
{
$hide_queries = (count($db->queries) > $this->_query_toggle_count) ? ' display:none' : '';
+ $total_time = number_format(array_sum($db->query_times), 4).' '.$this->CI->lang->line('profiler_seconds');
$show_hide_js = '(<span style="cursor: pointer;" onclick="var s=document.getElementById(\'ci_profiler_queries_db_'.$count.'\').style;s.display=s.display==\'none\'?\'\':\'none\';this.innerHTML=this.innerHTML==\''.$this->CI->lang->line('profiler_section_hide').'\'?\''.$this->CI->lang->line('profiler_section_show').'\':\''.$this->CI->lang->line('profiler_section_hide').'\';">'.$this->CI->lang->line('profiler_section_hide').'</span>)';
@@ -250,7 +251,7 @@ class CI_Profiler {
."\n"
.'<legend style="color:#0000FF;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_database')
.':&nbsp; '.$db->database.' ('.$name.')&nbsp;&nbsp;&nbsp;'.$this->CI->lang->line('profiler_queries')
- .': '.count($db->queries).'&nbsp;&nbsp;'.$show_hide_js."</legend>\n\n\n"
+ .': '.count($db->queries).' ('.$total_time.')&nbsp;&nbsp;'.$show_hide_js."</legend>\n\n\n"
.'<table style="width:100%;'.$hide_queries.'" id="ci_profiler_queries_db_'.$count."\">\n";
if (count($db->queries) === 0)
diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php
index 474641642..057e5a1d1 100644
--- a/system/libraries/Session/drivers/Session_cookie.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -602,6 +602,9 @@ class CI_Session_cookie extends CI_Session_driver {
$set['user_data'] = $this->_serialize($userdata);
}
+ // Reset query builder values.
+ $this->CI->db->reset_query();
+
// Run the update query
// Any time we change the session id, it gets updated immediately,
// so our where clause below is always safe
@@ -805,7 +808,7 @@ class CI_Session_cookie extends CI_Session_driver {
{
if (is_string($val))
{
- $val= str_replace('{{slash}}', '\\', $val);
+ $val = str_replace('{{slash}}', '\\', $val);
}
}
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 96bb17edc..1c14f99ed 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -430,7 +430,7 @@ class CI_Upload {
}
else
{
- // An extension was provided, lets have it!
+ // An extension was provided, let's have it!
$this->file_ext = $this->get_extension($this->_file_name_override);
}
@@ -463,7 +463,8 @@ class CI_Upload {
}
// Sanitize the file name for security
- $this->file_name = $this->clean_file_name($this->file_name);
+ $CI =& get_instance();
+ $this->file_name = $CI->security->sanitize_filename($this->file_name);
// Truncate the file name if it's too long
if ($this->max_filename > 0)
@@ -971,46 +972,6 @@ class CI_Upload {
// --------------------------------------------------------------------
/**
- * Clean the file name for security
- *
- * @param string $filename
- * @return string
- */
- public function clean_file_name($filename)
- {
- $bad = array(
- '<!--', '-->',
- "'", '"',
- '<', '>',
- '&', '$',
- '=',
- ';',
- '?',
- '/',
- '!',
- '#',
- '%20',
- '%22',
- '%3c', // <
- '%253c', // <
- '%3e', // >
- '%0e', // >
- '%28', // (
- '%29', // )
- '%2528', // (
- '%26', // &
- '%24', // $
- '%3f', // ?
- '%3b', // ;
- '%3d' // =
- );
-
- return stripslashes(str_replace($bad, '', $filename));
- }
-
- // --------------------------------------------------------------------
-
- /**
* Limit the File Name Length
*
* @param string $filename
@@ -1089,7 +1050,7 @@ class CI_Upload {
// <a, <body, <head, <html, <img, <plaintext, <pre, <script, <table, <title
// title is basically just in SVG, but we filter it anyhow
- // if its an image or no "triggers" detected in the first 256 bytes - we're good
+ // if it's an image or no "triggers" detected in the first 256 bytes - we're good
return ! preg_match('/<(a|body|head|html|img|plaintext|pre|script|table|title)[\s>]/i', $opening_bytes);
}
@@ -1251,7 +1212,7 @@ class CI_Upload {
* Notes:
* - the DIRECTORY_SEPARATOR comparison ensures that we're not on a Windows system
* - many system admins would disable the exec(), shell_exec(), popen() and similar functions
- * due to security concerns, hence the function_exists() checks
+ * due to security concerns, hence the function_usable() checks
*/
if (DIRECTORY_SEPARATOR !== '\\')
{
@@ -1262,7 +1223,7 @@ class CI_Upload {
if (function_usable('exec'))
{
/* This might look confusing, as $mime is being populated with all of the output when set in the second parameter.
- * However, we only neeed the last line, which is the actual return value of exec(), and as such - it overwrites
+ * However, we only need the last line, which is the actual return value of exec(), and as such - it overwrites
* anything that could already be set for $mime previously. This effectively makes the second parameter a dummy
* value, which is only put to allow us to get the return status code.
*/
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 1f4b2fa52..2f6f81909 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -175,15 +175,18 @@ class CI_User_agent {
*/
protected function _load_agent_file()
{
- if (defined('ENVIRONMENT') && is_file(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))
+ if (($found = file_exists(APPPATH.'config/user_agents.php')))
{
- include(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php');
+ include(APPPATH.'config/user_agents.php');
}
- elseif (is_file(APPPATH.'config/user_agents.php'))
+
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php'))
{
- include(APPPATH.'config/user_agents.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/user_agents.php');
+ $found = TRUE;
}
- else
+
+ if ($found !== TRUE)
{
return FALSE;
}
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index 465a1967b..2d2e7f13b 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -31,7 +31,7 @@ if ( ! function_exists('xml_parser_create'))
show_error('Your PHP installation does not support XML');
}
-if ( ! class_exists('CI_Xmlrpc'))
+if ( ! class_exists('CI_Xmlrpc', FALSE))
{
show_error('You must load the Xmlrpc class before loading the Xmlrpcs class in order to create a server.');
}
diff --git a/tests/Bootstrap.php b/tests/Bootstrap.php
index 8ce80b3fd..c98d88531 100644
--- a/tests/Bootstrap.php
+++ b/tests/Bootstrap.php
@@ -32,6 +32,7 @@ if ( ! class_exists('vfsStream') && file_exists(PROJECT_BASE.'vendor/autoload.ph
defined('BASEPATH') OR define('BASEPATH', vfsStream::url('system/'));
defined('APPPATH') OR define('APPPATH', vfsStream::url('application/'));
defined('VIEWPATH') OR define('VIEWPATH', APPPATH.'views/');
+defined('ENVIRONMENT') OR define('ENVIRONMENT', 'development');
// Set localhost "remote" IP
isset($_SERVER['REMOTE_ADDR']) OR $_SERVER['REMOTE_ADDR'] = '127.0.0.1';
diff --git a/tests/codeigniter/core/Input_test.php b/tests/codeigniter/core/Input_test.php
index ca1c6dfd7..5cf25fefa 100644
--- a/tests/codeigniter/core/Input_test.php
+++ b/tests/codeigniter/core/Input_test.php
@@ -95,8 +95,8 @@ class Input_test extends CI_TestCase {
public function test_cookie()
{
$_COOKIE['foo'] = 'bar';
-
$this->assertEquals('bar', $this->input->cookie('foo'));
+ $this->assertNull($this->input->cookie('bar'));
}
// --------------------------------------------------------------------
@@ -138,4 +138,27 @@ class Input_test extends CI_TestCase {
}
}
+ // --------------------------------------------------------------------
+
+ public function test_method()
+ {
+ $_SERVER['REQUEST_METHOD'] = 'GET';
+ $this->assertEquals('get', $this->input->method());
+ $this->assertEquals('GET', $this->input->method(TRUE));
+ $_SERVER['REQUEST_METHOD'] = 'POST';
+ $this->assertEquals('post', $this->input->method());
+ $this->assertEquals('POST', $this->input->method(TRUE));
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_is_ajax_request()
+ {
+ $this->assertFalse($this->input->is_ajax_request());
+ $_SERVER['HTTP_X_REQUESTED_WITH'] = 'test';
+ $this->assertFalse($this->input->is_ajax_request());
+ $_SERVER['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest';
+ $this->assertTrue($this->input->is_ajax_request());
+ }
+
} \ No newline at end of file
diff --git a/tests/codeigniter/core/Loader_test.php b/tests/codeigniter/core/Loader_test.php
index ecc5ca933..dea01a555 100644
--- a/tests/codeigniter/core/Loader_test.php
+++ b/tests/codeigniter/core/Loader_test.php
@@ -25,7 +25,7 @@ class Loader_test extends CI_TestCase {
// Create library in VFS
$lib = 'unit_test_lib';
$class = 'CI_'.ucfirst($lib);
- $this->ci_vfs_create($lib, '<?php class '.$class.' { }', $this->ci_base_root, 'libraries');
+ $this->ci_vfs_create(ucfirst($lib), '<?php class '.$class.' { }', $this->ci_base_root, 'libraries');
// Test is_loaded fail
$this->assertFalse($this->load->is_loaded($lib));
@@ -48,7 +48,7 @@ class Loader_test extends CI_TestCase {
// Test non-existent class
$this->setExpectedException(
'RuntimeException',
- 'CI Error: Non-existent class: '.$lib
+ 'CI Error: Unable to load the requested class: '.ucfirst($lib)
);
$this->assertNull($this->load->library($lib));
}
@@ -105,7 +105,7 @@ class Loader_test extends CI_TestCase {
$lib = 'unit_test_config_lib';
$class = 'CI_'.ucfirst($lib);
$content = '<?php class '.$class.' { public function __construct($params) { $this->config = $params; } }';
- $this->ci_vfs_create($lib, $content, $this->ci_base_root, 'libraries');
+ $this->ci_vfs_create(ucfirst($lib), $content, $this->ci_base_root, 'libraries');
// Create config file
$cfg = array(
@@ -133,7 +133,7 @@ class Loader_test extends CI_TestCase {
// Create library in VFS
$lib = 'super_test_library';
$class = ucfirst($lib);
- $this->ci_vfs_create($lib, '<?php class '.$class.' { }', $this->ci_app_root, 'libraries');
+ $this->ci_vfs_create(ucfirst($lib), '<?php class '.$class.' { }', $this->ci_app_root, 'libraries');
// Load library
$this->assertNull($this->load->library($lib));
@@ -152,7 +152,7 @@ class Loader_test extends CI_TestCase {
$dir = ucfirst($driver);
$class = 'CI_'.$dir;
$content = '<?php class '.$class.' { } ';
- $this->ci_vfs_create($driver, $content, $this->ci_base_root, 'libraries/'.$dir);
+ $this->ci_vfs_create(ucfirst($driver), $content, $this->ci_base_root, 'libraries/'.$dir);
// Test loading as an array.
$this->assertNull($this->load->driver(array($driver)));
@@ -410,7 +410,7 @@ class Loader_test extends CI_TestCase {
$dir = 'third-party';
$lib = 'unit_test_package';
$class = 'CI_'.ucfirst($lib);
- $this->ci_vfs_create($lib, '<?php class '.$class.' { }', $this->ci_app_root, array($dir, 'libraries'));
+ $this->ci_vfs_create(ucfirst($lib), '<?php class '.$class.' { }', $this->ci_app_root, array($dir, 'libraries'));
// Get paths
$paths = $this->load->get_package_paths(TRUE);
@@ -440,7 +440,7 @@ class Loader_test extends CI_TestCase {
// Test failed load without path
$this->setExpectedException(
'RuntimeException',
- 'CI Error: Unable to load the requested class: '.$lib
+ 'CI Error: Unable to load the requested class: '.ucfirst($lib)
);
$this->load->library($lib);
}
@@ -467,13 +467,13 @@ class Loader_test extends CI_TestCase {
// Create library in VFS
$lib = 'autolib';
$lib_class = 'CI_'.ucfirst($lib);
- $this->ci_vfs_create($lib, '<?php class '.$lib_class.' { }', $this->ci_base_root, 'libraries');
+ $this->ci_vfs_create(ucfirst($lib), '<?php class '.$lib_class.' { }', $this->ci_base_root, 'libraries');
// Create driver in VFS
$drv = 'autodrv';
$subdir = ucfirst($drv);
$drv_class = 'CI_'.$subdir;
- $this->ci_vfs_create($drv, '<?php class '.$drv_class.' { }', $this->ci_base_root, array('libraries', $subdir));
+ $this->ci_vfs_create(ucfirst($drv), '<?php class '.$drv_class.' { }', $this->ci_base_root, array('libraries', $subdir));
// Create model in VFS package path
$dir = 'testdir';
diff --git a/tests/codeigniter/core/Output_test.php b/tests/codeigniter/core/Output_test.php
index 728df3bf6..0eeb93f7b 100644
--- a/tests/codeigniter/core/Output_test.php
+++ b/tests/codeigniter/core/Output_test.php
@@ -3,6 +3,16 @@
class Output_test extends CI_TestCase {
public $output;
+ protected $_output_data = <<<HTML
+<html>
+ <head>
+ <title>Basic HTML</title>
+ </head>
+ <body>
+ Test
+ </body>
+</html>
+HTML;
public function set_up()
{
@@ -13,6 +23,31 @@ class Output_test extends CI_TestCase {
// --------------------------------------------------------------------
+ public function test_set_get_append_output()
+ {
+ $append = "<!-- comment /-->\n";
+
+ $this->assertEquals(
+ $this->_output_data.$append,
+ $this->output
+ ->set_output($this->_output_data)
+ ->append_output("<!-- comment /-->\n")
+ ->get_output()
+ );
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_minify()
+ {
+ $this->assertEquals(
+ str_replace(array("\t", "\n"), '', $this->_output_data),
+ $this->output->minify($this->_output_data)
+ );
+ }
+
+ // --------------------------------------------------------------------
+
public function test_get_content_type()
{
$this->assertEquals('text/html', $this->output->get_content_type());
diff --git a/tests/codeigniter/core/URI_test.php b/tests/codeigniter/core/URI_test.php
index e2deabe51..7fa0e6265 100644
--- a/tests/codeigniter/core/URI_test.php
+++ b/tests/codeigniter/core/URI_test.php
@@ -91,7 +91,7 @@ class URI_test extends CI_TestCase {
public function test_explode_segments()
{
- // Lets test the function's ability to clean up this mess
+ // Let's test the function's ability to clean up this mess
$uris = array(
'test/uri' => array('test', 'uri'),
'/test2/uri2' => array('test2', 'uri2'),
diff --git a/tests/codeigniter/core/Utf8_test.php b/tests/codeigniter/core/Utf8_test.php
new file mode 100644
index 000000000..caa7b6986
--- /dev/null
+++ b/tests/codeigniter/core/Utf8_test.php
@@ -0,0 +1,20 @@
+<?php
+
+class Utf8_test extends CI_TestCase {
+
+ public function set_up()
+ {
+ $this->utf8 = new Mock_Core_Utf8();
+ }
+
+ // --------------------------------------------------------------------
+
+ public function test_convert_to_utf8()
+ {
+ $this->assertEquals(
+ $this->utf8->convert_to_utf8('òåñò', 'WINDOWS-1251'),
+ 'теÑÑ‚'
+ );
+ }
+
+} \ No newline at end of file
diff --git a/tests/codeigniter/helpers/form_helper_test.php b/tests/codeigniter/helpers/form_helper_test.php
index 89165271e..e234f9c83 100644
--- a/tests/codeigniter/helpers/form_helper_test.php
+++ b/tests/codeigniter/helpers/form_helper_test.php
@@ -58,7 +58,7 @@ EOH;
public function test_form_upload()
{
$expected = <<<EOH
-<input type="file" name="attachment" value="" />
+<input type="file" name="attachment" />
EOH;
diff --git a/tests/codeigniter/helpers/url_helper_test.php b/tests/codeigniter/helpers/url_helper_test.php
index 5fc364238..24823a634 100644
--- a/tests/codeigniter/helpers/url_helper_test.php
+++ b/tests/codeigniter/helpers/url_helper_test.php
@@ -48,11 +48,12 @@ class Url_helper_test extends CI_TestCase {
public function test_auto_link_url()
{
$strings = array(
- 'www.codeigniter.com test' => '<a href="http://www.codeigniter.com">http://www.codeigniter.com</a> test',
+ 'www.codeigniter.com test' => '<a href="http://www.codeigniter.com">www.codeigniter.com</a> test',
'This is my noreply@codeigniter.com test' => 'This is my noreply@codeigniter.com test',
- '<br />www.google.com' => '<br /><a href="http://www.google.com">http://www.google.com</a>',
- 'Download CodeIgniter at www.codeigniter.com. Period test.' => 'Download CodeIgniter at <a href="http://www.codeigniter.com">http://www.codeigniter.com</a>. Period test.',
- 'Download CodeIgniter at www.codeigniter.com, comma test' => 'Download CodeIgniter at <a href="http://www.codeigniter.com">http://www.codeigniter.com</a>, comma test'
+ '<br />www.google.com' => '<br /><a href="http://www.google.com">www.google.com</a>',
+ 'Download CodeIgniter at www.codeigniter.com. Period test.' => 'Download CodeIgniter at <a href="http://www.codeigniter.com">www.codeigniter.com</a>. Period test.',
+ 'Download CodeIgniter at www.codeigniter.com, comma test' => 'Download CodeIgniter at <a href="http://www.codeigniter.com">www.codeigniter.com</a>, comma test',
+ 'This one: ://codeigniter.com must not break this one: http://codeigniter.com' => 'This one: <a href="://codeigniter.com">://codeigniter.com</a> must not break this one: <a href="http://codeigniter.com">http://codeigniter.com</a>'
);
foreach ($strings as $in => $out)
@@ -66,7 +67,7 @@ class Url_helper_test extends CI_TestCase {
public function test_pull_675()
{
$strings = array(
- '<br />www.google.com' => '<br /><a href="http://www.google.com">http://www.google.com</a>',
+ '<br />www.google.com' => '<br /><a href="http://www.google.com">www.google.com</a>',
);
foreach ($strings as $in => $out)
diff --git a/tests/codeigniter/libraries/Upload_test.php b/tests/codeigniter/libraries/Upload_test.php
index 1bd8f1430..4d9e4a46e 100644
--- a/tests/codeigniter/libraries/Upload_test.php
+++ b/tests/codeigniter/libraries/Upload_test.php
@@ -208,12 +208,6 @@ class Upload_test extends CI_TestCase {
$this->assertEquals('', $this->upload->get_extension('hello'));
}
- function test_clean_file_name()
- {
- $this->assertEquals('hello.txt', $this->upload->clean_file_name('hello.txt'));
- $this->assertEquals('hello.txt', $this->upload->clean_file_name('%253chell>o.txt'));
- }
-
function test_limit_filename_length()
{
$this->assertEquals('hello.txt', $this->upload->limit_filename_length('hello.txt', 10));
diff --git a/tests/mocks/database/ci_test.sqlite b/tests/mocks/database/ci_test.sqlite
index 44dcef9ec..574d3ae53 100755
--- a/tests/mocks/database/ci_test.sqlite
+++ b/tests/mocks/database/ci_test.sqlite
Binary files differ
diff --git a/tests/mocks/libraries/session.php b/tests/mocks/libraries/session.php
index 562033bbf..adbecb329 100644
--- a/tests/mocks/libraries/session.php
+++ b/tests/mocks/libraries/session.php
@@ -33,4 +33,6 @@ class Mock_Libraries_Session_cookie extends CI_Session_cookie {
$_COOKIE[$name] = $value;
}
}
-} \ No newline at end of file
+}
+
+class Mock_Libraries_Session_native extends CI_Session_native {} \ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 8b9ec2539..216bf80bc 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -38,7 +38,6 @@ Release Date: Not Released
- Updated support for php files in mimes.php.
- Updated support for zip files in mimes.php.
- Updated support for csv files in mimes.php.
- - Added some more doctypes.
- Added Romanian, Greek, Vietnamese and Cyrilic characters in *application/config/foreign_characters.php*.
- Changed logger to only chmod when file is first created.
- Removed previously deprecated SHA1 Library.
@@ -56,16 +55,16 @@ Release Date: Not Released
- Updated *ip_address* database field lengths from 16 to 45 for supporting IPv6 address on :doc:`Trackback Library <libraries/trackback>` and :doc:`Captcha Helper <helpers/captcha_helper>`.
- Removed *cheatsheets* and *quick_reference* PDFs from the documentation.
- Added availability checks where usage of dangerous functions like ``eval()`` and ``exec()`` is required.
+ - Added support for changing the file extension of log files using ``$config['log_file_extension']``.
- Helpers
- :doc:`Date Helper <helpers/date_helper>` changes include:
- - ``now()`` now works with all timezone strings supported by PHP.
- - Added an optional third parameter to ``timespan()`` that constrains the number of time units displayed.
- - Added an optional parameter to ``timezone_menu()`` that allows more attributes to be added to the generated select tag.
+ - :php:func:`now()` now works with all timezone strings supported by PHP.
+ - Added an optional third parameter to :php:func:`timespan()` that constrains the number of time units displayed.
+ - Added an optional parameter to :php:func:`timezone_menu()` that allows more attributes to be added to the generated select tag.
- Deprecated ``standard_date()``, which now just uses the native ``date()`` with `DateTime constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_.
- - Added function ``date_range()`` that generates a list of dates between a specified period.
- - ``create_captcha()`` accepts additional colors parameter, allowing for color customization.
+ - Added function :php:func:`date_range()` that generates a list of dates between a specified period.
- :doc:`URL Helper <helpers/url_helper>` changes include:
- Deprecated *separator* options **dash** and **underscore** for function :php:func:`url_title()` (they are only aliases for '-' and '_' respectively).
- :php:func:`url_title()` will now trim extra dashes from beginning and end.
@@ -74,7 +73,10 @@ Release Date: Not Released
- Added support (auto-detection) for HTTP/1.1 response code 303 in :php:func:`redirect()`.
- Changed :php:func:`redirect()` to only choose the **refresh** method only on IIS servers, instead of all servers on Windows (when **auto** is used).
- Changed :php:func:`anchor()`, :php:func:`anchor_popup()`, and :php:func:`redirect()` to support protocol-relative URLs (e.g. *//ellislab.com/codeigniter*).
- - Added XHTML Basic 1.1 doctype to :doc:`HTML Helper <helpers/html_helper>`.
+ - :doc:`HTML Helper <helpers/html_helper>` changes include:
+ - Added more doctypes.
+ - Changed application and environment config files to be loaded in a cascade-like manner.
+ - The doctypes array is now cached and loaded only once.
- :doc:`Inflector Helper <helpers/inflector_helper>` changes include:
- Changed :php:func:`humanize()` to allow passing an input separator as its second parameter.
- Refactored :php:func:`plural()` and :php:func:`singular()` to avoid double pluralization and support more words.
@@ -88,7 +90,10 @@ Release Date: Not Released
- :doc:`Security Helper <helpers/security_helper>` changes include:
- :php:func:`do_hash()` now uses PHP's native ``hash()`` function (supporting more algorithms) and is deprecated.
- :php:func:`strip_image_tags()` is now an alias for the same method in the :doc:`Security Library <libraries/security>`.
- - Removed previously deprecated helper function ``js_insert_smiley()`` from :doc:`Smiley Helper <helpers/smiley_helper>`.
+ - :doc:`Smiley Helper <helpers/smiley_helper>` changes include:
+ - Removed previously deprecated function ``js_insert_smiley()``.
+ - Changed application and environment config files to be loaded in a cascade-like manner.
+ - The smileys array is now cached and loaded only once.
- :doc:`File Helper <helpers/file_helper>` changes include:
- :php:func:`set_realpath()` can now also handle file paths as opposed to just directories.
- Added an optional paramater to :php:func:`delete_files()` to enable it to skip deleting files such as *.htaccess* and *index.html*.
@@ -210,6 +215,7 @@ Release Date: Not Released
- Added **max_filename_increment** config setting.
- Added an **index** parameter to the ``data()`` method.
- Added the **min_width** and **min_height** options for images.
+ - Removed method ``clean_file_name()`` and its usage in favor of :doc:`Security Library <libraries/security>`'s ``sanitize_filename()``.
- :doc:`Cart library <libraries/cart>` changes include:
- ``insert()`` now auto-increments quantity for an item when inserted twice instead of resetting it, this is the default behaviour of large e-commerce sites.
- *Product Name* strictness can be disabled by switching the ``$product_name_safe`` property to FALSE.
@@ -236,6 +242,7 @@ Release Date: Not Released
- Added rule **valid_url**.
- Added support for named parameters in error messages.
- :doc:`Language <libraries/language>` line keys must now be prefixed with **form_validation_**.
+ - Added rule **alpha_numeric_spaces**.
- Added support for setting :doc:`Table <libraries/table>` class defaults in a config file.
- :doc:`Caching Library <libraries/caching>` changes include:
- Added Wincache driver.
@@ -254,6 +261,7 @@ Release Date: Not Released
- Removed unused protected method ``_get_ip()`` (:doc:`Input Library <libraries/input>`'s ``ip_address()`` should be used anyway).
- Internal method ``_prep_q_encoding()`` now utilizes PHP's *mbstring* and *iconv* extensions (when available) and no longer has a second (``$from``) argument.
- Added an optional parameter to ``print_debugger()`` to allow specifying which parts of the message should be printed ('headers', 'subject', 'body').
+ - Added SMTP keepalive option to avoid opening the connection for each ``Email::send()``. Accessible as ``$smtp_keepalive``.
- :doc:`Pagination Library <libraries/pagination>` changes include:
- Added support for the anchor "rel" attribute.
- Added support for setting custom attributes.
@@ -264,7 +272,9 @@ Release Date: Not Released
- :doc:`Encryption Library <libraries/encryption>` changes include:
- Added support for hashing algorithms other than SHA1 and MD5.
- Removed previously deprecated ``sha1()`` method.
- - :doc:`Profiler Library <general/profiling>` now also displays database object names.
+ - :doc:`Profiler Library <general/profiling>` changes include:
+ - Database object names are now being displayed.
+ - The sum of all queries running times in seconds is now being displayed.
- :doc:`Migration Library <libraries/migration>` changes include:
- Added support for timestamp-based migrations (enabled by default).
- Added ``$config['migration_type']`` to allow switching between *sequential* and *timestamp* migrations.
@@ -329,16 +339,15 @@ Bug fixes for 3.0
- Fixed a bug where ``unlink()`` raised an error if cache file did not exist when you try to delete it.
- Fixed a bug (#181) where a mis-spelling was in the form validation language file.
-- Fixed a bug (#159, #163) that mishandled Query Builder nested transactions because _trans_depth was not getting incremented.
+- Fixed a bug (#159, #163) - :doc:`Query Builder <database/query_builder>` nested transactions didn't work properly due to ``_trans_depth`` not being incremented.
- Fixed a bug (#737, #75) - :doc:`Pagination <libraries/pagination>` anchor class was not set properly when using initialize method.
-- Fixed a bug (#419) - ``auto_link()`` now recognizes URLs that come after a word boundary.
+- Fixed a bug (#419) - :php:func:`auto_link()` didn't recognize URLs that come after a word boundary.
- Fixed a bug (#724) - :doc:`Form Validation Library <libraries/form_validation>` rule **is_unique** didn't check if a database connection exists.
- Fixed a bug (#647) - :doc:`Zip Library <libraries/zip>` internal method ``_get_mod_time()`` didn't suppress possible "stat failed" errors generated by ``filemtime()``.
-- Fixed a bug (#608) - Fixes an issue with the Image_lib class not clearing properties completely.
-- Fixed a bug (#157, #174) - the Image_lib clear() function now resets all variables to their default values.
-- Fixed a bug where using $this->dbforge->create_table() with PostgreSQL database could lead to fetching whole table.
-- Fixed a bug (#795) - Fixed form method and accept-charset when passing an empty array.
-- Fixed a bug (#797) - timespan() was using incorrect seconds for year and month.
+- Fixed a bug (#157, #174) - :doc:`Image Manipulation Library <libraries/image_lib>` method ``clear()`` didn't completely clear properties.
+- Fixed a bug where :doc:`Database Forge <database/forge>` method ``create_table()`` with PostgreSQL database could lead to fetching the whole table.
+- Fixed a bug (#795) - :doc:`Form Helper <helpers/form_helper>` :php:func:`form_open()` didn't add the default form *method* and *accept-charset* when an empty array is passed to it.
+- Fixed a bug (#797) - :php:func:`timespan()` was using incorrect seconds for year and month.
- Fixed a bug in CI_Cart::contents() where if called without a TRUE (or equal) parameter, it would fail due to a typo.
- Fixed a bug (#696) - make oci_execute() calls inside num_rows() non-committing, since they are only there to reset which row is next in line for oci_fetch calls and thus don't need to be committed.
- Fixed a bug (#406) - SQLSRV DB driver not returning resource on ``db_pconnect()``.
@@ -472,6 +481,12 @@ Bug fixes for 3.0
- Fixed a bug (#113) - :doc:`Form Validation Library <libraries/form_validation>` didn't properly handle empty fields that were specified as an array.
- Fixed a bug (#2061) - :doc:`Routing Class <general/routing>` didn't properly sanitize directory, controller and function triggers with **enable_query_strings** set to TRUE.
- Fixed a bug - SQLSRV didn't support ``escape_like_str()`` or escaping an array of values.
+- Fixed a bug - :doc:`DB result <database/results>` method ``list_fields()`` didn't reset its field pointer for the *mysql*, *mysqli* and *mssql* drivers.
+- Fixed a bug (#73) - :doc:`Security Library <libraries/security>` method ``sanitize_filename()`` could be tricked by an XSS attack.
+- Fixed a bug (#2211) - :doc:`Migration Library <libraries/migration>` extensions couldn't execute ``CI_Migration::__construct()``.
+- Fixed a bug (#2255) - :doc:`Email Library <libraries/email>` didn't apply ``smtp_timeout``to socket reads and writes.
+- Fixed a bug (#2239) - :doc:`Email Library <libraries/email>` improperly handled the Subject when used with ``bcc_batch_mode`` resulting in E_WARNING messages and an empty Subject.
+- Fixed a bug (#2234) - :doc:`Query Builder <database/query_builder>` didn't reset JOIN cache for write-type queries.
Version 2.1.3
=============
diff --git a/user_guide_src/source/database/call_function.rst b/user_guide_src/source/database/call_function.rst
index 9890fc453..83fc870d0 100644
--- a/user_guide_src/source/database/call_function.rst
+++ b/user_guide_src/source/database/call_function.rst
@@ -7,7 +7,7 @@ $this->db->call_function();
This function enables you to call PHP database functions that are not
natively included in CodeIgniter, in a platform independent manner. For
-example, lets say you want to call the mysql_get_client_info()
+example, let's say you want to call the mysql_get_client_info()
function, which is **not** natively supported by CodeIgniter. You could
do so like this::
diff --git a/user_guide_src/source/general/controllers.rst b/user_guide_src/source/general/controllers.rst
index 729b08417..8cfb012a0 100644
--- a/user_guide_src/source/general/controllers.rst
+++ b/user_guide_src/source/general/controllers.rst
@@ -108,7 +108,7 @@ Passing URI Segments to your methods
If your URI contains more then two segments they will be passed to your
method as parameters.
-For example, lets say you have a URI like this::
+For example, let's say you have a URI like this::
example.com/index.php/products/shoes/sandals/123
@@ -267,7 +267,7 @@ Simply create folders within your *application/controllers/* directory
and place your controller classes within them.
.. note:: When using this feature the first segment of your URI must
- specify the folder. For example, lets say you have a controller located
+ specify the folder. For example, let's say you have a controller located
here::
application/controllers/products/shoes.php
diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst
index 2a0332088..0c6dfe888 100644
--- a/user_guide_src/source/general/routing.rst
+++ b/user_guide_src/source/general/routing.rst
@@ -12,7 +12,7 @@ In some instances, however, you may want to remap this relationship so
that a different class/method can be called instead of the one
corresponding to the URL.
-For example, lets say you want your URLs to have this prototype::
+For example, let's say you want your URLs to have this prototype::
example.com/product/1/
example.com/product/2/
@@ -129,7 +129,7 @@ For those of you who don't know regular expressions and want to learn
more about them, `regular-expressions.info <http://www.regular-expressions.info/>`
might be a good starting point.
-..note:: You can also mix and match wildcards with regular expressions.
+.. note:: You can also mix and match wildcards with regular expressions.
Callbacks
=========
@@ -137,7 +137,7 @@ Callbacks
If you are using PHP >= 5.3 you can use callbacks in place of the normal
routing rules to process the back-references. Example::
- $route['products/([a-z]+)/edit/(\d+)'] = function ($product_type, $id)
+ $route['products/([a-zA-Z]+)/edit/(\d+)'] = function ($product_type, $id)
{
return 'catalog/product_edit/' . strtolower($product_type) . '/' . $id;
};
diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst
index 94f6321be..02841ab6e 100644
--- a/user_guide_src/source/installation/upgrade_300.rst
+++ b/user_guide_src/source/installation/upgrade_300.rst
@@ -1,5 +1,5 @@
#############################
-Upgrading from 2.1.2 to 3.0.0
+Upgrading from 2.1.3 to 3.0.0
#############################
.. note:: These upgrade notes are for a version that is yet to be released.
@@ -104,16 +104,47 @@ regular expression::
(.+) // matches ANYTHING
(:any) // matches any character, except for '/'
+*****************************************
+Step 9: Update your libraries' file names
+*****************************************
-****************************************************************************
-Step 9: Check the calls to Array Helper's element() and elements() functions
-****************************************************************************
+CodeIgniter 3.0 only allows library file names to be named in a *ucfirst* manner
+(meaning that the first letter of the class name must be a capital). For example,
+if you have the following library file:
+
+ application/libraries/mylibrary.php
+
+... then you'll have to rename it to:
+
+ application/libraries/Mylibrary.php
+
+The same goes for driver libraries and extensions and/or overrides of CodeIgniter's
+own libraries and core classes.
+
+ application/libraries/MY_email.php
+ application/core/MY_log.php
+
+The above files should respectively be renamed to the following:
+
+ application/libraries/MY_Email.php
+ application/core/MY_Log.php
+
+*****************************************************************************
+Step 10: Check the calls to Array Helper's element() and elements() functions
+*****************************************************************************
The default return value of these functions, when the required elements
don't exist, has been changed from FALSE to NULL.
+***********************************************************************
+Step 11: Check the calls to Directory Helper's directory_map() function
+***********************************************************************
+
+In the resulting array, directories now end with a trailing directory
+separator (i.e. a slash, usually).
+
*************************************************************
-Step 10: Update usage of Database Forge's drop_table() method
+Step 12: Update usage of Database Forge's drop_table() method
*************************************************************
Up until now, ``drop_table()`` added an IF EXISTS clause by default or it didn't work
@@ -135,7 +166,7 @@ If your application relies on IF EXISTS, you'll have to change its usage.
all drivers with the exception of ODBC.
***********************************************************
-Step 11: Change usage of Email library with multiple emails
+Step 13: Change usage of Email library with multiple emails
***********************************************************
The :doc:`Email Library <../libraries/email>` will automatically clear the
@@ -150,7 +181,7 @@ pass FALSE as the first parameter in the ``send()`` method:
}
***************************************************
-Step 12: Update your Form_validation language lines
+Step 14: Update your Form_validation language lines
***************************************************
Two improvements have been made to the :doc:`Form Validation Library
@@ -181,7 +212,7 @@ files and error messages format:
later.
****************************************************************
-Step 13: Remove usage of (previously) deprecated functionalities
+Step 15: Remove usage of (previously) deprecated functionalities
****************************************************************
In addition to the ``$autoload['core']`` configuration setting, there's a
@@ -214,7 +245,7 @@ Security helper do_hash()
:doc:`Security Helper <../helpers/security_helper>` function ``do_hash()`` is now just an alias for
PHP's native ``hash()`` function. It is deprecated and scheduled for removal in CodeIgniter 3.1+.
-.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
File helper read_file()
@@ -224,7 +255,7 @@ File helper read_file()
PHP's native ``file_get_contents()`` function. It is deprecated and scheduled for removal in
CodeIgniter 3.1+.
-.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
String helper repeater()
@@ -233,7 +264,7 @@ String helper repeater()
:doc:`String Helper <../helpers/string_helper>` function :php:func:`repeater()` is now just an alias for
PHP's native ``str_repeat()`` function. It is deprecated and scheduled for removal in CodeIgniter 3.1+.
-.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
String helper trim_slashes()
@@ -243,7 +274,7 @@ String helper trim_slashes()
for PHP's native ``trim()`` function (with a slash passed as its second argument). It is deprecated and
scheduled for removal in CodeIgniter 3.1+.
-.. note:: This function is still available, but you're strongly encouraged to remove it's usage sooner
+.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
Email helper functions
@@ -268,7 +299,7 @@ Date helper standard_date()
to the availability of native PHP `constants <http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_,
which when combined with ``date()`` provide the same functionality. Furthermore, they have the
exact same names as the ones supported by ``standard_date()``. Here are examples of how to replace
-it's usage:
+its usage:
::
@@ -284,7 +315,7 @@ it's usage:
// Replacement
date(DATE_ATOM, $time);
-.. note:: This function is still available, but you're strongly encouraged to remove its' usage sooner
+.. note:: This function is still available, but you're strongly encouraged to remove its usage sooner
rather than later as it is scheduled for removal in CodeIgniter 3.1+.
Pagination library 'anchor_class' setting
@@ -296,7 +327,7 @@ attribute to your anchors via the 'attributes' configuration setting. This inclu
As a result of that, the 'anchor_class' setting is now deprecated and scheduled for removal in
CodeIgniter 3.1+.
-.. note:: This setting is still available, but you're strongly encouraged to remove its' usage sooner
+.. note:: This setting is still available, but you're strongly encouraged to remove its usage sooner
rather than later.
String helper random_string() types 'unique' and 'encrypt'
diff --git a/user_guide_src/source/libraries/email.rst b/user_guide_src/source/libraries/email.rst
index 7d468251c..a55f1895d 100644
--- a/user_guide_src/source/libraries/email.rst
+++ b/user_guide_src/source/libraries/email.rst
@@ -89,6 +89,7 @@ Preference Default Value Options Descript
**smtp_pass** No Default None SMTP Password.
**smtp_port** 25 None SMTP Port.
**smtp_timeout** 5 None SMTP Timeout (in seconds).
+**smtp_keepalive** FALSE TRUE or FALSE (boolean) Enable persistent SMTP connections.
**smtp_crypto** No Default tls or ssl SMTP Encryption
**wordwrap** TRUE TRUE or FALSE (boolean) Enable word-wrap.
**wrapchars** 76 Character count to wrap at.
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index ae7859aa3..8b35fdc75 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -877,7 +877,9 @@ Rule Parameter Description
**less_than_equal_to** Yes Returns FALSE if the form element is greater than the parameter value, less_than_equal_to[8]
or not numeric.
**alpha** No Returns FALSE if the form element contains anything other than alphabetical characters.
-**alpha_numeric** No Returns FALSE if the form element contains anything other than alpha-numeric characters.
+**alpha_numeric** No Returns FALSE if the form element contains anything other than alpha-numeric characters.
+**alpha_numeric_spaces** No Returns FALSE if the form element contains anything other than alpha-numeric characters
+ or spaces. Should be used after trim to avoid spaces at the beginning or end.
**alpha_dash** No Returns FALSE if the form element contains anything other than alpha-numeric characters,
underscores or dashes.
**numeric** No Returns FALSE if the form element contains anything other than numeric characters.
diff --git a/user_guide_src/source/libraries/loader.rst b/user_guide_src/source/libraries/loader.rst
index 615aba1c2..b048f4881 100644
--- a/user_guide_src/source/libraries/loader.rst
+++ b/user_guide_src/source/libraries/loader.rst
@@ -11,14 +11,15 @@ can be libraries (classes) :doc:`View files <../general/views>`,
.. note:: This class is initialized automatically by the system so there
is no need to do it manually.
-The following functions are available in this class:
+The following methods are available in this class:
$this->load->library('class_name', $config, 'object name')
-===========================================================
+==========================================================
-This function is used to load core classes. Where class_name is the
-name of the class you want to load. Note: We use the terms "class" and
-"library" interchangeably.
+This method is used to load core classes. Where class_name is the
+name of the class you want to load.
+
+.. note:: We use the terms "class" and "library" interchangeably.
For example, if you would like to send email with CodeIgniter, the first
step is to load the email class within your controller::
@@ -26,15 +27,15 @@ step is to load the email class within your controller::
$this->load->library('email');
Once loaded, the library will be ready for use, using
-$this->email->*some_function*().
+$this->email->*some_method*().
Library files can be stored in subdirectories within the main
-"libraries" folder, or within your personal application/libraries
-folder. To load a file located in a subdirectory, simply include the
-path, relative to the "libraries" folder. For example, if you have file
-located at::
+"libraries" directory, or within your personal application/libraries
+directory. To load a file located in a subdirectory, simply include the
+path, relative to the "libraries" directory. For example, if you have
+file located at::
- libraries/flavors/chocolate.php
+ libraries/flavors/Chocolate.php
You will load it using::
@@ -43,7 +44,7 @@ You will load it using::
You may nest the file in as many subdirectories as you want.
Additionally, multiple libraries can be loaded at the same time by
-passing an array of libraries to the load function.
+passing an array of libraries to the load method.
::
@@ -56,10 +57,10 @@ The second (optional) parameter allows you to optionally pass
configuration setting. You will typically pass these as an array::
$config = array (
- 'mailtype' => 'html',
- 'charset' => 'utf-8,
- 'priority' => '1'
- );
+ 'mailtype' => 'html',
+ 'charset' => 'utf-8,
+ 'priority' => '1'
+ );
$this->load->library('email', $config);
@@ -84,16 +85,15 @@ third parameter::
$this->load->library('calendar', '', 'my_calendar');
// Calendar class is now accessed using:
-
$this->my_calendar
Please take note, when multiple libraries are supplied in an array for
the first parameter, this parameter is discarded.
$this->load->driver('parent_name', $config, 'object name')
-===========================================================
+==========================================================
-This function is used to load driver libraries. Where parent_name is the
+This method is used to load driver libraries. Where parent_name is the
name of the parent class you want to load.
As an example, if you would like to use sessions with CodeIgniter, the first
@@ -102,15 +102,15 @@ step is to load the session driver within your controller::
$this->load->driver('session');
Once loaded, the library will be ready for use, using
-$this->session->*some_function*().
+$this->session->*some_method*().
Driver files must be stored in a subdirectory within the main
-"libraries" folder, or within your personal application/libraries
-folder. The subdirectory must match the parent class name. Read the
+"libraries" directory, or within your personal application/libraries
+directory. The subdirectory must match the parent class name. Read the
:doc:`Drivers <../general/drivers>` description for details.
Additionally, multiple driver libraries can be loaded at the same time by
-passing an array of drivers to the load function.
+passing an array of drivers to the load method.
::
@@ -122,11 +122,11 @@ Setting options
The second (optional) parameter allows you to optionally pass
configuration settings. You will typically pass these as an array::
- $config = array (
- 'sess_driver' => 'cookie',
- 'sess_encrypt_cookie' => true,
- 'encryption_key' => 'mysecretkey'
- );
+ $config = array(
+ 'sess_driver' => 'cookie',
+ 'sess_encrypt_cookie' => true,
+ 'encryption_key' => 'mysecretkey'
+ );
$this->load->driver('session', $config);
@@ -135,12 +135,12 @@ is explained in detail in its own page, so please read the information
regarding each one you would like to use.
Assigning a Driver to a different object name
-----------------------------------------------
+---------------------------------------------
If the third (optional) parameter is blank, the library will be assigned
to an object with the same name as the parent class. For example, if
the library is named Session, it will be assigned to a variable named
-$this->session.
+``$this->session``.
If you prefer to set your own class names you can pass its value to the
third parameter::
@@ -148,32 +148,33 @@ third parameter::
$this->load->library('session', '', 'my_session');
// Session class is now accessed using:
-
$this->my_session
-.. note:: Driver libraries may also be loaded with the library() method,
- but it is faster to use driver()
+.. note:: Driver libraries may also be loaded with the ``library()`` method,
+ but it is faster to use ``driver()``.
-$this->load->view('file_name', $data, true/false)
-==================================================
+$this->load->view('file_name', $data, TRUE/FALSE)
+=================================================
-This function is used to load your View files. If you haven't read the
+This method is used to load your View files. If you haven't read the
:doc:`Views <../general/views>` section of the user guide it is
-recommended that you do since it shows you how this function is
+recommended that you do since it shows you how this method is
typically used.
The first parameter is required. It is the name of the view file you
-would like to load. Note: The .php file extension does not need to be
-specified unless you use something other than .php.
+would like to load.
+
+.. note:: The .php file extension does not need to be specified unless
+ you use something other than .php.
The second **optional** parameter can take an associative array or an
object as input, which it runs through the PHP
-`extract <http://www.php.net/extract>`_ function to convert to variables
+`extract() <http://www.php.net/extract>`_ function to convert to variables
that can be used in your view files. Again, read the
:doc:`Views <../general/views>` page to learn how this might be useful.
The third **optional** parameter lets you change the behavior of the
-function so that it returns data as a string rather than sending it to
+method so that it returns data as a string rather than sending it to
your browser. This can be useful if you want to process the data in some
way. If you set the parameter to true (boolean) it will return data. The
default behavior is false, which sends it to your browser. Remember to
@@ -189,79 +190,76 @@ $this->load->model('model_name');
$this->load->model('model_name');
-If your model is located in a sub-folder, include the relative path from
-your models folder. For example, if you have a model located at
+If your model is located in a subdirectory, include the relative path
+from your models directory. For example, if you have a model located at
application/models/blog/queries.php you'll load it using::
$this->load->model('blog/queries');
-
If you would like your model assigned to a different object name you can
-specify it via the second parameter of the loading function::
+specify it via the second parameter of the loading method::
$this->load->model('model_name', 'fubar');
+ $this->fubar->method();
- $this->fubar->function();
-
-$this->load->database('options', true/false)
+$this->load->database('options', TRUE/FALSE)
============================================
-This function lets you load the database class. The two parameters are
+This method lets you load the database class. The two parameters are
**optional**. Please see the :doc:`database <../database/index>`
section for more info.
$this->load->vars($array)
=========================
-This function takes an associative array as input and generates
+This method takes an associative array as input and generates
variables using the PHP `extract <http://www.php.net/extract>`_
-function. This function produces the same result as using the second
-parameter of the $this->load->view() function above. The reason you
-might want to use this function independently is if you would like to
+method. This method produces the same result as using the second
+parameter of the ``$this->load->view()`` method above. The reason you
+might want to use this method independently is if you would like to
set some global variables in the constructor of your controller and have
-them become available in any view file loaded from any function. You can
-have multiple calls to this function. The data get cached and merged
+them become available in any view file loaded from any method. You can
+have multiple calls to this method. The data get cached and merged
into one array for conversion to variables.
$this->load->get_var($key)
-===========================
+==========================
-This function checks the associative array of variables available to
+This method checks the associative array of variables available to
your views. This is useful if for any reason a var is set in a library
-or another controller method using $this->load->vars().
+or another controller method using ``$this->load->vars()``.
$this->load->get_vars()
-===========================
+=======================
-This function retrieves all variables available to
-your views.
+This method retrieves all variables available to your views.
$this->load->helper('file_name')
-=================================
+================================
-This function loads helper files, where file_name is the name of the
+This method loads helper files, where file_name is the name of the
file, without the _helper.php extension.
-$this->load->file('filepath/filename', true/false)
+$this->load->file('filepath/filename', TRUE/FALSE)
==================================================
-This is a generic file loading function. Supply the filepath and name in
+This is a generic file loading method. Supply the filepath and name in
the first parameter and it will open and read the file. By default the
data is sent to your browser, just like a View file, but if you set the
second parameter to true (boolean) it will instead return the data as a
string.
$this->load->language('file_name')
-===================================
+==================================
-This function is an alias of the :doc:`language loading
-function <language>`: $this->lang->load()
+This method is an alias of the :doc:`language loading
+method <language>`: ``$this->lang->load()``
$this->load->config('file_name')
-=================================
+================================
-This function is an alias of the :doc:`config file loading
-function <config>`: $this->config->load()
+This method is an alias of the :doc:`config file loading
+method <config>`: ``$this->config->load()``
Application "Packages"
======================
@@ -269,7 +267,7 @@ Application "Packages"
An application package allows for the easy distribution of complete sets
of resources in a single directory, complete with its own libraries,
models, helpers, config, and language files. It is recommended that
-these packages be placed in the application/third_party folder. Below
+these packages be placed in the application/third_party directory. Below
is a sample map of an package directory
Sample Package "Foo Bar" Directory Map
@@ -311,7 +309,7 @@ $this->load->remove_package_path()
When your controller is finished using resources from an application
package, and particularly if you have other application packages you
want to work with, you may wish to remove the package path so the Loader
-no longer looks in that folder for resources. To remove the last path
+no longer looks in that directory for resources. To remove the last path
added, simply call the method with no parameters.
$this->load->remove_package_path()
@@ -346,4 +344,4 @@ calling add_package_path().
// Again without the second parameter:
$this->load->add_package_path(APPPATH.'my_app');
$this->load->view('my_app_index'); // Loads
- $this->load->view('welcome_message'); // Loads
+ $this->load->view('welcome_message'); // Loads \ No newline at end of file
diff --git a/user_guide_src/source/libraries/migration.rst b/user_guide_src/source/libraries/migration.rst
index 9a7b10d64..b734f5c34 100644
--- a/user_guide_src/source/libraries/migration.rst
+++ b/user_guide_src/source/libraries/migration.rst
@@ -10,7 +10,7 @@ need to be run against the production machines next time you deploy.
The database table **migration** tracks which migrations have already been
run so all you have to do is update your application files and
-call **$this->migrate->current()** to work out which migrations should be run.
+call **$this->migration->current()** to work out which migrations should be run.
The current version is found in **config/migration.php**.
********************
diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst
index b64ea2aae..d7754e9f3 100644
--- a/user_guide_src/source/tutorial/news_section.rst
+++ b/user_guide_src/source/tutorial/news_section.rst
@@ -68,7 +68,7 @@ following code to your model.
$query = $this->db->get('news');
return $query->result_array();
}
-
+
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
@@ -146,7 +146,7 @@ and add the next piece of code.
<?php foreach ($news as $news_item): ?>
<h2><?php echo $news_item['title'] ?></h2>
- <div id="main">
+ <div class="main">
<?php echo $news_item['text'] ?>
</div>
<p><a href="<?php echo $news_item['slug'] ?>">View article</a></p>
@@ -162,7 +162,7 @@ The news overview page is now done, but a page to display individual
news items is still absent. The model created earlier is made in such
way that it can easily be used for this functionality. You only need to
add some code to the controller and create a new view. Go back to the
-news controller and add the following lines to the file.
+news controller and update ``view()`` with the following:
::
@@ -211,4 +211,4 @@ a slug to the view method in the news controller.
$route['default_controller'] = 'pages/view';
Point your browser to your document root, followed by index.php/news and
-watch your news page. \ No newline at end of file
+watch your news page.