summaryrefslogtreecommitdiffstats
path: root/system
diff options
context:
space:
mode:
authorAndrey Andreev <narf@devilix.net>2014-01-20 14:03:43 +0100
committerAndrey Andreev <narf@devilix.net>2014-01-20 14:03:43 +0100
commitea801ab4ab80042638ffddc6056483a1ec43fa80 (patch)
treef75f30c0df6a8f861ca7df22af09fa3240b0bbd6 /system
parent1c08d557a21ecb0f79cd1a1de4e06817a26e0537 (diff)
parent4d0571666d03511ac5b4a1f2a6882ccb1509a209 (diff)
Merge branch 'develop' into feature/user-guide-cleanup
Diffstat (limited to 'system')
-rw-r--r--system/core/CodeIgniter.php174
-rw-r--r--system/core/Common.php174
-rw-r--r--system/core/Config.php38
-rw-r--r--system/core/Exceptions.php53
-rw-r--r--system/core/Hooks.php39
-rw-r--r--system/core/Input.php113
-rw-r--r--system/core/Lang.php2
-rw-r--r--system/core/Loader.php225
-rw-r--r--system/core/Log.php17
-rw-r--r--system/core/Model.php3
-rw-r--r--system/core/Output.php288
-rw-r--r--system/core/Router.php328
-rw-r--r--system/core/Security.php68
-rw-r--r--system/core/URI.php280
-rw-r--r--system/core/Utf8.php2
-rw-r--r--system/database/DB.php5
-rw-r--r--system/database/DB_driver.php23
-rw-r--r--system/database/DB_forge.php21
-rw-r--r--system/database/DB_query_builder.php49
-rw-r--r--system/database/DB_utility.php3
-rw-r--r--system/database/drivers/mysql/mysql_driver.php14
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php41
-rw-r--r--system/database/drivers/oci8/oci8_driver.php4
-rw-r--r--system/database/drivers/oci8/oci8_result.php2
-rw-r--r--system/database/drivers/pdo/pdo_driver.php4
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php21
-rw-r--r--system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php4
-rw-r--r--system/database/drivers/postgre/postgre_driver.php12
-rw-r--r--system/helpers/captcha_helper.php24
-rw-r--r--system/helpers/cookie_helper.php13
-rw-r--r--system/helpers/file_helper.php12
-rw-r--r--system/helpers/form_helper.php194
-rw-r--r--system/helpers/html_helper.php6
-rw-r--r--system/helpers/language_helper.php3
-rw-r--r--system/helpers/security_helper.php9
-rw-r--r--system/helpers/text_helper.php31
-rw-r--r--system/helpers/url_helper.php39
-rw-r--r--system/language/english/ftp_lang.php10
-rw-r--r--system/libraries/Cache/Cache.php42
-rw-r--r--system/libraries/Cache/drivers/Cache_apc.php59
-rw-r--r--system/libraries/Cache/drivers/Cache_dummy.php31
-rw-r--r--system/libraries/Cache/drivers/Cache_file.php108
-rw-r--r--system/libraries/Cache/drivers/Cache_memcached.php56
-rw-r--r--system/libraries/Cache/drivers/Cache_redis.php75
-rw-r--r--system/libraries/Cache/drivers/Cache_wincache.php49
-rw-r--r--system/libraries/Calendar.php46
-rw-r--r--system/libraries/Email.php134
-rw-r--r--system/libraries/Form_validation.php79
-rw-r--r--system/libraries/Ftp.php14
-rw-r--r--system/libraries/Javascript.php4
-rw-r--r--system/libraries/Javascript/Jquery.php3
-rw-r--r--system/libraries/Pagination.php3
-rw-r--r--system/libraries/Parser.php30
-rw-r--r--system/libraries/Profiler.php28
-rw-r--r--system/libraries/Session/Session.php53
-rw-r--r--system/libraries/Session/drivers/Session_cookie.php122
-rw-r--r--system/libraries/Unit_test.php30
-rw-r--r--system/libraries/Upload.php38
-rw-r--r--system/libraries/User_agent.php60
-rw-r--r--system/libraries/Xmlrpc.php115
-rw-r--r--system/libraries/Xmlrpcs.php14
-rw-r--r--system/libraries/Zip.php76
62 files changed, 2140 insertions, 1477 deletions
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index c68266408..74a9eb0af 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -48,24 +48,22 @@ defined('BASEPATH') OR exit('No direct script access allowed');
/*
* ------------------------------------------------------
- * Load the global functions
+ * Load the framework constants
* ------------------------------------------------------
*/
- require_once(BASEPATH.'core/Common.php');
+ if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
+ {
+ require_once(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
+ }
+
+ require_once(APPPATH.'config/constants.php');
/*
* ------------------------------------------------------
- * Load the framework constants
+ * Load the global functions
* ------------------------------------------------------
*/
- if (file_exists(APPPATH.'config/'.ENVIRONMENT.'/constants.php'))
- {
- require(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
- }
- else
- {
- require(APPPATH.'config/constants.php');
- }
+ require_once(BASEPATH.'core/Common.php');
/*
* ------------------------------------------------------
@@ -73,11 +71,10 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* ------------------------------------------------------
*/
set_error_handler('_exception_handler');
+ register_shutdown_function('_shutdown_handler');
- if ( ! is_php('5.4'))
- {
- @ini_set('magic_quotes_runtime', 0); // Kill magic quotes
- }
+ // Kill magic quotes
+ is_php('5.4') OR @ini_set('magic_quotes_runtime', 0);
/*
* ------------------------------------------------------
@@ -88,7 +85,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
* The subclass prefix allows CI to know if a core class is
* being extended via a library in the local application
* "libraries" folder. Since CI allows config items to be
- * overriden via data set in the main index. php file,
+ * overriden via data set in the main index.php file,
* before proceeding we need to know if a subclass_prefix
* override exists. If so, we will set this value now,
* before any classes are loaded
@@ -166,12 +163,6 @@ defined('BASEPATH') OR exit('No direct script access allowed');
*/
$RTR =& load_class('Router', 'core');
- // Set any routing overrides that may exist in the main index file
- if (isset($routing))
- {
- $RTR->_set_overrides($routing);
- }
-
/*
* ------------------------------------------------------
* Instantiate the output class
@@ -218,7 +209,7 @@ defined('BASEPATH') OR exit('No direct script access allowed');
*
*/
// Load the base controller class
- require BASEPATH.'core/Controller.php';
+ require_once BASEPATH.'core/Controller.php';
/**
* Reference to the CI_Controller method.
@@ -234,92 +225,117 @@ defined('BASEPATH') OR exit('No direct script access allowed');
if (file_exists(APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php'))
{
- require APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
+ require_once APPPATH.'core/'.$CFG->config['subclass_prefix'].'Controller.php';
}
- // Load the local application controller
- // Note: The Router class automatically validates the controller path using the router->_validate_request().
- // If this include fails it means that the default controller in the Routes.php file is not resolving to something valid.
- if ( ! file_exists(APPPATH.'controllers/'.$RTR->directory.$RTR->class.'.php'))
- {
- show_error('Unable to load your default controller. Please make sure the controller specified in your Routes.php file is valid.');
- }
-
- include(APPPATH.'controllers/'.$RTR->directory.$RTR->class.'.php');
-
// Set a mark point for benchmarking
$BM->mark('loading_time:_base_classes_end');
/*
* ------------------------------------------------------
- * Security check
+ * Sanity checks
* ------------------------------------------------------
*
- * None of the methods in the app controller or the
- * loader class can be called via the URI, nor can
- * controller functions that begin with an underscore.
+ * The Router class has already validated the request,
+ * leaving us with 3 options here:
+ *
+ * 1) an empty class name, if we reached the default
+ * controller, but it didn't exist;
+ * 2) a query string which doesn't go through a
+ * file_exists() check
+ * 3) a regular request for a non-existing page
+ *
+ * We handle all of these as a 404 error.
+ *
+ * Furthermore, none of the methods in the app controller
+ * or the loader class can be called via the URI, nor can
+ * controller methods that begin with an underscore.
*/
- $class = $RTR->class;
- $method = $RTR->method;
-
- if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
- {
- if ( ! empty($RTR->routes['404_override']))
- {
- if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
- {
- $method = 'index';
- }
-
- if ( ! class_exists($class, FALSE))
- {
- if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
- {
- show_404($class.'/'.$method);
- }
- include_once(APPPATH.'controllers/'.$class.'.php');
- }
- }
- else
- {
- show_404($class.'/'.$method);
- }
- }
+ $e404 = FALSE;
+ $class = ucfirst($RTR->class);
+ $method = $RTR->method;
- if (method_exists($class, '_remap'))
+ if (empty($class) OR ! file_exists(APPPATH.'controllers/'.$RTR->directory.$class.'.php'))
{
- $params = array($method, array_slice($URI->rsegments, 2));
- $method = '_remap';
+ $e404 = TRUE;
}
else
{
+ require_once(APPPATH.'controllers/'.$RTR->directory.$class.'.php');
+
+ if ( ! class_exists($class, FALSE) OR $method[0] === '_' OR method_exists('CI_Controller', $method))
+ {
+ $e404 = TRUE;
+ }
+ elseif (method_exists($class, '_remap'))
+ {
+ $params = array($method, array_slice($URI->rsegments, 2));
+ $method = '_remap';
+ }
// WARNING: It appears that there are issues with is_callable() even in PHP 5.2!
// Furthermore, there are bug reports and feature/change requests related to it
// that make it unreliable to use in this context. Please, DO NOT change this
// work-around until a better alternative is available.
- if ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))
+ elseif ( ! in_array(strtolower($method), array_map('strtolower', get_class_methods($class)), TRUE))
{
- if (empty($RTR->routes['404_override']))
- {
- show_404($class.'/'.$method);
- }
- elseif (sscanf($RTR->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
+ $e404 = TRUE;
+ }
+ }
+
+ if ($e404)
+ {
+ if ( ! empty($RTR->routes['404_override']))
+ {
+ if (sscanf($RTR->routes['404_override'], '%[^/]/%s', $error_class, $error_method) !== 2)
{
- $method = 'index';
+ $error_method = 'index';
}
- if ( ! class_exists($class, FALSE))
+ $error_class = ucfirst($error_class);
+
+ if ( ! class_exists($error_class, FALSE))
{
- if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
+ if (file_exists(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php'))
{
- show_404($class.'/'.$method);
+ require_once(APPPATH.'controllers/'.$RTR->directory.$error_class.'.php');
+ $e404 = ! class_exists($error_class, FALSE);
}
-
- include_once(APPPATH.'controllers/'.$class.'.php');
+ // Were we in a directory? If so, check for a global override
+ elseif ( ! empty($RTR->directory) && file_exists(APPPATH.'controllers/'.$error_class.'.php'))
+ {
+ require_once(APPPATH.'controllers/'.$error_class.'.php');
+ if (($e404 = ! class_exists($error_class, FALSE)) === FALSE)
+ {
+ $RTR->directory = '';
+ }
+ }
+ }
+ else
+ {
+ $e404 = FALSE;
}
}
+ // Did we reset the $e404 flag? If so, set the rsegments, starting from index 1
+ if ( ! $e404)
+ {
+ $class = $error_class;
+ $method = $error_method;
+
+ $URI->rsegments = array(
+ 1 => $class,
+ 2 => $method
+ );
+ }
+ else
+ {
+ show_404($RTR->directory.$class.'/'.$method);
+ }
+ }
+
+ if ($method !== '_remap')
+ {
$params = array_slice($URI->rsegments, 2);
}
diff --git a/system/core/Common.php b/system/core/Common.php
index b95a05db9..00e303098 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -82,7 +82,7 @@ if ( ! function_exists('is_really_writable'))
function is_really_writable($file)
{
// If we're on a Unix server with safe_mode off we call is_writable
- if (DIRECTORY_SEPARATOR === '/' && (bool) @ini_get('safe_mode') === FALSE)
+ if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR (bool) @ini_get('safe_mode') === FALSE))
{
return is_writable($file);
}
@@ -224,56 +224,51 @@ if ( ! function_exists('get_config'))
* @param array
* @return array
*/
- function &get_config($replace = array())
+ function &get_config(Array $replace = array())
{
static $_config;
- if (isset($_config))
+ if (empty($_config))
{
- return $_config[0];
- }
+ $file_path = APPPATH.'config/config.php';
+ $found = FALSE;
+ if (file_exists($file_path))
+ {
+ $found = TRUE;
+ require($file_path);
+ }
- $file_path = APPPATH.'config/config.php';
- $found = FALSE;
- if (file_exists($file_path))
- {
- $found = TRUE;
- require($file_path);
- }
+ // Is the config file in the environment folder?
+ if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+ {
+ require($file_path);
+ }
+ elseif ( ! $found)
+ {
+ set_status_header(503);
+ echo 'The configuration file does not exist.';
+ exit(EXIT_CONFIG);
+ }
- // Is the config file in the environment folder?
- if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
- {
- require($file_path);
- }
- elseif ( ! $found)
- {
- set_status_header(503);
- echo 'The configuration file does not exist.';
- exit(EXIT_CONFIG);
- }
+ // Does the $config array exist in the file?
+ if ( ! isset($config) OR ! is_array($config))
+ {
+ set_status_header(503);
+ echo 'Your config file does not appear to be formatted correctly.';
+ exit(EXIT_CONFIG);
+ }
- // Does the $config array exist in the file?
- if ( ! isset($config) OR ! is_array($config))
- {
- set_status_header(503);
- echo 'Your config file does not appear to be formatted correctly.';
- exit(EXIT_CONFIG);
+ // references cannot be directly assigned to static variables, so we use an array
+ $_config[0] =& $config;
}
- // Are any values being dynamically replaced?
- if (count($replace) > 0)
+ // Are any values being dynamically added or replaced?
+ foreach ($replace as $key => $val)
{
- foreach ($replace as $key => $val)
- {
- if (isset($config[$key]))
- {
- $config[$key] = $val;
- }
- }
+ $_config[0][$key] = $val;
}
- return $_config[0] =& $config;
+ return $_config[0];
}
}
@@ -360,6 +355,24 @@ if ( ! function_exists('is_https'))
// ------------------------------------------------------------------------
+if ( ! function_exists('is_cli'))
+{
+
+ /**
+ * Is CLI?
+ *
+ * Test to see if a request was made from the command line.
+ *
+ * @return bool
+ */
+ function is_cli()
+ {
+ return (PHP_SAPI === 'cli' OR defined('STDIN'));
+ }
+}
+
+// ------------------------------------------------------------------------
+
if ( ! function_exists('show_error'))
{
/**
@@ -434,29 +447,19 @@ if ( ! function_exists('log_message'))
*
* @param string the error level: 'error', 'debug' or 'info'
* @param string the error message
- * @param bool whether the error is a native PHP error
* @return void
*/
- function log_message($level, $message, $php_error = FALSE)
+ function log_message($level, $message)
{
- static $_log, $_log_threshold;
-
- if ($_log_threshold === NULL)
- {
- $_log_threshold = config_item('log_threshold');
- }
-
- if ($_log_threshold === 0)
- {
- return;
- }
+ static $_log;
if ($_log === NULL)
{
- $_log =& load_class('Log', 'core');
+ // references cannot be directly assigned to static variables, so we use an array
+ $_log[0] =& load_class('Log', 'core');
}
- $_log->write_log($level, $message, $php_error);
+ $_log[0]->write_log($level, $message);
}
}
@@ -538,7 +541,7 @@ if ( ! function_exists('set_status_header'))
$server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
- if (strpos(php_sapi_name(), 'cgi') === 0)
+ if (strpos(PHP_SAPI, 'cgi') === 0)
{
header('Status: '.$code.' '.$text, TRUE);
}
@@ -556,22 +559,35 @@ if ( ! function_exists('_exception_handler'))
/**
* Exception Handler
*
- * This is the custom exception handler that is declaired at the top
- * of Codeigniter.php. The main reason we use this is to permit
+ * This is the custom exception handler that is declared at the top
+ * of CodeIgniter.php. The main reason we use this is to permit
* PHP errors to be logged in our own log files since the user may
* not have access to server logs. Since this function
* effectively intercepts PHP errors, however, we also need
* to display errors based on the current error_reporting level.
* We do that with the use of a PHP error template.
*
- * @param int
- * @param string
- * @param string
- * @param int
+ * @param int $severity
+ * @param string $message
+ * @param string $filepath
+ * @param int $line
* @return void
*/
function _exception_handler($severity, $message, $filepath, $line)
{
+ $is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
+
+ // When an error occurred, set the status header to '500 Internal Server Error'
+ // to indicate to the client something went wrong.
+ // This can't be done within the $_error->show_php_error method because
+ // it is only called when the display_errors flag is set (which isn't usually
+ // the case in a production environment) or when errors are ignored because
+ // they are above the error_reporting threshold.
+ if ($is_error)
+ {
+ set_status_header(500);
+ }
+
$_error =& load_class('Exceptions', 'core');
// Should we ignore the error? We'll get the current error_reporting
@@ -588,6 +604,42 @@ if ( ! function_exists('_exception_handler'))
}
$_error->log_exception($severity, $message, $filepath, $line);
+
+ // If the error is fatal, the execution of the script should be stopped because
+ // errors can't be recovered from. Halting the script conforms with PHP's
+ // default error handling. See http://www.php.net/manual/en/errorfunc.constants.php
+ if ($is_error)
+ {
+ exit(EXIT_ERROR);
+ }
+ }
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_shutdown_handler'))
+{
+ /**
+ * Shutdown Handler
+ *
+ * This is the shutdown handler that is declared at the top
+ * of CodeIgniter.php. The main reason we use this is to simulate
+ * a complete custom exception handler.
+ *
+ * E_STRICT is purposivly neglected because such events may have
+ * been caught. Duplication or none? None is preferred for now.
+ *
+ * @link http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a
+ * @return void
+ */
+ function _shutdown_handler()
+ {
+ $last_error = error_get_last();
+ if (isset($last_error) &&
+ ($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))
+ {
+ _exception_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
+ }
}
}
diff --git a/system/core/Config.php b/system/core/Config.php
index 7e64444bc..a0e830abe 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -184,16 +184,16 @@ class CI_Config {
*
* @param string $item Config item name
* @param string $index Index name
- * @return string|bool The configuration item or FALSE on failure
+ * @return string|null The configuration item or NULL if the item doesn't exist
*/
public function item($item, $index = '')
{
if ($index == '')
{
- return isset($this->config[$item]) ? $this->config[$item] : FALSE;
+ return isset($this->config[$item]) ? $this->config[$item] : NULL;
}
- return isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : FALSE;
+ return isset($this->config[$index], $this->config[$index][$item]) ? $this->config[$index][$item] : NULL;
}
// --------------------------------------------------------------------
@@ -202,13 +202,13 @@ class CI_Config {
* Fetch a config file item with slash appended (if not empty)
*
* @param string $item Config item name
- * @return string|bool The configuration item or FALSE on failure
+ * @return string|null The configuration item or NULL if the item doesn't exist
*/
public function slash_item($item)
{
if ( ! isset($this->config[$item]))
{
- return FALSE;
+ return NULL;
}
elseif (trim($this->config[$item]) === '')
{
@@ -228,13 +228,21 @@ class CI_Config {
* @uses CI_Config::_uri_string()
*
* @param string|string[] $uri URI string or an array of segments
+ * @param string $protocol
* @return string
*/
- public function site_url($uri = '')
+ public function site_url($uri = '', $protocol = NULL)
{
+ $base_url = $this->slash_item('base_url');
+
+ if (isset($protocol))
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
+
if (empty($uri))
{
- return $this->slash_item('base_url').$this->item('index_page');
+ return $base_url.$this->item('index_page');
}
$uri = $this->_uri_string($uri);
@@ -255,14 +263,14 @@ class CI_Config {
}
}
- return $this->slash_item('base_url').$this->slash_item('index_page').$uri;
+ return $base_url.$this->slash_item('index_page').$uri;
}
elseif (strpos($uri, '?') === FALSE)
{
$uri = '?'.$uri;
}
- return $this->slash_item('base_url').$this->item('index_page').$uri;
+ return $base_url.$this->item('index_page').$uri;
}
// -------------------------------------------------------------
@@ -275,11 +283,19 @@ class CI_Config {
* @uses CI_Config::_uri_string()
*
* @param string|string[] $uri URI string or an array of segments
+ * @param string $protocol
* @return string
*/
- public function base_url($uri = '')
+ public function base_url($uri = '', $protocol = NULL)
{
- return $this->slash_item('base_url').ltrim($this->_uri_string($uri), '/');
+ $base_url = $this->slash_item('base_url');
+
+ if (isset($protocol))
+ {
+ $base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+ }
+
+ return $base_url.ltrim($this->_uri_string($uri), '/');
}
// -------------------------------------------------------------
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index 9c68d06a5..809dc027a 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -91,7 +91,7 @@ class CI_Exceptions {
public function log_exception($severity, $message, $filepath, $line)
{
$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
- log_message('error', 'Severity: '.$severity.' --> '.$message. ' '.$filepath.' '.$line, TRUE);
+ log_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line);
}
// --------------------------------------------------------------------
@@ -107,13 +107,21 @@ class CI_Exceptions {
*/
public function show_404($page = '', $log_error = TRUE)
{
- $heading = '404 Page Not Found';
- $message = 'The page you requested was not found.';
+ if (is_cli())
+ {
+ $heading = 'Not Found';
+ $message = 'The controller/method pair you requested was not found.';
+ }
+ else
+ {
+ $heading = '404 Page Not Found';
+ $message = 'The page you requested was not found.';
+ }
// By default we log this, but allow a dev to skip it
if ($log_error)
{
- log_message('error', '404 Page Not Found --> '.$page);
+ log_message('error', $heading.': '.$page);
}
echo $this->show_error($heading, $message, 'error_404', 404);
@@ -137,16 +145,24 @@ class CI_Exceptions {
*/
public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
{
- set_status_header($status_code);
-
- $message = '<p>'.implode('</p><p>', is_array($message) ? $message : array($message)).'</p>';
+ if (is_cli())
+ {
+ $message = "\t".(is_array($message) ? implode("\n\t", $message) : $message);
+ $template = 'cli'.DIRECTORY_SEPARATOR.$template;
+ }
+ else
+ {
+ set_status_header($status_code);
+ $message = '<p>'.(is_array($message) ? implode('</p><p>', $message) : $message).'</p>';
+ $template = 'html'.DIRECTORY_SEPARATOR.$template;
+ }
if (ob_get_level() > $this->ob_level + 1)
{
ob_end_flush();
}
ob_start();
- include(VIEWPATH.'errors/'.$template.'.php');
+ include(VIEWPATH.'errors'.DIRECTORY_SEPARATOR.$template.'.php');
$buffer = ob_get_contents();
ob_end_clean();
return $buffer;
@@ -166,13 +182,22 @@ class CI_Exceptions {
public function show_php_error($severity, $message, $filepath, $line)
{
$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
- $filepath = str_replace('\\', '/', $filepath);
- // For safety reasons we do not show the full file path
- if (FALSE !== strpos($filepath, '/'))
+ // For safety reasons we don't show the full file path in non-CLI requests
+ if ( ! is_cli())
+ {
+ $filepath = str_replace('\\', '/', $filepath);
+ if (FALSE !== strpos($filepath, '/'))
+ {
+ $x = explode('/', $filepath);
+ $filepath = $x[count($x)-2].'/'.end($x);
+ }
+
+ $template = 'html'.DIRECTORY_SEPARATOR.'error_php';
+ }
+ else
{
- $x = explode('/', $filepath);
- $filepath = $x[count($x)-2].'/'.end($x);
+ $template = 'cli'.DIRECTORY_SEPARATOR.'error_php';
}
if (ob_get_level() > $this->ob_level + 1)
@@ -180,7 +205,7 @@ class CI_Exceptions {
ob_end_flush();
}
ob_start();
- include(VIEWPATH.'errors/error_php.php');
+ include(VIEWPATH.'errors'.DIRECTORY_SEPARATOR.$template.'.php');
$buffer = ob_get_contents();
ob_end_clean();
echo $buffer;
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
index b3b111991..9bcc23a65 100644
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -54,6 +54,13 @@ class CI_Hooks {
public $hooks = array();
/**
+ * Array with class objects to use hooks methods
+ *
+ * @var array
+ */
+ protected $_objects = array();
+
+ /**
* In progress flag
*
* Determines whether hook is in progress, used to prevent infinte loops
@@ -184,7 +191,7 @@ class CI_Hooks {
$function = empty($data['function']) ? FALSE : $data['function'];
$params = isset($data['params']) ? $data['params'] : '';
- if ($class === FALSE && $function === FALSE)
+ if (empty($function))
{
return FALSE;
}
@@ -195,19 +202,39 @@ class CI_Hooks {
// Call the requested class and/or function
if ($class !== FALSE)
{
- if ( ! class_exists($class, FALSE))
+ // The object is stored?
+ if (isset($this->_objects[$class]))
{
- require($filepath);
+ if (method_exists($this->_objects[$class], $function))
+ {
+ $this->_objects[$class]->$function($params);
+ }
+ else
+ {
+ return $this->_in_progress = FALSE;
+ }
}
+ else
+ {
+ class_exists($class, FALSE) OR require_once($filepath);
+
+ if ( ! class_exists($class, FALSE) OR ! method_exists($class, $function))
+ {
+ return $this->_in_progress = FALSE;
+ }
- $HOOK = new $class();
- $HOOK->$function($params);
+ // Store the object and execute the method
+ $this->_objects[$class] = new $class();
+ $this->_objects[$class]->$function($params);
+ }
}
else
{
+ function_exists($function) OR require_once($filepath);
+
if ( ! function_exists($function))
{
- require($filepath);
+ return $this->_in_progress = FALSE;
}
$function($params);
diff --git a/system/core/Input.php b/system/core/Input.php
index 0ef81128e..ccb70daec 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -47,7 +47,7 @@ class CI_Input {
public $ip_address = FALSE;
/**
- * User agent strin
+ * User agent string
*
* @var string
*/
@@ -63,7 +63,7 @@ class CI_Input {
protected $_allow_get_array = TRUE;
/**
- * Standartize new lines flag
+ * Standardize new lines flag
*
* If set to TRUE, then newlines are standardized.
*
@@ -121,9 +121,10 @@ class CI_Input {
{
log_message('debug', 'Input Class Initialized');
- $this->_allow_get_array = (config_item('allow_get_array') === TRUE);
- $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
- $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
+ $this->_allow_get_array = (config_item('allow_get_array') === TRUE);
+ $this->_enable_xss = (config_item('global_xss_filtering') === TRUE);
+ $this->_enable_csrf = (config_item('csrf_protection') === TRUE);
+ $this->_sandardize_newlines = (bool) config_item('standardize_newlines');
global $SEC;
$this->security =& $SEC;
@@ -151,8 +152,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- protected function _fetch_from_array(&$array, $index = '', $xss_clean = FALSE)
+ protected function _fetch_from_array(&$array, $index = '', $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
if (isset($array[$index]))
{
$value = $array[$index];
@@ -197,8 +200,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function get($index = NULL, $xss_clean = FALSE)
+ public function get($index = NULL, $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
// Check if a field has been provided
if ($index === NULL)
{
@@ -229,8 +234,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function post($index = NULL, $xss_clean = FALSE)
+ public function post($index = NULL, $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
// Check if a field has been provided
if ($index === NULL)
{
@@ -261,8 +268,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function get_post($index = '', $xss_clean = FALSE)
+ public function post_get($index = '', $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
return isset($_POST[$index])
? $this->post($index, $xss_clean)
: $this->get($index, $xss_clean);
@@ -271,14 +280,34 @@ class CI_Input {
// --------------------------------------------------------------------
/**
+ * Fetch an item from GET data with fallback to POST
+ *
+ * @param string $index Index for item to be fetched from $_GET or $_POST
+ * @param bool $xss_clean Whether to apply XSS filtering
+ * @return mixed
+ */
+ public function get_post($index = '', $xss_clean = NULL)
+ {
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
+ return isset($_GET[$index])
+ ? $this->get($index, $xss_clean)
+ : $this->post($index, $xss_clean);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Fetch an item from the COOKIE array
*
* @param string $index Index for item to be fetched from $_COOKIE
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function cookie($index = '', $xss_clean = FALSE)
+ public function cookie($index = '', $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
return $this->_fetch_from_array($_COOKIE, $index, $xss_clean);
}
@@ -291,8 +320,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function server($index = '', $xss_clean = FALSE)
+ public function server($index = '', $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
return $this->_fetch_from_array($_SERVER, $index, $xss_clean);
}
@@ -307,8 +338,10 @@ class CI_Input {
* @param bool $xss_clean Whether to apply XSS filtering
* @return mixed
*/
- public function input_stream($index = '', $xss_clean = FALSE)
+ public function input_stream($index = '', $xss_clean = NULL)
{
+ is_bool($xss_clean) OR $xss_clean = $this->_enable_xss;
+
// The input stream can only be read once, so we'll need to check
// if we have already done that first.
if (is_array($this->_input_stream))
@@ -345,7 +378,7 @@ class CI_Input {
* @param bool $httponly Whether to only makes the cookie accessible via HTTP (no javascript)
* @return void
*/
- public function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
+ public function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
{
if (is_array($name))
{
@@ -671,13 +704,22 @@ class CI_Input {
// but that when present will trip our 'Disallowed Key Characters' alarm
// http://www.ietf.org/rfc/rfc2109.txt
// note that the key names below are single quoted strings, and are not PHP variables
- unset($_COOKIE['$Version']);
- unset($_COOKIE['$Path']);
- unset($_COOKIE['$Domain']);
+ unset(
+ $_COOKIE['$Version'],
+ $_COOKIE['$Path'],
+ $_COOKIE['$Domain']
+ );
foreach ($_COOKIE as $key => $val)
{
- $_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+ if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
+ {
+ $_COOKIE[$cookie_key] = $this->_clean_input_data($val);
+ }
+ else
+ {
+ unset($_COOKIE[$key]);
+ }
}
}
@@ -685,12 +727,12 @@ class CI_Input {
$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
// CSRF Protection check
- if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
+ if ($this->_enable_csrf === TRUE && ! is_cli())
{
$this->security->csrf_verify();
}
- log_message('debug', 'Global POST and COOKIE data sanitized');
+ log_message('debug', 'Global POST, GET and COOKIE data sanitized');
}
// --------------------------------------------------------------------
@@ -733,13 +775,7 @@ class CI_Input {
}
// Remove control characters
- $str = remove_invisible_characters($str);
-
- // Should we filter the input data?
- if ($this->_enable_xss === TRUE)
- {
- $str = $this->security->xss_clean($str);
- }
+ $str = remove_invisible_characters($str, FALSE);
// Standardize newlines if needed
if ($this->_standardize_newlines === TRUE)
@@ -760,15 +796,25 @@ class CI_Input {
* only named with alpha-numeric text and a few other items.
*
* @param string $str Input string
- * @return string
+ * @param string $fatal Whether to terminate script exection
+ * or to return FALSE if an invalid
+ * key is encountered
+ * @return string|bool
*/
- protected function _clean_input_keys($str)
+ protected function _clean_input_keys($str, $fatal = TRUE)
{
if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
{
- set_status_header(503);
- echo 'Disallowed Key Characters.';
- exit(EXIT_USER_INPUT);
+ if ($fatal === TRUE)
+ {
+ return FALSE;
+ }
+ else
+ {
+ set_status_header(503);
+ echo 'Disallowed Key Characters.';
+ exit(EXIT_USER_INPUT);
+ }
}
// Clean UTF-8 if supported
@@ -868,11 +914,12 @@ class CI_Input {
*
* Test to see if a request was made from the command line.
*
- * @return bool
+ * @deprecated 3.0.0 Use is_cli() instead
+ * @return bool
*/
public function is_cli_request()
{
- return (php_sapi_name() === 'cli' OR defined('STDIN'));
+ return is_cli();
}
// --------------------------------------------------------------------
diff --git a/system/core/Lang.php b/system/core/Lang.php
index 3236709f2..290b38bea 100644
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -166,7 +166,7 @@ class CI_Lang {
* @param bool $log_errors Whether to log an error message if the line is not found
* @return string Translation
*/
- public function line($line = '', $log_errors = TRUE)
+ public function line($line, $log_errors = TRUE)
{
$value = ($line === '' OR ! isset($this->language[$line])) ? FALSE : $this->language[$line];
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 70a6b6fa6..8c8d5a37c 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -76,13 +76,6 @@ class CI_Loader {
protected $_ci_helper_paths = array(APPPATH, BASEPATH);
/**
- * List of loaded base classes
- *
- * @var array
- */
- protected $_base_classes = array(); // Set by the controller class
-
- /**
* List of cached variables
*
* @var array
@@ -120,6 +113,8 @@ class CI_Loader {
'user_agent' => 'agent'
);
+ // --------------------------------------------------------------------
+
/**
* Class constructor
*
@@ -129,7 +124,8 @@ class CI_Loader {
*/
public function __construct()
{
- $this->_ci_ob_level = ob_get_level();
+ $this->_ci_ob_level = ob_get_level();
+ $this->_ci_classes =& is_loaded();
log_message('debug', 'Loader Class Initialized');
}
@@ -147,7 +143,6 @@ class CI_Loader {
*/
public function initialize()
{
- $this->_base_classes =& is_loaded();
$this->_ci_autoloader();
}
@@ -165,7 +160,7 @@ class CI_Loader {
*/
public function is_loaded($class)
{
- return isset($this->_ci_classes[$class]) ? $this->_ci_classes[$class] : FALSE;
+ return array_search(ucfirst($class), $this->_ci_classes, TRUE);
}
// --------------------------------------------------------------------
@@ -179,23 +174,29 @@ class CI_Loader {
* @param string $library Library name
* @param array $params Optional parameters to pass to the library class constructor
* @param string $object_name An optional object name to assign to
- * @return void
+ * @return object
*/
- public function library($library = '', $params = NULL, $object_name = NULL)
+ public function library($library, $params = NULL, $object_name = NULL)
{
- if (is_array($library))
+ if (empty($library))
+ {
+ return $this;
+ }
+ elseif (is_array($library))
{
- foreach ($library as $class)
+ foreach ($library as $key => $value)
{
- $this->library($class, $params);
+ if (is_int($key))
+ {
+ $this->library($value, $params);
+ }
+ else
+ {
+ $this->library($key, $params, $value);
+ }
}
- return;
- }
-
- if ($library === '' OR isset($this->_base_classes[$library]))
- {
- return;
+ return $this;
}
if ($params !== NULL && ! is_array($params))
@@ -204,6 +205,7 @@ class CI_Loader {
}
$this->_ci_load_class($library, $params, $object_name);
+ return $this;
}
// --------------------------------------------------------------------
@@ -216,21 +218,22 @@ class CI_Loader {
* @param string $model Model name
* @param string $name An optional object name to assign to
* @param bool $db_conn An optional database connection configuration to initialize
- * @return void
+ * @return object
*/
public function model($model, $name = '', $db_conn = FALSE)
{
if (empty($model))
{
- return;
+ return $this;
}
elseif (is_array($model))
{
foreach ($model as $key => $value)
{
- $this->model(is_int($key) ? $value : $key, $value);
+ is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
}
- return;
+
+ return $this;
}
$path = '';
@@ -252,7 +255,7 @@ class CI_Loader {
if (in_array($name, $this->_ci_models, TRUE))
{
- return;
+ return $this;
}
$CI =& get_instance();
@@ -261,36 +264,35 @@ class CI_Loader {
show_error('The model name you are loading is the name of a resource that is already being used: '.$name);
}
- $model = strtolower($model);
-
- foreach ($this->_ci_model_paths as $mod_path)
+ if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
{
- if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
+ if ($db_conn === TRUE)
{
- continue;
+ $db_conn = '';
}
- if ($db_conn !== FALSE && ! class_exists('CI_DB', FALSE))
- {
- if ($db_conn === TRUE)
- {
- $db_conn = '';
- }
+ $CI->load->database($db_conn, FALSE, TRUE);
+ }
- $CI->load->database($db_conn, FALSE, TRUE);
- }
+ if ( ! class_exists('CI_Model', FALSE))
+ {
+ load_class('Model', 'core');
+ }
- if ( ! class_exists('CI_Model', FALSE))
+ $model = ucfirst(strtolower($model));
+
+ foreach ($this->_ci_model_paths as $mod_path)
+ {
+ if ( ! file_exists($mod_path.'models/'.$path.$model.'.php'))
{
- load_class('Model', 'core');
+ continue;
}
require_once($mod_path.'models/'.$path.$model.'.php');
- $model = ucfirst($model);
$CI->$name = new $model();
$this->_ci_models[] = $name;
- return;
+ return $this;
}
// couldn't find the model
@@ -307,8 +309,8 @@ class CI_Loader {
* @param bool $query_builder Whether to enable Query Builder
* (overrides the configuration setting)
*
- * @return void|object|bool Database object if $return is set to TRUE,
- * FALSE on failure, void in any other case
+ * @return object|bool Database object if $return is set to TRUE,
+ * FALSE on failure, CI_Loader instance in any other case
*/
public function database($params = '', $return = FALSE, $query_builder = NULL)
{
@@ -334,6 +336,7 @@ class CI_Loader {
// Load the DB class
$CI->db =& DB($params, $query_builder);
+ return $this;
}
// --------------------------------------------------------------------
@@ -342,8 +345,8 @@ class CI_Loader {
* Load the Database Utilities Class
*
* @param object $db Database object
- * @param bool $return Whether to return the DB Forge class object or not
- * @return void|object
+ * @param bool $return Whether to return the DB Utilities class object or not
+ * @return object
*/
public function dbutil($db = NULL, $return = FALSE)
{
@@ -365,6 +368,7 @@ class CI_Loader {
}
$CI->dbutil = new $class($db);
+ return $this;
}
// --------------------------------------------------------------------
@@ -374,7 +378,7 @@ class CI_Loader {
*
* @param object $db Database object
* @param bool $return Whether to return the DB Forge class object or not
- * @return void|object
+ * @return object
*/
public function dbforge($db = NULL, $return = FALSE)
{
@@ -408,6 +412,7 @@ class CI_Loader {
}
$CI->dbforge = new $class($db);
+ return $this;
}
// --------------------------------------------------------------------
@@ -422,7 +427,7 @@ class CI_Loader {
* to be extracted for use in the view
* @param bool $return Whether to return the view output
* or leave it to the Output class
- * @return void
+ * @return object|string
*/
public function view($view, $vars = array(), $return = FALSE)
{
@@ -436,7 +441,7 @@ class CI_Loader {
*
* @param string $path File path
* @param bool $return Whether to return the file output
- * @return void|string
+ * @return object|string
*/
public function file($path, $return = FALSE)
{
@@ -455,9 +460,9 @@ class CI_Loader {
* An associative array or object containing values
* to be set, or a value's name if string
* @param string $val Value to set, only used if $vars is a string
- * @return void
+ * @return object
*/
- public function vars($vars = array(), $val = '')
+ public function vars($vars, $val = '')
{
if (is_string($vars))
{
@@ -473,6 +478,23 @@ class CI_Loader {
$this->_ci_cached_vars[$key] = $val;
}
}
+
+ return $this;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Clear Cached Variables
+ *
+ * Clears the cached variables.
+ *
+ * @return object
+ */
+ public function clear_vars()
+ {
+ $this->_ci_cached_vars = array();
+ return $this;
}
// --------------------------------------------------------------------
@@ -510,7 +532,7 @@ class CI_Loader {
* Helper Loader
*
* @param string|string[] $helpers Helper name(s)
- * @return void
+ * @return object
*/
public function helper($helpers = array())
{
@@ -567,6 +589,8 @@ class CI_Loader {
show_error('Unable to load the requested file: helpers/'.$helper.'.php');
}
}
+
+ return $this;
}
// --------------------------------------------------------------------
@@ -579,11 +603,11 @@ class CI_Loader {
*
* @uses CI_Loader::helper()
* @param string|string[] $helpers Helper name(s)
- * @return void
+ * @return object
*/
public function helpers($helpers = array())
{
- $this->helper($helpers);
+ return $this->helper($helpers);
}
// --------------------------------------------------------------------
@@ -595,18 +619,19 @@ class CI_Loader {
*
* @param string|string[] $files List of language file names to load
* @param string Language name
- * @return void
+ * @return object
*/
- public function language($files = array(), $lang = '')
+ public function language($files, $lang = '')
{
$CI =& get_instance();
-
is_array($files) OR $files = array($files);
foreach ($files as $langfile)
{
$CI->lang->load($langfile, $lang);
}
+
+ return $this;
}
// --------------------------------------------------------------------
@@ -622,10 +647,9 @@ class CI_Loader {
* @param bool $fail_gracefully Whether to just return FALSE or display an error message
* @return bool TRUE if the file was loaded correctly or FALSE on failure
*/
- public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
+ public function config($file, $use_sections = FALSE, $fail_gracefully = FALSE)
{
- $CI =& get_instance();
- return $CI->config->load($file, $use_sections, $fail_gracefully);
+ return get_instance()->config->load($file, $use_sections, $fail_gracefully);
}
// --------------------------------------------------------------------
@@ -639,10 +663,10 @@ class CI_Loader {
* @param array $params Optional parameters to pass to the driver
* @param string $object_name An optional object name to assign to
*
- * @return void|object|bool Object or FALSE on failure if $library is a string
- * and $object_name is set. void otherwise.
+ * @return object|bool Object or FALSE on failure if $library is a string
+ * and $object_name is set. CI_Loader instance otherwise.
*/
- public function driver($library = '', $params = NULL, $object_name = NULL)
+ public function driver($library, $params = NULL, $object_name = NULL)
{
if (is_array($library))
{
@@ -650,10 +674,10 @@ class CI_Loader {
{
$this->driver($driver);
}
- return;
- }
- if ($library === '')
+ return $this;
+ }
+ elseif (empty($library))
{
return FALSE;
}
@@ -689,7 +713,7 @@ class CI_Loader {
*
* @param string $path Path to add
* @param bool $view_cascade (default: TRUE)
- * @return void
+ * @return object
*/
public function add_package_path($path, $view_cascade = TRUE)
{
@@ -704,6 +728,8 @@ class CI_Loader {
// Add config file path
$config =& $this->_ci_get_component('config');
$config->_config_paths[] = $path;
+
+ return $this;
}
// --------------------------------------------------------------------
@@ -731,7 +757,7 @@ class CI_Loader {
* added path will be removed removed.
*
* @param string $path Path to remove
- * @return void
+ * @return object
*/
public function remove_package_path($path = '')
{
@@ -773,6 +799,8 @@ class CI_Loader {
$this->_ci_model_paths = array_unique(array_merge($this->_ci_model_paths, array(APPPATH)));
$this->_ci_view_paths = array_merge($this->_ci_view_paths, array(APPPATH.'views/' => TRUE));
$config->_config_paths = array_unique(array_merge($config->_config_paths, array(APPPATH)));
+
+ return $this;
}
// --------------------------------------------------------------------
@@ -788,7 +816,7 @@ class CI_Loader {
* @used-by CI_Loader::view()
* @used-by CI_Loader::file()
* @param array $_ci_data Data to load
- * @return void
+ * @return object
*/
protected function _ci_load($_ci_data)
{
@@ -912,6 +940,8 @@ class CI_Loader {
$_ci_CI->output->append_output(ob_get_contents());
@ob_end_clean();
}
+
+ return $this;
}
// --------------------------------------------------------------------
@@ -1118,30 +1148,35 @@ class CI_Loader {
// Set the variable name we will assign the class to
// Was a custom class name supplied? If so we'll use it
- $class = strtolower($class);
-
- if ($object_name === NULL)
+ if (empty($object_name))
{
- $classvar = isset($this->_ci_varmap[$class]) ? $this->_ci_varmap[$class] : $class;
+ $object_name = strtolower($class);
+ if (isset($this->_ci_varmap[$object_name]))
+ {
+ $object_name = $this->_ci_varmap[$object_name];
+ }
}
- else
+
+ // Don't overwrite existing properties
+ $CI =& get_instance();
+ if (isset($CI->$object_name))
{
- $classvar = $object_name;
+ if ($CI->$object_name instanceof $name)
+ {
+ log_message('debug', $class." has already been instantiated as '".$object_name."'. Second attempt aborted.");
+ return;
+ }
+
+ show_error("Resource '".$object_name."' already exists and is not a ".$class." instance.");
}
// Save the class name and object name
- $this->_ci_classes[$class] = $classvar;
+ $this->_ci_classes[$object_name] = $class;
// Instantiate the class
- $CI =& get_instance();
- if ($config !== NULL)
- {
- $CI->$classvar = new $name($config);
- }
- else
- {
- $CI->$classvar = new $name();
- }
+ $CI->$object_name = isset($config)
+ ? new $name($config)
+ : new $name();
}
// --------------------------------------------------------------------
@@ -1198,6 +1233,15 @@ class CI_Loader {
}
}
+ // Autoload drivers
+ if (isset($autoload['drivers']))
+ {
+ foreach ($autoload['drivers'] as $item)
+ {
+ $this->driver($item);
+ }
+ }
+
// Load libraries
if (isset($autoload['libraries']) && count($autoload['libraries']) > 0)
{
@@ -1215,15 +1259,6 @@ class CI_Loader {
}
}
- // Autoload drivers
- if (isset($autoload['drivers']))
- {
- foreach ($autoload['drivers'] as $item)
- {
- $this->driver($item);
- }
- }
-
// Autoload models
if (isset($autoload['model']))
{
diff --git a/system/core/Log.php b/system/core/Log.php
index e4d72b544..63fef2088 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -140,10 +140,9 @@ class CI_Log {
*
* @param string the error level: 'error', 'debug' or 'info'
* @param string the error message
- * @param bool whether the error is a native PHP error
* @return bool
*/
- public function write_log($level, $msg, $php_error = FALSE)
+ public function write_log($level, $msg)
{
if ($this->_enabled === FALSE)
{
@@ -176,10 +175,18 @@ class CI_Log {
return FALSE;
}
- $message .= $level.' '.($level === 'INFO' ? ' -' : '-').' '.date($this->_date_fmt).' --> '.$msg."\n";
+ $message .= $level.' - '.date($this->_date_fmt).' --> '.$msg."\n";
flock($fp, LOCK_EX);
- fwrite($fp, $message);
+
+ for ($written = 0, $length = strlen($message); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($message, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
flock($fp, LOCK_UN);
fclose($fp);
@@ -188,7 +195,7 @@ class CI_Log {
@chmod($filepath, FILE_WRITE_MODE);
}
- return TRUE;
+ return is_int($result);
}
}
diff --git a/system/core/Model.php b/system/core/Model.php
index 1eb6f909b..11e60759b 100644
--- a/system/core/Model.php
+++ b/system/core/Model.php
@@ -59,8 +59,7 @@ class CI_Model {
*/
public function __get($key)
{
- $CI =& get_instance();
- return $CI->$key;
+ return get_instance()->$key;
}
}
diff --git a/system/core/Output.php b/system/core/Output.php
index 06d7a866b..2ad8e90fa 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -58,21 +58,21 @@ class CI_Output {
*
* @var array
*/
- public $headers = array();
+ public $headers = array();
/**
* List of mime types
*
* @var array
*/
- public $mimes = array();
+ public $mimes = array();
/**
* Mime-type for the current page
*
* @var string
*/
- protected $mime_type = 'text/html';
+ protected $mime_type = 'text/html';
/**
* Enable Profiler flag
@@ -82,11 +82,18 @@ class CI_Output {
public $enable_profiler = FALSE;
/**
- * zLib output compression flag
+ * php.ini zlib.output_compression flag
*
* @var bool
*/
- protected $_zlib_oc = FALSE;
+ protected $_zlib_oc = FALSE;
+
+ /**
+ * CI output compression flag
+ *
+ * @var bool
+ */
+ protected $_compress_output = FALSE;
/**
* List of profiler sections
@@ -102,7 +109,7 @@ class CI_Output {
*
* @var bool
*/
- public $parse_exec_vars = TRUE;
+ public $parse_exec_vars = TRUE;
/**
* Class constructor
@@ -114,6 +121,11 @@ class CI_Output {
public function __construct()
{
$this->_zlib_oc = (bool) @ini_get('zlib.output_compression');
+ $this->_compress_output = (
+ $this->_zlib_oc === FALSE
+ && config_item('compress_output') === TRUE
+ && extension_loaded('zlib')
+ );
// Get mime types for later
$this->mimes =& get_mimes();
@@ -436,15 +448,14 @@ class CI_Output {
if ($this->parse_exec_vars === TRUE)
{
$memory = round(memory_get_usage() / 1024 / 1024, 2).'MB';
-
$output = str_replace(array('{elapsed_time}', '{memory_usage}'), array($elapsed, $memory), $output);
}
// --------------------------------------------------------------------
// Is compression requested?
- if ($CFG->item('compress_output') === TRUE && $this->_zlib_oc === FALSE
- && extension_loaded('zlib')
+ if (isset($CI) // This means that we're not serving a cache file, if we were, it would already be compressed
+ && $this->_compress_output === TRUE
&& isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
{
ob_start('ob_gzhandler');
@@ -468,6 +479,21 @@ class CI_Output {
// simply echo out the data and exit.
if ( ! isset($CI))
{
+ if ($this->_compress_output === TRUE)
+ {
+ if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) && strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
+ {
+ header('Content-Encoding: gzip');
+ header('Content-Length: '.strlen($output));
+ }
+ else
+ {
+ // User agent doesn't support gzip compression,
+ // so we'll have to decompress our cache
+ $output = gzinflate(substr($output, 10, -8));
+ }
+ }
+
echo $output;
log_message('debug', 'Final output sent to browser');
log_message('debug', 'Total execution time: '.$elapsed);
@@ -530,9 +556,9 @@ class CI_Output {
return;
}
- $uri = $CI->config->item('base_url').
- $CI->config->item('index_page').
- $CI->uri->uri_string();
+ $uri = $CI->config->item('base_url')
+ .$CI->config->item('index_page')
+ .$CI->uri->uri_string();
$cache_path .= md5($uri);
@@ -542,17 +568,39 @@ class CI_Output {
return;
}
- $expire = time() + ($this->cache_expiration * 60);
-
- // Put together our serialized info.
- $cache_info = serialize(array(
- 'expire' => $expire,
- 'headers' => $this->headers
- ));
-
if (flock($fp, LOCK_EX))
{
- fwrite($fp, $cache_info.'ENDCI--->'.$output);
+ // If output compression is enabled, compress the cache
+ // itself, so that we don't have to do that each time
+ // we're serving it
+ if ($this->_compress_output === TRUE)
+ {
+ $output = gzencode($output);
+
+ if ($this->get_header('content-type') === NULL)
+ {
+ $this->set_content_type($this->mime_type);
+ }
+ }
+
+ $expire = time() + ($this->cache_expiration * 60);
+
+ // Put together our serialized info.
+ $cache_info = serialize(array(
+ 'expire' => $expire,
+ 'headers' => $this->headers
+ ));
+
+ $output = $cache_info.'ENDCI--->'.$output;
+
+ for ($written = 0, $length = strlen($output); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($output, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
flock($fp, LOCK_UN);
}
else
@@ -560,13 +608,22 @@ class CI_Output {
log_message('error', 'Unable to secure a file lock for file at: '.$cache_path);
return;
}
+
fclose($fp);
- @chmod($cache_path, FILE_WRITE_MODE);
- log_message('debug', 'Cache file written: '.$cache_path);
+ if (is_int($result))
+ {
+ @chmod($cache_path, FILE_WRITE_MODE);
+ log_message('debug', 'Cache file written: '.$cache_path);
- // Send HTTP cache-control headers to browser to match file cache settings.
- $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
+ // Send HTTP cache-control headers to browser to match file cache settings.
+ $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire);
+ }
+ else
+ {
+ @unlink($cache_path);
+ log_message('error', 'Unable to write the complete cache content at: '.$cache_path);
+ }
}
// --------------------------------------------------------------------
@@ -701,7 +758,7 @@ class CI_Output {
else
{
header('Pragma: public');
- header('Cache-Control: max-age=' . $max_age . ', public');
+ header('Cache-Control: max-age='.$max_age.', public');
header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
}
@@ -740,13 +797,13 @@ class CI_Output {
preg_match_all('{<style.+</style>}msU', $output, $style_clean);
foreach ($style_clean[0] as $s)
{
- $output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
+ $output = str_replace($s, $this->_minify_js_css($s, 'css', TRUE), $output);
}
// Minify the javascript in <script> tags.
foreach ($javascript_clean[0] as $s)
{
- $javascript_mini[] = $this->_minify_script_style($s, TRUE);
+ $javascript_mini[] = $this->_minify_js_css($s, 'js', TRUE);
}
// Replace multiple spaces with a single space.
@@ -792,13 +849,14 @@ class CI_Output {
break;
case 'text/css':
+
+ return $this->_minify_js_css($output, 'css');
+
case 'text/javascript':
case 'application/javascript':
case 'application/x-javascript':
- $output = $this->_minify_script_style($output);
-
- break;
+ return $this->_minify_js_css($output, 'js');
default: break;
}
@@ -809,134 +867,100 @@ class CI_Output {
// --------------------------------------------------------------------
/**
- * Minify Style and Script
- *
- * Reduce excessive size of CSS/JavaScript content. To remove spaces this
- * script walks the string as an array and determines if the pointer is inside
- * a string created by single quotes or double quotes. spaces inside those
- * strings are not stripped. Opening and closing tags are severed from
- * the string initially and saved without stripping whitespace to preserve
- * the tags and any associated properties if tags are present
+ * Minify JavaScript and CSS code
*
- * Minification logic/workflow is similar to methods used by Douglas Crockford
- * in JSMIN. http://www.crockford.com/javascript/jsmin.html
+ * Strips comments and excessive whitespace characters
*
- * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
- * where there should be one will break the Javascript. New lines after a
- * closing parenthesis are not recognized by the script. For best results
- * be sure to terminate lines with a semicolon when appropriate.
- *
- * @param string $output Output to minify
- * @param bool $has_tags Specify if the output has style or script tags
- * @return string Minified output
+ * @param string $output
+ * @param string $type 'js' or 'css'
+ * @param bool $tags Whether $output contains the 'script' or 'style' tag
+ * @return string
*/
- protected function _minify_script_style($output, $has_tags = FALSE)
+ protected function _minify_js_css($output, $type, $tags = FALSE)
{
- // We only need this if there are tags in the file
- if ($has_tags === TRUE)
+ if ($tags === TRUE)
{
- // Remove opening tag and save for later
- $pos = strpos($output, '>') + 1;
- $open_tag = substr($output, 0, $pos);
- $output = substr_replace($output, '', 0, $pos);
+ $tags = array('close' => strrchr($output, '<'));
- // Remove closing tag and save it for later
- $pos = strpos($output, '</');
- $closing_tag = substr($output, $pos, strlen($output));
- $output = substr_replace($output, '', $pos);
- }
+ $open_length = strpos($output, '>') + 1;
+ $tags['open'] = substr($output, 0, $open_length);
- // Remove CSS comments
- $output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!i', '', $output);
+ $output = substr($output, $open_length, -strlen($tags['close']));
- // Remove spaces around curly brackets, colons,
- // semi-colons, parenthesis, commas
- $chunks = preg_split('/([\'|"]).+(?![^\\\]\\1)\\1/iU', $output, -1, PREG_SPLIT_OFFSET_CAPTURE);
- for ($i = count($chunks) - 1; $i >= 0; $i--)
- {
- $output = substr_replace(
- $output,
- preg_replace('/\s*(:|;|,|}|{|\(|\))\s*/i', '$1', $chunks[$i][0]),
- $chunks[$i][1],
- strlen($chunks[$i][0])
- );
+ // Strip spaces from the tags
+ $tags = preg_replace('#\s{2,}#', ' ', $tags);
}
- // Replace tabs with spaces
- // Replace carriage returns & multiple new lines with single new line
- // and trim any leading or trailing whitespace
- $output = trim(preg_replace(array('/\t+/', '/\r/', '/\n+/'), array(' ', "\n", "\n"), $output));
+ $output = trim($output);
- // Remove spaces when safe to do so.
- $in_string = $in_dstring = $prev = FALSE;
- $array_output = str_split($output);
- foreach ($array_output as $key => $value)
+ if ($type === 'js')
{
- if ($in_string === FALSE && $in_dstring === FALSE)
+ // Catch all string literals and comment blocks
+ if (preg_match_all('#((?:((?<!\\\)\'|")|(/\*)|(//)).*(?(2)(?<!\\\)\2|(?(3)\*/|\n)))#msuUS', $output, $match, PREG_OFFSET_CAPTURE))
{
- if ($value === ' ')
+ $js_literals = $js_code = array();
+ for ($match = $match[0], $c = count($match), $i = $pos = $offset = 0; $i < $c; $i++)
{
- // Get the next element in the array for comparisons
- $next = $array_output[$key + 1];
-
- // Strip spaces preceded/followed by a non-ASCII character
- // or not preceded/followed by an alphanumeric
- // or not preceded/followed \ $ and _
- if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
- && ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
- && ! in_array($next, array('\\', '_', '$'), TRUE)
- && ! in_array($prev, array('\\', '_', '$'), TRUE)
- )
+ $js_code[$pos++] = trim(substr($output, $offset, $match[$i][1] - $offset));
+ $offset = $match[$i][1] + strlen($match[$i][0]);
+
+ // Save only if we haven't matched a comment block
+ if ($match[$i][0][0] !== '/')
{
- unset($array_output[$key]);
+ $js_literals[$pos++] = array_shift($match[$i]);
}
}
- else
- {
- // Save this value as previous for the next iteration
- // if it is not a blank space
- $prev = $value;
- }
- }
+ $js_code[$pos] = substr($output, $offset);
- if ($value === "'")
- {
- $in_string = ! $in_string;
+ // $match might be quite large, so free it up together with other vars that we no longer need
+ unset($match, $offset, $pos);
}
- elseif ($value === '"')
+ else
{
- $in_dstring = ! $in_dstring;
+ $js_code = array($output);
+ $js_literals = array();
}
+
+ $varname = 'js_code';
+ }
+ else
+ {
+ $varname = 'output';
}
- // Put the string back together after spaces have been stripped
- $output = implode($array_output);
+ // Standartize new lines
+ $$varname = str_replace(array("\r\n", "\r"), "\n", $$varname);
- // Remove new line characters unless previous or next character is
- // printable or Non-ASCII
- preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
- $removed_lf = 0;
- foreach ($lf as $feed_position)
+ if ($type === 'js')
{
- foreach ($feed_position as $position)
- {
- $position = $position[1] - $removed_lf;
- $next = $output[$position + 1];
- $prev = $output[$position - 1];
- if ( ! ctype_print($next) && ! ctype_print($prev)
- && ! preg_match('/^[\x20-\x7f]*$/D', $next)
- && ! preg_match('/^[\x20-\x7f]*$/D', $prev)
- )
- {
- $output = substr_replace($output, '', $position, 1);
- $removed_lf++;
- }
- }
+ $patterns = array(
+ '#\s*([!\#%&()*+,\-./:;<=>?@\[\]^`{|}~])\s*#' => '$1', // Remove spaces following and preceeding JS-wise non-special & non-word characters
+ '#\s{2,}#' => ' ' // Reduce the remaining multiple whitespace characters to a single space
+ );
+ }
+ else
+ {
+ $patterns = array(
+ '#/\*.*(?=\*/)\*/#s' => '', // Remove /* block comments */
+ '#\n?//[^\n]*#' => '', // Remove // line comments
+ '#\s*([^\w.\#%])\s*#U' => '$1', // Remove spaces following and preceeding non-word characters, excluding dots, hashes and the percent sign
+ '#\s{2,}#' => ' ' // Reduce the remaining multiple space characters to a single space
+ );
+ }
+
+ $$varname = preg_replace(array_keys($patterns), array_values($patterns), $$varname);
+
+ // Glue back JS quoted strings
+ if ($type === 'js')
+ {
+ $js_code += $js_literals;
+ ksort($js_code);
+ $output = implode($js_code);
+ unset($js_code, $js_literals, $varname, $patterns);
}
- // Put the opening and closing tags back if applicable
- return isset($open_tag)
- ? $open_tag.$output.$closing_tag
+ return is_array($tags)
+ ? $tags['open'].$output.$tags['close']
: $output;
}
diff --git a/system/core/Router.php b/system/core/Router.php
index cc3916f86..633524023 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -91,6 +91,15 @@ class CI_Router {
*/
public $translate_uri_dashes = FALSE;
+ /**
+ * Enable query strings flag
+ *
+ * Determines wether to use GET parameters or segment URIs
+ *
+ * @var bool
+ */
+ public $enable_query_strings = FALSE;
+
// --------------------------------------------------------------------
/**
@@ -102,9 +111,34 @@ class CI_Router {
*/
public function __construct()
{
+ global $routing;
+
$this->config =& load_class('Config', 'core');
$this->uri =& load_class('URI', 'core');
+
+ $this->enable_query_strings = ( ! is_cli() && $this->config->item('enable_query_strings') === TRUE);
$this->_set_routing();
+
+ // Set any routing overrides that may exist in the main index file
+ if (isset($routing) && is_array($routing))
+ {
+ if (isset($routing['directory']))
+ {
+ $this->set_directory($routing['directory']);
+ }
+
+ if ( ! empty($routing['controller']))
+ {
+ $this->set_class($routing['controller']);
+ }
+
+ if (isset($routing['function']))
+ {
+ $routing['function'] = empty($routing['function']) ? 'index' : $routing['function'];
+ $this->set_method($routing['function']);
+ }
+ }
+
log_message('debug', 'Router Class Initialized');
}
@@ -123,26 +157,39 @@ class CI_Router {
// Are query strings enabled in the config file? Normally CI doesn't utilize query strings
// since URI segments are more search-engine friendly, but they can optionally be used.
// If this feature is enabled, we will gather the directory/class/method a little differently
- $segments = array();
- if ($this->config->item('enable_query_strings') === TRUE
- && ! empty($_GET[$this->config->item('controller_trigger')])
- && is_string($_GET[$this->config->item('controller_trigger')])
- )
+ if ($this->enable_query_strings)
{
- if (isset($_GET[$this->config->item('directory_trigger')]) && is_string($_GET[$this->config->item('directory_trigger')]))
+ $_d = $this->config->item('directory_trigger');
+ $_d = isset($_GET[$_d]) ? trim($_GET[$_d], " \t\n\r\0\x0B/") : '';
+ if ($_d !== '')
{
- $this->set_directory(trim($this->uri->_filter_uri($_GET[$this->config->item('directory_trigger')])));
- $segments[] = $this->directory;
+ $this->set_directory($this->uri->filter_uri($_d));
}
- $this->set_class(trim($this->uri->_filter_uri($_GET[$this->config->item('controller_trigger')])));
- $segments[] = $this->class;
+ $_c = $this->config->item('controller_trigger');
+ if ( ! empty($_GET[$_c]))
+ {
+ $this->set_class(trim($this->uri->filter_uri(trim($_GET[$_c]))));
+
+ $_f = $this->config->item('function_trigger');
+ if ( ! empty($_GET[$_f]))
+ {
+ $this->set_method(trim($this->uri->filter_uri($_GET[$_f])));
+ }
- if ( ! empty($_GET[$this->config->item('function_trigger')]) && is_string($_GET[$this->config->item('function_trigger')]))
+ $this->uri->rsegments = array(
+ 1 => $this->class,
+ 2 => $this->method
+ );
+ }
+ else
{
- $this->set_method(trim($this->uri->_filter_uri($_GET[$this->config->item('function_trigger')])));
- $segments[] = $this->method;
+ $this->_set_default_controller();
}
+
+ // Routing rules don't apply to query strings and we don't need to detect
+ // directories, so we're done here
+ return;
}
// Load the routes.php file.
@@ -165,53 +212,15 @@ class CI_Router {
$this->routes = $route;
}
- // Were there any query string segments? If so, we'll validate them and bail out since we're done.
- if (count($segments) > 0)
+ // Is there anything to parse?
+ if ($this->uri->uri_string !== '')
{
- return $this->_validate_request($segments);
+ $this->_parse_routes();
}
-
- // Fetch the complete URI string
- $this->uri->_fetch_uri_string();
-
- // Is there a URI string? If not, the default controller specified in the "routes" file will be shown.
- if ($this->uri->uri_string == '')
+ else
{
- return $this->_set_default_controller();
+ $this->_set_default_controller();
}
-
- $this->uri->_remove_url_suffix(); // Remove the URL suffix
- $this->uri->_explode_segments(); // Compile the segments into an array
- $this->_parse_routes(); // Parse any custom routing that may exist
- $this->uri->_reindex_segments(); // Re-index the segment array so that it starts with 1 rather than 0
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Set default controller
- *
- * @return void
- */
- protected function _set_default_controller()
- {
- if (empty($this->default_controller))
- {
- show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
- }
-
- // Is the method being specified?
- if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
- {
- $method = 'index';
- }
-
- $this->_set_request(array($class, $method));
-
- // re-index the routed segments array so it starts with 1 rather than 0
- $this->uri->_reindex_segments();
-
- log_message('debug', 'No URI present. Default controller set.');
}
// --------------------------------------------------------------------
@@ -222,16 +231,19 @@ class CI_Router {
* Takes an array of URI segments as input and sets the class/method
* to be called.
*
+ * @used-by CI_Router::_parse_routes()
* @param array $segments URI segments
* @return void
*/
protected function _set_request($segments = array())
{
$segments = $this->_validate_request($segments);
-
- if (count($segments) === 0)
+ // If we don't have any segments left - try the default controller;
+ // WARNING: Directories get shifted out of the segments array!
+ if (empty($segments))
{
- return $this->_set_default_controller();
+ $this->_set_default_controller();
+ return;
}
if ($this->translate_uri_dashes === TRUE)
@@ -244,92 +256,86 @@ class CI_Router {
}
$this->set_class($segments[0]);
- isset($segments[1]) OR $segments[1] = 'index';
- $this->set_method($segments[1]);
+ if (isset($segments[1]))
+ {
+ $this->set_method($segments[1]);
+ }
- // Update our "routed" segment array to contain the segments.
- // Note: If there is no custom routing, this array will be
- // identical to $this->uri->segments
+ array_unshift($segments, NULL);
+ unset($segments[0]);
$this->uri->rsegments = $segments;
}
// --------------------------------------------------------------------
/**
- * Validate request
- *
- * Attempts validate the URI request and determine the controller path.
+ * Set default controller
*
- * @param array $segments URI segments
- * @return array URI segments
+ * @return void
*/
- protected function _validate_request($segments)
+ protected function _set_default_controller()
{
- if (count($segments) === 0)
+ if (empty($this->default_controller))
{
- return $segments;
+ show_error('Unable to determine what should be displayed. A default route has not been specified in the routing file.');
}
- $test = ($this->translate_uri_dashes === TRUE)
- ? str_replace('-', '_', $segments[0]) : $segments[0];
-
- // Does the requested controller exist in the root folder?
- if (file_exists(APPPATH.'controllers/'.$test.'.php'))
+ // Is the method being specified?
+ if (sscanf($this->default_controller, '%[^/]/%s', $class, $method) !== 2)
{
- return $segments;
+ $method = 'index';
}
- // Is the controller in a sub-folder?
- if (is_dir(APPPATH.'controllers/'.$segments[0]))
+ if ( ! file_exists(APPPATH.'controllers/'.$this->directory.ucfirst($class).'.php'))
{
- // Set the directory and remove it from the segment array
- $this->set_directory(array_shift($segments));
- if (count($segments) > 0)
- {
- $test = ($this->translate_uri_dashes === TRUE)
- ? str_replace('-', '_', $segments[0]) : $segments[0];
+ // This will trigger 404 later
+ return;
+ }
- // Does the requested controller exist in the sub-directory?
- if ( ! file_exists(APPPATH.'controllers/'.$this->directory.$test.'.php'))
- {
- if ( ! empty($this->routes['404_override']))
- {
- $this->directory = '';
- return explode('/', $this->routes['404_override'], 2);
- }
- else
- {
- show_404($this->directory.$segments[0]);
- }
- }
- }
- else
- {
- // Is the method being specified in the route?
- $segments = explode('/', $this->default_controller);
- if ( ! file_exists(APPPATH.'controllers/'.$this->directory.$segments[0].'.php'))
- {
- $this->directory = '';
- }
- }
+ $this->set_class($class);
+ $this->set_method($method);
- return $segments;
- }
+ // Assign routed segments, index starting from 1
+ $this->uri->rsegments = array(
+ 1 => $class,
+ 2 => $method
+ );
- // If we've gotten this far it means that the URI does not correlate to a valid
- // controller class. We will now see if there is an override
- if ( ! empty($this->routes['404_override']))
+ log_message('debug', 'No URI present. Default controller set.');
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Validate request
+ *
+ * Attempts validate the URI request and determine the controller path.
+ *
+ * @used-by CI_Router::_set_request()
+ * @param array $segments URI segments
+ * @return mixed URI segments
+ */
+ protected function _validate_request($segments)
+ {
+ $c = count($segments);
+ // Loop through our segments and return as soon as a controller
+ // is found or when such a directory doesn't exist
+ while ($c-- > 0)
{
- if (sscanf($this->routes['404_override'], '%[^/]/%s', $class, $method) !== 2)
+ $test = $this->directory
+ .ucfirst($this->translate_uri_dashes === TRUE ? str_replace('-', '_', $segments[0]) : $segments[0]);
+
+ if ( ! file_exists(APPPATH.'controllers/'.$test.'.php') && is_dir(APPPATH.'controllers/'.$this->directory.$segments[0]))
{
- $method = 'index';
+ $this->set_directory(array_shift($segments), TRUE);
+ continue;
}
- return array($class, $method);
+ return $segments;
}
- // Nothing else to do at this point but show a 404
- show_404($segments[0]);
+ // This means that all segments were actually directories
+ return $segments;
}
// --------------------------------------------------------------------
@@ -347,16 +353,43 @@ class CI_Router {
// Turn the segment array into a URI string
$uri = implode('/', $this->uri->segments);
+ // Get HTTP verb
+ $http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
+
// Is there a literal match? If so we're done
- if (isset($this->routes[$uri]) && is_string($this->routes[$uri]))
+ if (isset($this->routes[$uri]))
{
- return $this->_set_request(explode('/', $this->routes[$uri]));
+ // Check default routes format
+ if (is_string($this->routes[$uri]))
+ {
+ $this->_set_request(explode('/', $this->routes[$uri]));
+ return;
+ }
+ // Is there a matching http verb?
+ elseif (is_array($this->routes[$uri]) && isset($this->routes[$uri][$http_verb]))
+ {
+ $this->_set_request(explode('/', $this->routes[$uri][$http_verb]));
+ return;
+ }
}
- // Loop through the route array looking for wild-cards
+ // Loop through the route array looking for wildcards
foreach ($this->routes as $key => $val)
{
- // Convert wild-cards to RegEx
+ // Check if route format is using http verb
+ if (is_array($val))
+ {
+ if (isset($val[$http_verb]))
+ {
+ $val = $val[$http_verb];
+ }
+ else
+ {
+ continue;
+ }
+ }
+
+ // Convert wildcards to RegEx
$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
// Does the RegEx match?
@@ -406,13 +439,14 @@ class CI_Router {
$val = preg_replace('#^'.$key.'$#', $val, $uri);
}
- return $this->_set_request(explode('/', $val));
+ $this->_set_request(explode('/', $val));
+ return;
}
}
// If we got this far it means we didn't encounter a
// matching route so we'll set the site default route
- $this->_set_request($this->uri->segments);
+ $this->_set_request(array_values($this->uri->segments));
}
// --------------------------------------------------------------------
@@ -473,11 +507,19 @@ class CI_Router {
* Set directory name
*
* @param string $dir Directory name
+ * @param bool $appent Whether we're appending rather then setting the full value
* @return void
*/
- public function set_directory($dir)
+ public function set_directory($dir, $append = FALSE)
{
- $this->directory = str_replace(array('/', '.'), '', $dir).'/';
+ if ($append !== TRUE OR empty($this->directory))
+ {
+ $this->directory = str_replace('.', '', trim($dir, '/')).'/';
+ }
+ else
+ {
+ $this->directory .= str_replace('.', '', trim($dir, '/')).'/';
+ }
}
// --------------------------------------------------------------------
@@ -496,38 +538,6 @@ class CI_Router {
return $this->directory;
}
- // --------------------------------------------------------------------
-
- /**
- * Set controller overrides
- *
- * @param array $routing Route overrides
- * @return void
- */
- public function _set_overrides($routing)
- {
- if ( ! is_array($routing))
- {
- return;
- }
-
- if (isset($routing['directory']))
- {
- $this->set_directory($routing['directory']);
- }
-
- if ( ! empty($routing['controller']))
- {
- $this->set_class($routing['controller']);
- }
-
- if (isset($routing['function']))
- {
- $routing['function'] = empty($routing['function']) ? 'index' : $routing['function'];
- $this->set_method($routing['function']);
- }
- }
-
}
/* End of file Router.php */
diff --git a/system/core/Security.php b/system/core/Security.php
index 196d61144..95957a3d8 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -38,6 +38,30 @@ defined('BASEPATH') OR exit('No direct script access allowed');
class CI_Security {
/**
+ * List of sanitize filename strings
+ *
+ * @var array
+ */
+ public $filename_bad_chars = array(
+ '../', '<!--', '-->', '<', '>',
+ "'", '"', '&', '$', '#',
+ '{', '}', '[', ']', '=',
+ ';', '?', '%20', '%22',
+ '%3c', // <
+ '%253c', // <
+ '%3e', // >
+ '%0e', // >
+ '%28', // (
+ '%29', // )
+ '%2528', // (
+ '%26', // &
+ '%24', // $
+ '%3f', // ?
+ '%3b', // ;
+ '%3d' // =
+ );
+
+ /**
* XSS Hash
*
* Random Hash for protecting URLs.
@@ -93,7 +117,6 @@ class CI_Security {
'document.write' => '[removed]',
'.parentNode' => '[removed]',
'.innerHTML' => '[removed]',
- 'window.location' => '[removed]',
'-moz-binding' => '[removed]',
'<!--' => '&lt;!--',
'-->' => '--&gt;',
@@ -108,6 +131,7 @@ class CI_Security {
*/
protected $_never_allowed_regex = array(
'javascript\s*:',
+ '(document|(document\.)?window)\.(location|on\w*)',
'expression\s*(\(|&\#40;)', // CSS and IE
'vbscript\s*:', // IE, surprise!
'Redirect\s+302',
@@ -527,13 +551,13 @@ class CI_Security {
do
{
- $matches = $matches1 = 0;
+ $m1 = $m2 = 0;
+ $str = preg_replace('/(&#x0*[0-9a-f]{2,5})(?![0-9a-f;])/iS', '$1;', $str, -1, $m1);
+ $str = preg_replace('/(&#\d{2,4})(?![0-9;])/S', '$1;', $str, -1, $m2);
$str = html_entity_decode($str, ENT_COMPAT, $charset);
- $str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str, -1, $matches);
- $str = preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str, -1, $matches1);
}
- while ($matches OR $matches1);
+ while ($m1 OR $m2);
return $str;
}
@@ -549,24 +573,7 @@ class CI_Security {
*/
public function sanitize_filename($str, $relative_path = FALSE)
{
- $bad = array(
- '../', '<!--', '-->', '<', '>',
- "'", '"', '&', '$', '#',
- '{', '}', '[', ']', '=',
- ';', '?', '%20', '%22',
- '%3c', // <
- '%253c', // <
- '%3e', // >
- '%0e', // >
- '%28', // (
- '%29', // )
- '%2528', // (
- '%26', // &
- '%24', // $
- '%3f', // ?
- '%3b', // ;
- '%3d' // =
- );
+ $bad = $this->filename_bad_chars;
if ( ! $relative_path)
{
@@ -596,7 +603,7 @@ class CI_Security {
*/
public function strip_image_tags($str)
{
- return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
+ return preg_replace(array('#<img[\s/]+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img[\s/]+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
}
// ----------------------------------------------------------------
@@ -641,8 +648,8 @@ class CI_Security {
*/
protected function _remove_evil_attributes($str, $is_image)
{
- // All javascript event handlers (e.g. onload, onclick, onmouseover), style, and xmlns
- $evil_attributes = array('on\w*', 'style', 'xmlns', 'formaction');
+ // Formaction, style, and xmlns
+ $evil_attributes = array('style', 'xmlns', 'formaction');
if ($is_image === TRUE)
{
@@ -830,14 +837,15 @@ class CI_Security {
* Add a semicolon if missing. We do this to enable
* the conversion of entities to ASCII later.
*/
- $str = preg_replace('#(&\#?[0-9a-z]{2,})([\x00-\x20])*;?#i', '\\1;\\2', $str);
+ $str = preg_replace('/(&#\d{2,4})(?![0-9;])/', '$1;', $str);
+ $str = preg_replace('/(&[a-z]{2,})(?![a-z;])/i', '$1;', $str);
/*
* Validate UTF16 two byte encoding (x00)
*
* Just as above, adds a semicolon if missing.
*/
- $str = preg_replace('#(&\#x?)([0-9A-F]+);?#i', '\\1\\2;', $str);
+ $str = preg_replace('/(&#x0*[0-9a-f]{2,5})(?![0-9a-f;])/i', '$1;', $str);
/*
* Un-Protect GET variables in URLs
@@ -877,7 +885,7 @@ class CI_Security {
{
if ($this->_csrf_hash === '')
{
- // If the cookie exists we will use it's value.
+ // If the cookie exists we will use its value.
// We don't necessarily want to regenerate it with
// each page load since a page could contain embedded
// sub-pages causing this feature to fail
@@ -887,7 +895,7 @@ class CI_Security {
return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
}
- $this->_csrf_hash = md5(uniqid(rand(), TRUE));
+ $this->_csrf_hash = md5(uniqid(mt_rand(), TRUE));
$this->csrf_set_cookie();
}
diff --git a/system/core/URI.php b/system/core/URI.php
index bc086d223..13682cbee 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -44,21 +44,21 @@ class CI_URI {
*
* @var array
*/
- public $keyval = array();
+ public $keyval = array();
/**
* Current URI string
*
* @var string
*/
- public $uri_string;
+ public $uri_string = '';
/**
* List of URI segments
*
* @var array
*/
- public $segments = array();
+ public $segments = array();
/**
* Re-indexed list of URI segments
@@ -67,90 +67,67 @@ class CI_URI {
*
* @var array
*/
- public $rsegments = array();
+ public $rsegments = array();
/**
- * Class constructor
+ * Permitted URI chars
*
- * Simply globalizes the $RTR object. The front
- * loads the Router class early on so it's not available
- * normally as other classes are.
+ * PCRE character group allowed in URI segments
*
- * @return void
+ * @var string
*/
- public function __construct()
- {
- $this->config =& load_class('Config', 'core');
- log_message('debug', 'URI Class Initialized');
- }
-
- // --------------------------------------------------------------------
+ protected $_permitted_uri_chars;
/**
- * Fetch URI String
+ * Class constructor
*
- * @used-by CI_Router
* @return void
*/
- public function _fetch_uri_string()
+ public function __construct()
{
- $protocol = strtoupper($this->config->item('uri_protocol'));
+ $this->config =& load_class('Config', 'core');
- if ($protocol === 'AUTO')
+ // If query strings are enabled, we don't need to parse any segments.
+ // However, they don't make sense under CLI.
+ if (is_cli() OR $this->config->item('enable_query_strings') !== TRUE)
{
- // Is the request coming from the command line?
- if ($this->_is_cli_request())
+ $this->_permitted_uri_chars = $this->config->item('permitted_uri_chars');
+
+ // If it's a CLI request, ignore the configuration
+ if (is_cli() OR ($protocol = strtoupper($this->config->item('uri_protocol'))) === 'CLI')
{
$this->_set_uri_string($this->_parse_argv());
- return;
}
-
- // Is there a PATH_INFO variable? This should be the easiest solution.
- if (isset($_SERVER['PATH_INFO']))
+ elseif ($protocol === 'AUTO')
{
- $this->_set_uri_string($_SERVER['PATH_INFO']);
- return;
+ // Is there a PATH_INFO variable? This should be the easiest solution.
+ if (isset($_SERVER['PATH_INFO']))
+ {
+ $this->_set_uri_string($_SERVER['PATH_INFO']);
+ }
+ // No PATH_INFO? Let's try REQUST_URI or QUERY_STRING then
+ elseif (($uri = $this->_parse_request_uri()) !== '' OR ($uri = $this->_parse_query_string()) !== '')
+ {
+ $this->_set_uri_string($uri);
+ }
+ // As a last ditch effor, let's try using the $_GET array
+ elseif (is_array($_GET) && count($_GET) === 1 && trim(key($_GET), '/') !== '')
+ {
+ $this->_set_uri_string(key($_GET));
+ }
}
-
- // Let's try REQUEST_URI then, this will work in most situations
- if (($uri = $this->_parse_request_uri()) !== '')
+ elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol))))
{
- $this->_set_uri_string($uri);
- return;
+ $this->_set_uri_string($this->$method());
}
-
- // No REQUEST_URI either?... What about QUERY_STRING?
- if (($uri = $this->_parse_query_string()) !== '')
+ else
{
+ $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol);
$this->_set_uri_string($uri);
- return;
- }
-
- // 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));
- return;
}
-
- // We've exhausted all our options...
- $this->uri_string = '';
- return;
}
- if ($protocol === 'CLI')
- {
- $this->_set_uri_string($this->_parse_argv());
- return;
- }
- elseif (method_exists($this, ($method = '_parse_'.strtolower($protocol))))
- {
- $this->_set_uri_string($this->$method());
- return;
- }
-
- $uri = isset($_SERVER[$protocol]) ? $_SERVER[$protocol] : @getenv($protocol);
- $this->_set_uri_string($uri);
+ log_message('debug', 'URI Class Initialized');
}
// --------------------------------------------------------------------
@@ -165,6 +142,35 @@ class CI_URI {
{
// Filter out control characters and trim slashes
$this->uri_string = trim(remove_invisible_characters($str, FALSE), '/');
+
+ if ($this->uri_string !== '')
+ {
+ // Remove the URL suffix, if present
+ if (($suffix = (string) $this->config->item('url_suffix')) !== '')
+ {
+ $slen = strlen($suffix);
+
+ if (substr($this->uri_string, -$slen) === $suffix)
+ {
+ $this->uri_string = substr($this->uri_string, 0, -$slen);
+ }
+ }
+
+ $this->segments[0] = NULL;
+ // Populate the segments array
+ foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val)
+ {
+ // Filter segments for security
+ $val = trim($this->filter_uri($val));
+
+ if ($val !== '')
+ {
+ $this->segments[] = $val;
+ }
+ }
+
+ unset($this->segments[0]);
+ }
}
// --------------------------------------------------------------------
@@ -225,36 +231,10 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Remove relative directory (../) and multi slashes (///)
- *
- * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
- *
- * @param string $url
- * @return string
- */
- protected function _remove_relative_directory($uri)
- {
- $uris = array();
- $tok = strtok($uri, '/');
- while ($tok !== FALSE)
- {
- if (( ! empty($tok) OR $tok === '0') && $tok !== '..')
- {
- $uris[] = $tok;
- }
- $tok = strtok('/');
- }
- return implode('/', $uris);
- }
-
- // --------------------------------------------------------------------
-
- /**
* Parse QUERY_STRING
*
* Will parse QUERY_STRING and automatically detect the URI from it.
*
- * @used-by CI_URI::_fetch_uri_string()
* @return string
*/
protected function _parse_query_string()
@@ -280,23 +260,6 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Is CLI Request?
- *
- * Duplicate of method from the Input class to test to see if
- * a request was made from the command line.
- *
- * @see CI_Input::is_cli_request()
- * @used-by CI_URI::_fetch_uri_string()
- * @return bool
- */
- protected function _is_cli_request()
- {
- return (PHP_SAPI === 'cli') OR defined('STDIN');
- }
-
- // --------------------------------------------------------------------
-
- /**
* Parse CLI arguments
*
* Take each command line argument and assume it is a URI segment.
@@ -312,104 +275,52 @@ class CI_URI {
// --------------------------------------------------------------------
/**
- * Filter URI
+ * Remove relative directory (../) and multi slashes (///)
*
- * Filters segments for malicious characters.
+ * Do some final cleaning of the URI and return it, currently only used in self::_parse_request_uri()
*
- * @used-by CI_Router
- * @param string $str
+ * @param string $url
* @return string
*/
- public function _filter_uri($str)
+ protected function _remove_relative_directory($uri)
{
- if ($str !== '' && $this->config->item('permitted_uri_chars') != '' && $this->config->item('enable_query_strings') === FALSE)
+ $uris = array();
+ $tok = strtok($uri, '/');
+ while ($tok !== FALSE)
{
- // preg_quote() in PHP 5.3 escapes -, so the str_replace() and addition of - to preg_quote() is to maintain backwards
- // compatibility as many are unaware of how characters in the permitted_uri_chars will be parsed as a regex pattern
- if ( ! preg_match('|^['.str_replace(array('\\-', '\-'), '-', preg_quote($this->config->item('permitted_uri_chars'), '-')).']+$|i', $str))
+ if (( ! empty($tok) OR $tok === '0') && $tok !== '..')
{
- show_error('The URI you submitted has disallowed characters.', 400);
+ $uris[] = $tok;
}
+ $tok = strtok('/');
}
- // Convert programatic characters to entities and return
- return str_replace(
- array('$', '(', ')', '%28', '%29'), // Bad
- array('&#36;', '&#40;', '&#41;', '&#40;', '&#41;'), // Good
- $str);
- }
-
- // --------------------------------------------------------------------
-
- /**
- * Remove URL suffix
- *
- * Removes the suffix from the URL if needed.
- *
- * @used-by CI_Router
- * @return void
- */
- public function _remove_url_suffix()
- {
- $suffix = (string) $this->config->item('url_suffix');
-
- if ($suffix === '')
- {
- return;
- }
-
- $slen = strlen($suffix);
-
- if (substr($this->uri_string, -$slen) === $suffix)
- {
- $this->uri_string = substr($this->uri_string, 0, -$slen);
- }
+ return implode('/', $uris);
}
// --------------------------------------------------------------------
/**
- * Explode URI segments
+ * Filter URI
*
- * The individual segments will be stored in the $this->segments array.
+ * Filters segments for malicious characters.
*
- * @see CI_URI::$segments
- * @used-by CI_Router
- * @return void
+ * @param string $str
+ * @return string
*/
- public function _explode_segments()
+ public function filter_uri($str)
{
- foreach (explode('/', preg_replace('|/*(.+?)/*$|', '\\1', $this->uri_string)) as $val)
+ if ( ! empty($str) && ! empty($this->_permitted_uri_chars) && ! preg_match('/^['.$this->_permitted_uri_chars.']+$/i'.(UTF8_ENABLED ? 'u' : ''), $str))
{
- // Filter segments for security
- $val = trim($this->_filter_uri($val));
-
- if ($val !== '')
- {
- $this->segments[] = $val;
- }
+ show_error('The URI you submitted has disallowed characters.', 400);
}
- }
- // --------------------------------------------------------------------
-
- /**
- * Re-index Segments
- *
- * Re-indexes the CI_URI::$segment array so that it starts at 1 rather
- * than 0. Doing so makes it simpler to use methods like
- * CI_URI::segment(n) since there is a 1:1 relationship between the
- * segment array and the actual segments.
- *
- * @used-by CI_Router
- * @return void
- */
- public function _reindex_segments()
- {
- array_unshift($this->segments, NULL);
- array_unshift($this->rsegments, NULL);
- unset($this->segments[0]);
- unset($this->rsegments[0]);
+ // Convert programatic characters to entities and return
+ return str_replace(
+ array('$', '(', ')', '%28', '%29'), // Bad
+ array('&#36;', '&#40;', '&#41;', '&#40;', '&#41;'), // Good
+ $str
+ );
}
// --------------------------------------------------------------------
@@ -720,12 +631,7 @@ class CI_URI {
{
global $RTR;
- if (($dir = $RTR->directory) === '/')
- {
- $dir = '';
- }
-
- return $dir.implode('/', $this->rsegment_array());
+ return ltrim($RTR->directory, '/').implode('/', $this->rsegments);
}
}
diff --git a/system/core/Utf8.php b/system/core/Utf8.php
index a78616d40..828a8aeba 100644
--- a/system/core/Utf8.php
+++ b/system/core/Utf8.php
@@ -66,7 +66,7 @@ class CI_Utf8 {
}
if (
- @preg_match('/./u', 'é') === 1 // PCRE must support UTF-8
+ defined('PREG_BAD_UTF8_ERROR') // PCRE must support UTF-8
&& function_exists('iconv') // iconv must be installed
&& MB_ENABLED === TRUE // mbstring must be enabled
&& $charset === 'UTF-8' // Application charset must be UTF-8
diff --git a/system/database/DB.php b/system/database/DB.php
index 8742800c8..96da87c6d 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -206,11 +206,6 @@ function &DB($params = '', $query_builder_override = NULL)
$DB->initialize();
}
- if ( ! empty($params['stricton']))
- {
- $DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
- }
-
return $DB;
}
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 425657e17..f066b58de 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -624,7 +624,14 @@ 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_depth > 0 && $this->trans_complete();
+ if ($this->_trans_depth !== 0)
+ {
+ do
+ {
+ $this->trans_complete();
+ }
+ while ($this->_trans_depth !== 0);
+ }
// Display errors
return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql));
@@ -917,7 +924,7 @@ abstract class CI_DB_driver {
*/
public function is_write_type($sql)
{
- return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+ return (bool) preg_match('/^\s*"?(SET|INSERT|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s/i', $sql);
}
// --------------------------------------------------------------------
@@ -1135,7 +1142,7 @@ abstract class CI_DB_driver {
else
{
/* We have no other choice but to just get the first element's key.
- * Due to array_shift() accepting it's argument by reference, if
+ * Due to array_shift() accepting its argument by reference, if
* E_STRICT is on, this would trigger a warning. So we'll have to
* assign it first.
*/
@@ -1375,7 +1382,9 @@ abstract class CI_DB_driver {
$fields[$this->protect_identifiers($key)] = $this->escape($val);
}
- return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
+ $sql = $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
+ $this->_reset_write();
+ return $sql;
}
// --------------------------------------------------------------------
@@ -1412,7 +1421,7 @@ abstract class CI_DB_driver {
*/
protected function _has_operator($str)
{
- return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
+ return (bool) preg_match('/(<|>|!|=|\sIS NULL|\sIS NOT NULL|\sEXISTS|\sBETWEEN|\sLIKE|\sIN\s*\(|\s)/i', trim($str));
}
// --------------------------------------------------------------------
@@ -1438,6 +1447,8 @@ abstract class CI_DB_driver {
'\s*>\s*', // >
'\s+IS NULL', // IS NULL
'\s+IS NOT NULL', // IS NOT NULL
+ '\s+EXISTS\s*\([^\)]+\)', // EXISTS(sql)
+ '\s+NOT EXISTS\s*\([^\)]+\)', // NOT EXISTS(sql)
'\s+BETWEEN\s+\S+\s+AND\s+\S+', // BETWEEN value AND value
'\s+IN\s*\([^\)]+\)', // IN(list)
'\s+NOT IN\s*\([^\)]+\)', // NOT IN (list)
@@ -1474,7 +1485,7 @@ abstract class CI_DB_driver {
}
return (func_num_args() > 1)
- ? call_user_func_array($function, array_splice(func_get_args(), 1))
+ ? call_user_func_array($function, array_slice(func_get_args(), 1))
: call_user_func($function);
}
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index d52029ecd..1cebb189c 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -740,6 +740,18 @@ abstract class CI_DB_forge {
'_literal' => FALSE
);
+ if ($create_table === FALSE)
+ {
+ if (isset($attributes['AFTER']))
+ {
+ $field['after'] = $attributes['AFTER'];
+ }
+ elseif (isset($attributes['FIRST']))
+ {
+ $field['first'] = (bool) $attributes['FIRST'];
+ }
+ }
+
$this->_attr_default($attributes, $field);
if (isset($attributes['NULL']))
@@ -748,11 +760,15 @@ abstract class CI_DB_forge {
{
$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
}
- elseif ($create_table === TRUE)
+ else
{
$field['null'] = ' NOT NULL';
}
}
+ elseif ($create_table === TRUE)
+ {
+ $field['null'] = ' NOT NULL';
+ }
$this->_attr_auto_increment($attributes, $field);
$this->_attr_unique($attributes, $field);
@@ -968,7 +984,6 @@ abstract class CI_DB_forge {
*/
protected function _process_indexes($table)
{
- $table = $this->db->escape_identifiers($table);
$sqls = array();
for ($i = 0, $c = count($this->keys); $i < $c; $i++)
@@ -992,7 +1007,7 @@ abstract class CI_DB_forge {
is_array($this->keys[$i]) OR $this->keys[$i] = array($this->keys[$i]);
- $sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers(implode('_', $this->keys[$i]))
+ $sqls[] = 'CREATE INDEX '.$this->db->escape_identifiers($table.'_'.implode('_', $this->keys[$i]))
.' ON '.$this->db->escape_identifiers($table)
.' ('.implode(', ', $this->db->escape_identifiers($this->keys[$i])).');';
}
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 292621b66..c543e1584 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -385,7 +385,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
$alias = $this->_create_alias_from_table(trim($select));
}
- $sql = $this->protect_identifiers($type.'('.trim($select).')').' AS '.$this->escape_identifiers(trim($alias));
+ $sql = $type.'('.$this->protect_identifiers(trim($select)).') AS '.$this->escape_identifiers(trim($alias));
$this->qb_select[] = $sql;
$this->qb_no_escape[] = NULL;
@@ -1138,7 +1138,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* ORDER BY
*
* @param string $orderby
- * @param string $direction ASC or DESC
+ * @param string $direction ASC, DESC or RANDOM
* @param bool $escape
* @return CI_DB_query_builder
*/
@@ -1152,7 +1152,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
// Do we have a seed value?
$orderby = ctype_digit((string) $orderby)
- ? $orderby = sprintf($this->_random_keyword[1], $orderby)
+ ? sprintf($this->_random_keyword[1], $orderby)
: $this->_random_keyword[0];
}
elseif (empty($orderby))
@@ -1338,7 +1338,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
* returned by an Query Builder query.
*
* @param string
- * @return string
+ * @return int
*/
public function count_all_results($table = '')
{
@@ -1846,6 +1846,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
$this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index)));
$affected_rows += $this->affected_rows();
+ $this->qb_where = array();
}
$this->_reset_write();
@@ -2290,7 +2291,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
{
- if ($this->{$qb_key}[$i]['escape'] === FALSE)
+ // Is this condition already compiled?
+ if (is_string($this->{$qb_key}[$i]))
+ {
+ continue;
+ }
+ elseif ($this->{$qb_key}[$i]['escape'] === FALSE)
{
$this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
continue;
@@ -2360,6 +2366,12 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)
{
+ // Is it already compiled?
+ if (is_string($this->qb_groupby))
+ {
+ continue;
+ }
+
$this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))
? $this->qb_groupby[$i]['field']
: $this->protect_identifiers($this->qb_groupby[$i]['field']);
@@ -2544,17 +2556,34 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
return;
}
+ elseif (in_array('select', $this->qb_cache_exists, TRUE))
+ {
+ $qb_no_escape = $this->qb_cache_no_escape;
+ }
- foreach ($this->qb_cache_exists as $val)
+ foreach (array_unique($this->qb_cache_exists) as $val) // select, from, etc.
{
$qb_variable = 'qb_'.$val;
$qb_cache_var = 'qb_cache_'.$val;
+ $qb_new = $this->$qb_cache_var;
- if (count($this->$qb_cache_var) === 0)
+ for ($i = 0, $c = count($this->$qb_variable); $i < $c; $i++)
{
- continue;
+ if ( ! in_array($this->{$qb_variable}[$i], $qb_new, TRUE))
+ {
+ $qb_new[] = $this->{$qb_variable}[$i];
+ if ($val === 'select')
+ {
+ $qb_no_escape[] = $this->qb_no_escape[$i];
+ }
+ }
+ }
+
+ $this->$qb_variable = $qb_new;
+ if ($val === 'select')
+ {
+ $this->qb_no_escape = $qb_no_escape;
}
- $this->$qb_variable = array_merge($this->$qb_variable, array_diff($this->$qb_cache_var, $this->$qb_variable));
}
// If we are "protecting identifiers" we need to examine the "from"
@@ -2563,8 +2592,6 @@ abstract class CI_DB_query_builder extends CI_DB_driver {
{
$this->_track_aliases($this->qb_from);
}
-
- $this->qb_no_escape = array_merge($this->qb_no_escape, array_diff($this->qb_cache_no_escape, $this->qb_no_escape));
}
// --------------------------------------------------------------------
diff --git a/system/database/DB_utility.php b/system/database/DB_utility.php
index 9f953d4ac..665615909 100644
--- a/system/database/DB_utility.php
+++ b/system/database/DB_utility.php
@@ -282,8 +282,7 @@ abstract class CI_DB_utility {
extract($params);
// Load the xml helper
- $CI =& get_instance();
- $CI->load->helper('xml');
+ get_instance()->load->helper('xml');
// Generate the result
$xml = '<'.$root.'>'.$newline;
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index b94642b35..16b2f6f53 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -66,6 +66,15 @@ class CI_DB_mysql_driver extends CI_DB {
*/
public $delete_hack = TRUE;
+ /**
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
+ *
+ * @var bool
+ */
+ public $stricton = FALSE;
+
// --------------------------------------------------------------------
/**
@@ -126,6 +135,11 @@ class CI_DB_mysql_driver extends CI_DB {
: FALSE;
}
+ if ($this->stricton && is_resource($this->conn_id))
+ {
+ $this->simple_query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
+ }
+
return $this->conn_id;
}
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index ef2cb8a8d..62ba2c50d 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -66,6 +66,15 @@ class CI_DB_mysqli_driver extends CI_DB {
*/
public $delete_hack = TRUE;
+ /**
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
+ *
+ * @var bool
+ */
+ public $stricton = FALSE;
+
// --------------------------------------------------------------------
/**
@@ -93,6 +102,11 @@ class CI_DB_mysqli_driver extends CI_DB {
$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
$mysqli = mysqli_init();
+ if ($this->stricton)
+ {
+ $mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode="STRICT_ALL_TABLES"');
+ }
+
return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags)
? $mysqli : FALSE;
}
@@ -241,9 +255,10 @@ class CI_DB_mysqli_driver extends CI_DB {
// even if the queries produce a successful result.
$this->_trans_failure = ($test_mode === TRUE);
- $this->simple_query('SET AUTOCOMMIT=0');
- $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
- return TRUE;
+ $this->conn_id->autocommit(FALSE);
+ return is_php('5.5')
+ ? $this->conn_id->begin_transaction()
+ : $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
}
// --------------------------------------------------------------------
@@ -261,9 +276,13 @@ class CI_DB_mysqli_driver extends CI_DB {
return TRUE;
}
- $this->simple_query('COMMIT');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ if ($this->conn_id->commit())
+ {
+ $this->conn_id->autocommit(TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
@@ -281,9 +300,13 @@ class CI_DB_mysqli_driver extends CI_DB {
return TRUE;
}
- $this->simple_query('ROLLBACK');
- $this->simple_query('SET AUTOCOMMIT=1');
- return TRUE;
+ if ($this->conn_id->rollback())
+ {
+ $this->conn_id->autocommit(TRUE);
+ return TRUE;
+ }
+
+ return FALSE;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 93e62b4dd..d75ed28cc 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -18,7 +18,7 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 1.0
@@ -344,7 +344,7 @@ class CI_DB_oci8_driver extends CI_DB {
$have_cursor = TRUE;
}
}
- $sql = trim($sql, ',') . '); END;';
+ $sql = trim($sql, ',').'); END;';
$this->stmt_id = FALSE;
$this->_set_stmt_id($sql);
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index fd1d28787..ce09b62bc 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -18,7 +18,7 @@
*
* @package CodeIgniter
* @author EllisLab Dev Team
- * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @copyright Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
* @license http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
* @link http://codeigniter.com
* @since Version 1.0
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index fa89661b1..184a8df33 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -69,7 +69,7 @@ class CI_DB_pdo_driver extends CI_DB {
{
parent::__construct($params);
- if (preg_match('/([^;]+):/', $this->dsn, $match) && count($match) === 2)
+ if (preg_match('/([^:]+):/', $this->dsn, $match) && count($match) === 2)
{
// If there is a minimum valid dsn string pattern found, we're done
// This is for general PDO users, who tend to have a full DSN string.
@@ -77,7 +77,7 @@ class CI_DB_pdo_driver extends CI_DB {
return;
}
// Legacy support for DSN specified in the hostname field
- elseif (preg_match('/([^;]+):/', $this->hostname, $match) && count($match) === 2)
+ elseif (preg_match('/([^:]+):/', $this->hostname, $match) && count($match) === 2)
{
$this->dsn = $this->hostname;
$this->hostname = NULL;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index ff486fc5a..bc92cab83 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -55,6 +55,15 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
*/
public $compress = FALSE;
+ /**
+ * Strict ON flag
+ *
+ * Whether we're running in strict SQL mode.
+ *
+ * @var bool
+ */
+ public $stricton = FALSE;
+
// --------------------------------------------------------------------
/**
@@ -114,6 +123,18 @@ class CI_DB_pdo_mysql_driver extends CI_DB_pdo_driver {
.(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);
}
+ if ($this->stricton)
+ {
+ if (empty($this->options[PDO::MYSQL_ATTR_INIT_COMMAND]))
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode="STRICT_ALL_TABLES"';
+ }
+ else
+ {
+ $this->options[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', @@session.sql_mode = "STRICT_ALL_TABLES"';
+ }
+ }
+
if ($this->compress === TRUE)
{
$this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
index d0cdde2e2..6ee327bd5 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -137,7 +137,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
*/
public function is_write_type($sql)
{
- return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+ return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE(?!.*\sRETURNING)|DELETE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s/i', str_replace(array("\r\n", "\r", "\n"), ' ', $sql));
}
// --------------------------------------------------------------------
@@ -166,7 +166,7 @@ class CI_DB_pdo_pgsql_driver extends CI_DB_pdo_driver {
* ORDER BY
*
* @param string $orderby
- * @param string $direction ASC or DESC
+ * @param string $direction ASC, DESC or RANDOM
* @param bool $escape
* @return object
*/
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index ac7345ad6..19404ae55 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -318,7 +318,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
public function is_write_type($sql)
{
- return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+ return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE(?!.*\sRETURNING)|DELETE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s/i', str_replace(array("\r\n", "\r", "\n"), ' ', $sql));
}
// --------------------------------------------------------------------
@@ -331,7 +331,7 @@ class CI_DB_postgre_driver extends CI_DB {
*/
protected function _escape_str($str)
{
- return pg_escape_string($str);
+ return pg_escape_string($this->conn_id, $str);
}
// --------------------------------------------------------------------
@@ -346,7 +346,11 @@ class CI_DB_postgre_driver extends CI_DB {
*/
public function escape($str)
{
- if (is_bool($str))
+ if (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))))
+ {
+ return pg_escape_literal($this->conn_id, $str);
+ }
+ elseif (is_bool($str))
{
return ($str) ? 'TRUE' : 'FALSE';
}
@@ -512,7 +516,7 @@ class CI_DB_postgre_driver extends CI_DB {
* ORDER BY
*
* @param string $orderby
- * @param string $direction ASC or DESC
+ * @param string $direction ASC, DESC or RANDOM
* @param bool $escape
* @return object
*/
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 2d2ae7751..24cd53568 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -126,9 +126,9 @@ if ( ! function_exists('create_captcha'))
// Determine angle and position
// -----------------------------------
$length = strlen($word);
- $angle = ($length >= 6) ? rand(-($length-6), ($length-6)) : 0;
- $x_axis = rand(6, (360/$length)-16);
- $y_axis = ($angle >= 0) ? rand($img_height, $img_width) : rand(6, $img_height);
+ $angle = ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0;
+ $x_axis = mt_rand(6, (360/$length)-16);
+ $y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height);
// Create image
// PHP.net recommends imagecreatetruecolor(), but it isn't always available
@@ -142,7 +142,7 @@ if ( ! function_exists('create_captcha'))
is_array($colors) OR $colors = $defaults['colors'];
- foreach (array_keys($default['colors']) as $key)
+ foreach (array_keys($defaults['colors']) as $key)
{
// Check for a possible missing value
is_array($colors[$key]) OR $colors[$key] = $defaults['colors'][$key];
@@ -183,13 +183,13 @@ if ( ! function_exists('create_captcha'))
if ($use_font === FALSE)
{
$font_size = 5;
- $x = rand(0, $img_width / ($length / 3));
+ $x = mt_rand(0, $img_width / ($length / 3));
$y = 0;
}
else
{
$font_size = 16;
- $x = rand(0, $img_width / ($length / 1.5));
+ $x = mt_rand(0, $img_width / ($length / 1.5));
$y = $font_size + 2;
}
@@ -197,13 +197,13 @@ if ( ! function_exists('create_captcha'))
{
if ($use_font === FALSE)
{
- $y = rand(0 , $img_height / 2);
+ $y = mt_rand(0 , $img_height / 2);
imagestring($im, $font_size, $x, $y, $word[$i], $colors['text']);
$x += ($font_size * 2);
}
else
{
- $y = rand($img_height / 2, $img_height - 3);
+ $y = mt_rand($img_height / 2, $img_height - 3);
imagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]);
$x += $font_size;
}
@@ -215,12 +215,12 @@ if ( ! function_exists('create_captcha'))
// -----------------------------------
// Generate the image
// -----------------------------------
- $img_name = $now.'.jpg';
- ImageJPEG($im, $img_path.$img_name);
- $img = '<img src="'.$img_url.$img_name.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
+ $img_filename = $now.'.jpg';
+ ImageJPEG($im, $img_path.$img_filename);
+ $img = '<img src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
ImageDestroy($im);
- return array('word' => $word, 'time' => $now, 'image' => $img);
+ return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);
}
}
diff --git a/system/helpers/cookie_helper.php b/system/helpers/cookie_helper.php
index e5cf6b1d6..a79083a63 100644
--- a/system/helpers/cookie_helper.php
+++ b/system/helpers/cookie_helper.php
@@ -56,11 +56,10 @@ if ( ! function_exists('set_cookie'))
* @param bool true makes the cookie accessible via http(s) only (no javascript)
* @return void
*/
- function set_cookie($name = '', $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
+ function set_cookie($name, $value = '', $expire = '', $domain = '', $path = '/', $prefix = '', $secure = FALSE, $httponly = FALSE)
{
// Set the config file options
- $CI =& get_instance();
- $CI->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly);
+ get_instance()->input->set_cookie($name, $value, $expire, $domain, $path, $prefix, $secure, $httponly);
}
}
@@ -75,11 +74,11 @@ if ( ! function_exists('get_cookie'))
* @param bool
* @return mixed
*/
- function get_cookie($index = '', $xss_clean = FALSE)
+ function get_cookie($index, $xss_clean = NULL)
{
- $CI =& get_instance();
+ is_bool($xss_clean) OR $xss_clean = (config_item('global_xss_filtering') === TRUE);
$prefix = isset($_COOKIE[$index]) ? '' : config_item('cookie_prefix');
- return $CI->input->cookie($prefix.$index, $xss_clean);
+ return get_instance()->input->cookie($prefix.$index, $xss_clean);
}
}
@@ -96,7 +95,7 @@ if ( ! function_exists('delete_cookie'))
* @param string the cookie prefix
* @return void
*/
- function delete_cookie($name = '', $domain = '', $path = '/', $prefix = '')
+ function delete_cookie($name, $domain = '', $path = '/', $prefix = '')
{
set_cookie($name, '', '', $domain, $path, $prefix);
}
diff --git a/system/helpers/file_helper.php b/system/helpers/file_helper.php
index 4b45a62d0..0587740b1 100644
--- a/system/helpers/file_helper.php
+++ b/system/helpers/file_helper.php
@@ -79,11 +79,19 @@ if ( ! function_exists('write_file'))
}
flock($fp, LOCK_EX);
- fwrite($fp, $data);
+
+ for ($written = 0, $length = strlen($data); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($data, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
flock($fp, LOCK_UN);
fclose($fp);
- return TRUE;
+ return is_int($result);
}
}
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 2002d4269..a3d299b0d 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -50,15 +50,10 @@ if ( ! function_exists('form_open'))
* @param array a key/value pair hidden data
* @return string
*/
- function form_open($action = '', $attributes = '', $hidden = array())
+ function form_open($action = '', $attributes = array(), $hidden = array())
{
$CI =& get_instance();
- if ($attributes === '')
- {
- $attributes = 'method="post"';
- }
-
// If an action is not a full URL then turn it into one
if ($action && strpos($action, '://') === FALSE)
{
@@ -70,10 +65,22 @@ if ( ! function_exists('form_open'))
$action = $CI->config->site_url($CI->uri->uri_string());
}
- $form = '<form action="'.$action.'"'._attributes_to_string($attributes, TRUE).">\n";
+ $attributes = _attributes_to_string($attributes);
+
+ if (stripos($attributes, 'method=') === FALSE)
+ {
+ $attributes .= ' method="post"';
+ }
+
+ if (stripos($attributes, 'accept-charset=') === FALSE)
+ {
+ $attributes .= ' accept-charset="'.strtolower(config_item('charset')).'"';
+ }
+
+ $form = '<form action="'.$action.'"'.$attributes.">\n";
// Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
- if ($CI->config->item('csrf_protection') === TRUE && ! (strpos($action, $CI->config->base_url()) === FALSE OR strpos($form, 'method="get"')))
+ if ($CI->config->item('csrf_protection') === TRUE && ! (strpos($action, $CI->config->base_url()) === FALSE OR stripos($form, 'method="get"')))
{
$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();
}
@@ -309,7 +316,7 @@ if ( ! function_exists('form_dropdown'))
{
isset($name['options']) OR $name['options'] = array();
isset($name['selected']) OR $name['selected'] = array();
- isset($name['extra']) OR $name['extra'] = array();
+ isset($name['extra']) OR $name['extra'] = '';
return form_dropdown($name['name'], $name['options'], $name['selected'], $name['extra']);
}
@@ -322,10 +329,7 @@ if ( ! function_exists('form_dropdown'))
$selected = array($_POST[$name]);
}
- if ($extra != '')
- {
- $extra = ' '.$extra;
- }
+ $extra = _attributes_to_string($extra);
$multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
@@ -542,12 +546,12 @@ if ( ! function_exists('form_fieldset'))
* use form_fieldset_close()
*
* @param string The legend text
- * @param string Additional attributes
+ * @param array Additional attributes
* @return string
*/
function form_fieldset($legend_text = '', $attributes = array())
{
- $fieldset = '<fieldset'._attributes_to_string($attributes, FALSE).">\n";
+ $fieldset = '<fieldset'._attributes_to_string($attributes).">\n";
if ($legend_text !== '')
{
return $fieldset.'<legend>'.$legend_text."</legend>\n";
@@ -668,37 +672,33 @@ if ( ! function_exists('set_select'))
*/
function set_select($field = '', $value = '', $default = FALSE)
{
- $OBJ =& _get_validation_object();
+ $CI =& get_instance();
- if ($OBJ === FALSE)
+ if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
{
- if ( ! isset($_POST[$field]))
- {
- if (count($_POST) === 0 && $default === TRUE)
- {
- return ' selected="selected"';
- }
- return '';
- }
-
- $field = $_POST[$field];
+ return $CI->form_validation->set_select($field, $value, $default);
+ }
+ elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+ {
+ return ($default === TRUE) ? ' selected="selected"' : '';
+ }
- if (is_array($field))
+ $value = (string) $value;
+ if (is_array($input))
+ {
+ // Note: in_array('', array(0)) returns TRUE, do not use it
+ foreach ($input as &$v)
{
- if ( ! in_array($value, $field))
+ if ($value === $v)
{
- return '';
+ return ' selected="selected"';
}
}
- elseif (($field == '' OR $value == '') OR $field !== $value)
- {
- return '';
- }
- return ' selected="selected"';
+ return '';
}
- return $OBJ->set_select($field, $value, $default);
+ return ($input === $value) ? ' selected="selected"' : '';
}
}
@@ -719,37 +719,33 @@ if ( ! function_exists('set_checkbox'))
*/
function set_checkbox($field = '', $value = '', $default = FALSE)
{
- $OBJ =& _get_validation_object();
+ $CI =& get_instance();
- if ($OBJ === FALSE)
+ if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
{
- if ( ! isset($_POST[$field]))
- {
- if (count($_POST) === 0 && $default === TRUE)
- {
- return ' checked="checked"';
- }
- return '';
- }
-
- $field = $_POST[$field];
+ return $CI->form_validation->set_checkbox($field, $value, $default);
+ }
+ elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+ {
+ return ($default === TRUE) ? ' checked="checked"' : '';
+ }
- if (is_array($field))
+ $value = (string) $value;
+ if (is_array($input))
+ {
+ // Note: in_array('', array(0)) returns TRUE, do not use it
+ foreach ($input as &$v)
{
- if ( ! in_array($value, $field))
+ if ($value === $v)
{
- return '';
+ return ' checked="checked"';
}
}
- elseif (($field == '' OR $value == '') OR $field !== $value)
- {
- return '';
- }
- return ' checked="checked"';
+ return '';
}
- return $OBJ->set_checkbox($field, $value, $default);
+ return ($input === $value) ? ' checked="checked"' : '';
}
}
@@ -763,47 +759,25 @@ if ( ! function_exists('set_radio'))
* Let's you set the selected value of a radio field via info in the POST array.
* If Form Validation is active it retrieves the info from the validation class
*
- * @param string
- * @param string
- * @param bool
+ * @param string $field
+ * @param string $value
+ * @param bool $default
* @return string
*/
function set_radio($field = '', $value = '', $default = FALSE)
{
- $OBJ =& _get_validation_object();
+ $CI =& get_instance();
- if ($OBJ === FALSE)
+ if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
{
- if ( ! isset($_POST[$field]))
- {
- if (count($_POST) === 0 && $default === TRUE)
- {
- return ' checked="checked"';
- }
- return '';
- }
-
- $field = $_POST[$field];
-
- if (is_array($field))
- {
- if ( ! in_array($value, $field))
- {
- return '';
- }
- }
- else
- {
- if (($field == '' OR $value == '') OR $field !== $value)
- {
- return '';
- }
- }
-
- return ' checked="checked"';
+ return $CI->form_validation->set_radio($field, $value, $default);
+ }
+ elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+ {
+ return ($default === TRUE) ? ' checked="checked"' : '';
}
- return $OBJ->set_radio($field, $value, $default);
+ return ($input === (string) $value) ? ' checked="checked"' : '';
}
}
@@ -920,45 +894,24 @@ if ( ! function_exists('_attributes_to_string'))
* Helper function used by some of the form helpers
*
* @param mixed
- * @param bool
* @return string
*/
- function _attributes_to_string($attributes, $formtag = FALSE)
+ function _attributes_to_string($attributes)
{
- if (is_string($attributes) && strlen($attributes) > 0)
+ if (empty($attributes))
{
- if ($formtag === TRUE && strpos($attributes, 'method=') === FALSE)
- {
- $attributes .= ' method="post"';
- }
-
- if ($formtag === TRUE && strpos($attributes, 'accept-charset=') === FALSE)
- {
- $attributes .= ' accept-charset="'.strtolower(config_item('charset')).'"';
- }
-
- return ' '.$attributes;
+ return '';
}
- if (is_object($attributes) && count($attributes) > 0)
+ if (is_object($attributes))
{
$attributes = (array) $attributes;
}
- if (is_array($attributes) && ($formtag === TRUE OR count($attributes) > 0))
+ if (is_array($attributes))
{
$atts = '';
- if ( ! isset($attributes['method']) && $formtag === TRUE)
- {
- $atts .= ' method="post"';
- }
-
- if ( ! isset($attributes['accept-charset']) && $formtag === TRUE)
- {
- $atts .= ' accept-charset="'.strtolower(config_item('charset')).'"';
- }
-
foreach ($attributes as $key => $val)
{
$atts .= ' '.$key.'="'.$val.'"';
@@ -966,6 +919,13 @@ if ( ! function_exists('_attributes_to_string'))
return $atts;
}
+
+ if (is_string($attributes))
+ {
+ return ' '.$attributes;
+ }
+
+ return FALSE;
}
}
@@ -988,7 +948,7 @@ if ( ! function_exists('_get_validation_object'))
// We set this as a variable since we're returning by reference.
$return = FALSE;
- if (FALSE !== ($object = $CI->load->is_loaded('form_validation')))
+ if (FALSE !== ($object = $CI->load->is_loaded('Form_validation')))
{
if ( ! isset($CI->$object) OR ! is_object($CI->$object))
{
diff --git a/system/helpers/html_helper.php b/system/helpers/html_helper.php
index ece39584b..988eee715 100644
--- a/system/helpers/html_helper.php
+++ b/system/helpers/html_helper.php
@@ -199,15 +199,13 @@ if ( ! function_exists('img'))
{
if ($k === 'src' && strpos($v, '://') === FALSE)
{
- $CI =& get_instance();
-
if ($index_page === TRUE)
{
- $img .= ' src="'.$CI->config->site_url($v).'"';
+ $img .= ' src="'.get_instance()->config->site_url($v).'"';
}
else
{
- $img .= ' src="'.$CI->config->slash_item('base_url').$v.'"';
+ $img .= ' src="'.get_instance()->config->slash_item('base_url').$v.'"';
}
}
else
diff --git a/system/helpers/language_helper.php b/system/helpers/language_helper.php
index 4d571a71c..d7aa8e638 100644
--- a/system/helpers/language_helper.php
+++ b/system/helpers/language_helper.php
@@ -52,8 +52,7 @@ if ( ! function_exists('lang'))
*/
function lang($line, $for = '', $attributes = array())
{
- $CI =& get_instance();
- $line = $CI->lang->line($line);
+ $line = get_instance()->lang->line($line);
if ($for !== '')
{
diff --git a/system/helpers/security_helper.php b/system/helpers/security_helper.php
index 4bb94a201..7a6df5420 100644
--- a/system/helpers/security_helper.php
+++ b/system/helpers/security_helper.php
@@ -49,8 +49,7 @@ if ( ! function_exists('xss_clean'))
*/
function xss_clean($str, $is_image = FALSE)
{
- $CI =& get_instance();
- return $CI->security->xss_clean($str, $is_image);
+ return get_instance()->security->xss_clean($str, $is_image);
}
}
@@ -66,8 +65,7 @@ if ( ! function_exists('sanitize_filename'))
*/
function sanitize_filename($filename)
{
- $CI =& get_instance();
- return $CI->security->sanitize_filename($filename);
+ return get_instance()->security->sanitize_filename($filename);
}
}
@@ -107,8 +105,7 @@ if ( ! function_exists('strip_image_tags'))
*/
function strip_image_tags($str)
{
- $CI =& get_instance();
- return $CI->security->strip_image_tags($str);
+ return get_instance()->security->strip_image_tags($str);
}
}
diff --git a/system/helpers/text_helper.php b/system/helpers/text_helper.php
index b2351db95..bda844630 100644
--- a/system/helpers/text_helper.php
+++ b/system/helpers/text_helper.php
@@ -127,7 +127,7 @@ if ( ! function_exists('ascii_to_entities'))
function ascii_to_entities($str)
{
$out = '';
- for ($i = 0, $s = strlen($str), $count = 1, $temp = array(); $i < $s; $i++)
+ for ($i = 0, $s = strlen($str) - 1, $count = 1, $temp = array(); $i <= $s; $i++)
{
$ordinal = ord($str[$i]);
@@ -164,6 +164,11 @@ if ( ! function_exists('ascii_to_entities'))
$count = 1;
$temp = array();
}
+ // If this is the last iteration, just output whatever we have
+ elseif ($i === $s)
+ {
+ $out .= '&#'.implode(';', $temp).';';
+ }
}
}
@@ -329,25 +334,17 @@ if ( ! function_exists('highlight_phrase'))
*
* Highlights a phrase within a text string
*
- * @param string the text string
- * @param string the phrase you'd like to highlight
- * @param string the openging tag to precede the phrase with
- * @param string the closing tag to end the phrase with
+ * @param string $str the text string
+ * @param string $phrase the phrase you'd like to highlight
+ * @param string $tag_open the openging tag to precede the phrase with
+ * @param string $tag_close the closing tag to end the phrase with
* @return string
*/
- function highlight_phrase($str, $phrase, $tag_open = '<strong>', $tag_close = '</strong>')
+ function highlight_phrase($str, $phrase, $tag_open = '<mark>', $tag_close = '</mark>')
{
- if ($str === '')
- {
- return '';
- }
-
- if ($phrase !== '')
- {
- return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open.'\\1'.$tag_close, $str);
- }
-
- return $str;
+ return ($str !== '' && $phrase !== '')
+ ? preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open.'\\1'.$tag_close, $str)
+ : $str;
}
}
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index fbb4a1b24..f9650cd04 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -52,14 +52,7 @@ if ( ! function_exists('site_url'))
*/
function site_url($uri = '', $protocol = NULL)
{
- $uri = get_instance()->config->site_url($uri);
-
- if (isset($protocol))
- {
- return $protocol.substr($uri, strpos($uri, '://'));
- }
-
- return $uri;
+ return get_instance()->config->site_url($uri, $protocol);
}
}
@@ -80,14 +73,7 @@ if ( ! function_exists('base_url'))
*/
function base_url($uri = '', $protocol = NULL)
{
- $uri = get_instance()->config->base_url($uri);
-
- if (isset($protocol))
- {
- return $protocol.substr($uri, strpos($uri, '://'));
- }
-
- return $uri;
+ return get_instance()->config->base_url($uri, $protocol);
}
}
@@ -123,8 +109,7 @@ if ( ! function_exists('uri_string'))
*/
function uri_string()
{
- $CI =& get_instance();
- return $CI->uri->uri_string();
+ return get_instance()->uri->uri_string();
}
}
@@ -141,8 +126,7 @@ if ( ! function_exists('index_page'))
*/
function index_page()
{
- $CI =& get_instance();
- return $CI->config->item('index_page');
+ return get_instance()->config->item('index_page');
}
}
@@ -548,11 +532,16 @@ if ( ! function_exists('redirect'))
}
elseif ($method !== 'refresh' && (empty($code) OR ! is_numeric($code)))
{
- // Reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
- $code = (isset($_SERVER['REQUEST_METHOD'], $_SERVER['SERVER_PROTOCOL'])
- && $_SERVER['REQUEST_METHOD'] === 'POST'
- && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1')
- ? 303 : 302;
+ if (isset($_SERVER['SERVER_PROTOCOL'], $_SERVER['REQUEST_METHOD']) && $_SERVER['SERVER_PROTOCOL'] === 'HTTP/1.1')
+ {
+ $code = ($_SERVER['REQUEST_METHOD'] !== 'GET')
+ ? 303 // reference: http://en.wikipedia.org/wiki/Post/Redirect/Get
+ : 307;
+ }
+ else
+ {
+ $code = 302;
+ }
}
switch ($method)
diff --git a/system/language/english/ftp_lang.php b/system/language/english/ftp_lang.php
index ae4086ff3..042ab55df 100644
--- a/system/language/english/ftp_lang.php
+++ b/system/language/english/ftp_lang.php
@@ -26,18 +26,18 @@
*/
defined('BASEPATH') OR exit('No direct script access allowed');
-$lang['ftp_no_connection'] = 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.';
+$lang['ftp_no_connection'] = 'Unable to locate a valid connection ID. Please make sure you are connected before peforming any file routines.';
$lang['ftp_unable_to_connect'] = 'Unable to connect to your FTP server using the supplied hostname.';
$lang['ftp_unable_to_login'] = 'Unable to login to your FTP server. Please check your username and password.';
-$lang['ftp_unable_to_makdir'] = 'Unable to create the directory you have specified.';
+$lang['ftp_unable_to_mkdir'] = 'Unable to create the directory you have specified.';
$lang['ftp_unable_to_changedir'] = 'Unable to change directories.';
-$lang['ftp_unable_to_chmod'] = 'Unable to set file permissions. Please check your path. Note: This feature is only available in PHP 5 or higher.';
+$lang['ftp_unable_to_chmod'] = 'Unable to set file permissions. Please check your path.';
$lang['ftp_unable_to_upload'] = 'Unable to upload the specified file. Please check your path.';
$lang['ftp_unable_to_download'] = 'Unable to download the specified file. Please check your path.';
-$lang['ftp_no_source_file'] = 'Unable to locate the source file. Please check your path.';
+$lang['ftp_no_source_file'] = 'Unable to locate the source file. Please check your path.';
$lang['ftp_unable_to_rename'] = 'Unable to rename the file.';
$lang['ftp_unable_to_delete'] = 'Unable to delete the file.';
-$lang['ftp_unable_to_move'] = 'Unable to move the file. Please make sure the destination directory exists.';
+$lang['ftp_unable_to_move'] = 'Unable to move the file. Please make sure the destination directory exists.';
/* End of file ftp_lang.php */
/* Location: ./system/language/english/ftp_lang.php */ \ No newline at end of file
diff --git a/system/libraries/Cache/Cache.php b/system/libraries/Cache/Cache.php
index e1089f755..2dffa350c 100644
--- a/system/libraries/Cache/Cache.php
+++ b/system/libraries/Cache/Cache.php
@@ -106,7 +106,7 @@ class CI_Cache extends CI_Driver_Library {
isset($config['key_prefix']) && $this->key_prefix = $config['key_prefix'];
- if (isset($config['backup']) && in_array('cache_'.$config['backup'], $this->valid_drivers))
+ if (isset($config['backup']) && in_array($config['backup'], $this->valid_drivers))
{
$this->_backup_driver = $config['backup'];
}
@@ -123,6 +123,7 @@ class CI_Cache extends CI_Driver_Library {
else
{
// Backup is supported. Set it to primary.
+ log_message('debug', 'Cache adapter "'.$this->_adapter.'" is unavailable. Falling back to "'.$this->_backup_driver.'" backup adapter.');
$this->_adapter = $this->_backup_driver;
}
}
@@ -149,14 +150,15 @@ class CI_Cache extends CI_Driver_Library {
/**
* Cache Save
*
- * @param string $id Cache ID
- * @param mixed $data Data to store
- * @param int $ttl = 60 Cache TTL (in seconds)
+ * @param string $id Cache ID
+ * @param mixed $data Data to store
+ * @param int $ttl Cache TTL (in seconds)
+ * @param bool $raw Whether to store the raw value
* @return bool TRUE on success, FALSE on failure
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
- return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl);
+ return $this->{$this->_adapter}->save($this->key_prefix.$id, $data, $ttl, $raw);
}
// ------------------------------------------------------------------------
@@ -175,6 +177,34 @@ class CI_Cache extends CI_Driver_Library {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ return $this->{$this->_adapter}->increment($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ return $this->{$this->_adapter}->decrement($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the cache
*
* @return bool TRUE on success, FALSE on failure
diff --git a/system/libraries/Cache/drivers/Cache_apc.php b/system/libraries/Cache/drivers/Cache_apc.php
index 127a220a7..b5381ddaf 100644
--- a/system/libraries/Cache/drivers/Cache_apc.php
+++ b/system/libraries/Cache/drivers/Cache_apc.php
@@ -51,8 +51,14 @@ class CI_Cache_apc extends CI_Driver {
$success = FALSE;
$data = apc_fetch($id, $success);
- return ($success === TRUE && is_array($data))
- ? unserialize($data[0]) : FALSE;
+ if ($success === TRUE)
+ {
+ return is_array($data)
+ ? unserialize($data[0])
+ : $data;
+ }
+
+ return FALSE;
}
// ------------------------------------------------------------------------
@@ -60,16 +66,21 @@ class CI_Cache_apc extends CI_Driver {
/**
* Cache Save
*
- * @param string Unique Key
- * @param mixed Data to store
- * @param int Length of time (in seconds) to cache the data
- *
- * @return bool true on success/false on failure
+ * @param string $id Cache ID
+ * @param mixed $data Data to store
+ * @param int $ttol Length of time (in seconds) to cache the data
+ * @param bool $raw Whether to store the raw value
+ * @return bool TRUE on success, FALSE on failure
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
$ttl = (int) $ttl;
- return apc_store($id, array(serialize($data), time(), $ttl), $ttl);
+
+ return apc_store(
+ $id,
+ ($raw === TRUE ? $data : array(serialize($data), time(), $ttl)),
+ $ttl
+ );
}
// ------------------------------------------------------------------------
@@ -88,6 +99,34 @@ class CI_Cache_apc extends CI_Driver {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ return apc_inc($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ return apc_dec($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the cache
*
* @return bool false on failure/true on success
@@ -150,7 +189,7 @@ class CI_Cache_apc extends CI_Driver {
{
if ( ! extension_loaded('apc') OR ! (bool) @ini_get('apc.enabled'))
{
- log_message('error', 'The APC PHP extension must be loaded to use APC Cache.');
+ log_message('debug', 'The APC PHP extension must be loaded to use APC Cache.');
return FALSE;
}
diff --git a/system/libraries/Cache/drivers/Cache_dummy.php b/system/libraries/Cache/drivers/Cache_dummy.php
index d9af3773b..7e2b907a6 100644
--- a/system/libraries/Cache/drivers/Cache_dummy.php
+++ b/system/libraries/Cache/drivers/Cache_dummy.php
@@ -58,9 +58,10 @@ class CI_Cache_dummy extends CI_Driver {
* @param string Unique Key
* @param mixed Data to store
* @param int Length of time (in seconds) to cache the data
+ * @param bool Whether to store the raw value
* @return bool TRUE, Simulating success
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return TRUE;
}
@@ -81,6 +82,34 @@ class CI_Cache_dummy extends CI_Driver {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ return TRUE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ return TRUE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the cache
*
* @return bool TRUE, simulating success
diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php
index 769bd5a26..8c99c5ef3 100644
--- a/system/libraries/Cache/drivers/Cache_file.php
+++ b/system/libraries/Cache/drivers/Cache_file.php
@@ -62,25 +62,13 @@ class CI_Cache_file extends CI_Driver {
/**
* Fetch from cache
*
- * @param mixed unique key id
- * @return mixed data on success/false on failure
+ * @param string $id Cache ID
+ * @return mixed Data on success, FALSE on failure
*/
public function get($id)
{
- if ( ! file_exists($this->_cache_path.$id))
- {
- return FALSE;
- }
-
- $data = unserialize(file_get_contents($this->_cache_path.$id));
-
- if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])
- {
- unlink($this->_cache_path.$id);
- return FALSE;
- }
-
- return $data['data'];
+ $data = $this->_get($id);
+ return is_array($data) ? $data['data'] : FALSE;
}
// ------------------------------------------------------------------------
@@ -88,13 +76,13 @@ class CI_Cache_file extends CI_Driver {
/**
* Save into cache
*
- * @param string unique key
- * @param mixed data to store
- * @param int length of time (in seconds) the cache is valid
- * - Default is 60 seconds
- * @return bool true on success/false on failure
+ * @param string $id Cache ID
+ * @param mixed $data Data to store
+ * @param int $ttl Time to live in seconds
+ * @param bool $raw Whether to store the raw value (unused)
+ * @return bool TRUE on success, FALSE on failure
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
$contents = array(
'time' => time(),
@@ -127,6 +115,54 @@ class CI_Cache_file extends CI_Driver {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return New value on success, FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ $data = $this->_get($id);
+
+ if ($data === FALSE OR ! is_int($data['data']))
+ {
+ return FALSE;
+ }
+
+ $new_value = $data['data'] + $offset;
+ return $this->save($id, $new_value, $data['ttl'])
+ ? $new_value
+ : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return New value on success, FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ $data = $this->_get($id);
+
+ if ($data === FALSE OR ! is_int($data['data']))
+ {
+ return FALSE;
+ }
+
+ $new_value = $data['data'] - $offset;
+ return $this->save($id, $new_value, $data['ttl'])
+ ? $new_value
+ : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the Cache
*
* @return bool false on failure/true on success
@@ -200,6 +236,34 @@ class CI_Cache_file extends CI_Driver {
return is_really_writable($this->_cache_path);
}
+ // ------------------------------------------------------------------------
+
+ /**
+ * Get all data
+ *
+ * Internal method to get all the relevant data about a cache item
+ *
+ * @param string $id Cache ID
+ * @return mixed Data array on success or FALSE on failure
+ */
+ protected function _get($id)
+ {
+ if ( ! file_exists($this->_cache_path.$id))
+ {
+ return FALSE;
+ }
+
+ $data = unserialize(file_get_contents($this->_cache_path.$id));
+
+ if ($data['ttl'] > 0 && time() > $data['time'] + $data['ttl'])
+ {
+ unlink($this->_cache_path.$id);
+ return FALSE;
+ }
+
+ return $data;
+ }
+
}
/* End of file Cache_file.php */
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index 35d91049a..d59847752 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -60,14 +60,14 @@ class CI_Cache_memcached extends CI_Driver {
/**
* Fetch from cache
*
- * @param mixed unique key id
- * @return mixed data on success/false on failure
+ * @param string $id Cache ID
+ * @return mixed Data on success, FALSE on failure
*/
public function get($id)
{
$data = $this->_memcached->get($id);
- return is_array($data) ? $data[0] : FALSE;
+ return is_array($data) ? $data[0] : $data;
}
// ------------------------------------------------------------------------
@@ -75,20 +75,26 @@ class CI_Cache_memcached extends CI_Driver {
/**
* Save
*
- * @param string unique identifier
- * @param mixed data being cached
- * @param int time to live
- * @return bool true on success, false on failure
+ * @param string $id Cache ID
+ * @param mixed $data Data being cached
+ * @param int $ttl Time to live
+ * @param bool $raw Whether to store the raw value
+ * @return bool TRUE on success, FALSE on failure
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
+ if ($raw !== TRUE)
+ {
+ $data = array($data, time(), $ttl);
+ }
+
if (get_class($this->_memcached) === 'Memcached')
{
- return $this->_memcached->set($id, array($data, time(), $ttl), $ttl);
+ return $this->_memcached->set($id, $data, $ttl);
}
elseif (get_class($this->_memcached) === 'Memcache')
{
- return $this->_memcached->set($id, array($data, time(), $ttl), 0, $ttl);
+ return $this->_memcached->set($id, $data, 0, $ttl);
}
return FALSE;
@@ -110,6 +116,34 @@ class CI_Cache_memcached extends CI_Driver {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ return $this->_memcached->increment($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ return $this->_memcached->decrement($id, $offset);
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the Cache
*
* @return bool false on failure/true on success
@@ -240,7 +274,7 @@ class CI_Cache_memcached extends CI_Driver {
{
if ( ! extension_loaded('memcached') && ! extension_loaded('memcache'))
{
- log_message('error', 'The Memcached Extension must be loaded to use Memcached Cache.');
+ log_message('debug', 'The Memcached Extension must be loaded to use Memcached Cache.');
return FALSE;
}
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
index 484f284f1..b6fddf035 100644
--- a/system/libraries/Cache/drivers/Cache_redis.php
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -44,6 +44,7 @@ class CI_Cache_redis extends CI_Driver
* @var array
*/
protected static $_default_config = array(
+ 'socket_type' => 'tcp',
'host' => '127.0.0.1',
'password' => NULL,
'port' => 6379,
@@ -62,7 +63,7 @@ class CI_Cache_redis extends CI_Driver
/**
* Get cache
*
- * @param string Cache key identifier
+ * @param string Cache ID
* @return mixed
*/
public function get($key)
@@ -75,16 +76,17 @@ class CI_Cache_redis extends CI_Driver
/**
* Save cache
*
- * @param string Cache key identifier
- * @param mixed Data to save
- * @param int Time to live
- * @return bool
+ * @param string $id Cache ID
+ * @param mixed $data Data to save
+ * @param int $ttl Time to live in seconds
+ * @param bool $raw Whether to store the raw value (unused)
+ * @return bool TRUE on success, FALSE on failure
*/
- public function save($key, $value, $ttl = NULL)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return ($ttl)
- ? $this->_redis->setex($key, $ttl, $value)
- : $this->_redis->set($key, $value);
+ ? $this->_redis->setex($id, $ttl, $data)
+ : $this->_redis->set($id, $data);
}
// ------------------------------------------------------------------------
@@ -103,6 +105,38 @@ class CI_Cache_redis extends CI_Driver
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ return $this->_redis->exists($id)
+ ? $this->_redis->incr($id, $offset)
+ : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ return $this->_redis->exists($id)
+ ? $this->_redis->decr($id, $offset)
+ : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean cache
*
* @return bool
@@ -163,12 +197,11 @@ class CI_Cache_redis extends CI_Driver
{
if (extension_loaded('redis'))
{
- $this->_setup_redis();
- return TRUE;
+ return $this->_setup_redis();
}
else
{
- log_message('error', 'The Redis extension must be loaded to use Redis cache.');
+ log_message('debug', 'The Redis extension must be loaded to use Redis cache.');
return FALSE;
}
}
@@ -200,17 +233,33 @@ class CI_Cache_redis extends CI_Driver
try
{
- $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+ if ($config['socket_type'] === 'unix')
+ {
+ $success = $this->_redis->connect($config['socket']);
+ }
+ else // tcp socket
+ {
+ $success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+ }
+
+ if ( ! $success)
+ {
+ log_message('debug', 'Cache: Redis connection refused. Check the config.');
+ return FALSE;
+ }
}
catch (RedisException $e)
{
- show_error('Redis connection refused. ' . $e->getMessage());
+ log_message('debug', 'Cache: Redis connection refused ('.$e->getMessage().')');
+ return FALSE;
}
if (isset($config['password']))
{
$this->_redis->auth($config['password']);
}
+
+ return TRUE;
}
// ------------------------------------------------------------------------
diff --git a/system/libraries/Cache/drivers/Cache_wincache.php b/system/libraries/Cache/drivers/Cache_wincache.php
index d749978f5..25c18ab58 100644
--- a/system/libraries/Cache/drivers/Cache_wincache.php
+++ b/system/libraries/Cache/drivers/Cache_wincache.php
@@ -46,8 +46,8 @@ class CI_Cache_wincache extends CI_Driver {
* Look for a value in the cache. If it exists, return the data,
* if not, return FALSE
*
- * @param string
- * @return mixed value that is stored/FALSE on failure
+ * @param string $id Cache Ide
+ * @return mixed Value that is stored/FALSE on failure
*/
public function get($id)
{
@@ -63,12 +63,13 @@ class CI_Cache_wincache extends CI_Driver {
/**
* Cache Save
*
- * @param string Unique Key
- * @param mixed Data to store
- * @param int Length of time (in seconds) to cache the data
+ * @param string $id Cache ID
+ * @param mixed $data Data to store
+ * @param int $ttl Time to live (in seconds)
+ * @param bool $raw Whether to store the raw value (unused)
* @return bool true on success/false on failure
*/
- public function save($id, $data, $ttl = 60)
+ public function save($id, $data, $ttl = 60, $raw = FALSE)
{
return wincache_ucache_set($id, $data, $ttl);
}
@@ -89,6 +90,40 @@ class CI_Cache_wincache extends CI_Driver {
// ------------------------------------------------------------------------
/**
+ * Increment a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to add
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function increment($id, $offset = 1)
+ {
+ $success = FALSE;
+ $value = wincache_ucache_inc($id, $offset, $success);
+
+ return ($success === TRUE) ? $value : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
+ * Decrement a raw value
+ *
+ * @param string $id Cache ID
+ * @param int $offset Step/value to reduce by
+ * @return mixed New value on success or FALSE on failure
+ */
+ public function decrement($id, $offset = 1)
+ {
+ $success = FALSE;
+ $value = wincache_ucache_dec($id, $offset, $success);
+
+ return ($success === TRUE) ? $value : FALSE;
+ }
+
+ // ------------------------------------------------------------------------
+
+ /**
* Clean the cache
*
* @return bool false on failure/true on success
@@ -150,7 +185,7 @@ class CI_Cache_wincache extends CI_Driver {
{
if ( ! extension_loaded('wincache'))
{
- log_message('error', 'The Wincache PHP extension must be loaded to use Wincache Cache.');
+ log_message('debug', 'The Wincache PHP extension must be loaded to use Wincache Cache.');
return FALSE;
}
diff --git a/system/libraries/Calendar.php b/system/libraries/Calendar.php
index 9c68c94c1..fc6599931 100644
--- a/system/libraries/Calendar.php
+++ b/system/libraries/Calendar.php
@@ -96,6 +96,13 @@ class CI_Calendar {
public $next_prev_url = '';
/**
+ * Show days of other months
+ *
+ * @var bool
+ */
+ public $show_other_days = FALSE;
+
+ /**
* Class constructor
*
* Loads the calendar language file and sets the default time reference.
@@ -143,6 +150,12 @@ class CI_Calendar {
$this->$key = $val;
}
}
+
+ // Set the next_prev_url to the controller if required but not defined
+ if ($this->show_next_prev === TRUE && empty($this->next_prev_url))
+ {
+ $this->next_prev_url = $this->CI->config->site_url($this->CI->router->class.'/'.$this->CI->router->method);
+ }
}
// --------------------------------------------------------------------
@@ -261,10 +274,10 @@ class CI_Calendar {
for ($i = 0; $i < 7; $i++)
{
- $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->temp['cal_cell_start_today'] : $this->temp['cal_cell_start'];
-
if ($day > 0 && $day <= $total_days)
{
+ $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->temp['cal_cell_start_today'] : $this->temp['cal_cell_start'];
+
if (isset($data[$day]))
{
// Cells with content
@@ -279,14 +292,34 @@ class CI_Calendar {
$this->temp['cal_cell_no_content_today'] : $this->temp['cal_cell_no_content'];
$out .= str_replace('{day}', $day, $temp);
}
+
+ $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->temp['cal_cell_end_today'] : $this->temp['cal_cell_end'];
+ }
+ elseif ($this->show_other_days === TRUE)
+ {
+ $out .= $this->temp['cal_cell_start_other'];
+
+ if ($day <= 0)
+ {
+ // Day of previous month
+ $prev_month = $this->adjust_date($month - 1, $year);
+ $prev_month_days = $this->get_total_days($prev_month['month'], $prev_month['year']);
+ $out .= str_replace('{day}', $prev_month_days + $day, $this->temp['cal_cell_other']);
+ }
+ else
+ {
+ // Day of next month
+ $out .= str_replace('{day}', $day - $total_days, $this->temp['cal_cell_other']);
+ }
+
+ $out .= $this->temp['cal_cell_end_other'];
}
else
{
// Blank cells
- $out .= $this->temp['cal_cell_blank'];
+ $out .= $this->temp['cal_cell_start'].$this->temp['cal_cell_blank'].$this->temp['cal_cell_end'];
}
- $out .= ($is_current_month === TRUE && $day == $cur_day) ? $this->temp['cal_cell_end_today'] : $this->temp['cal_cell_end'];
$day++;
}
@@ -457,13 +490,16 @@ class CI_Calendar {
'cal_row_start' => '<tr>',
'cal_cell_start' => '<td>',
'cal_cell_start_today' => '<td>',
+ 'cal_cell_start_other' => '<td style="color: #666;">',
'cal_cell_content' => '<a href="{content}">{day}</a>',
'cal_cell_content_today' => '<a href="{content}"><strong>{day}</strong></a>',
'cal_cell_no_content' => '{day}',
'cal_cell_no_content_today' => '<strong>{day}</strong>',
'cal_cell_blank' => '&nbsp;',
+ 'cal_cell_other' => '{day}',
'cal_cell_end' => '</td>',
'cal_cell_end_today' => '</td>',
+ 'cal_cell_end_other' => '</td>',
'cal_row_end' => '</tr>',
'table_close' => '</table>'
);
@@ -490,7 +526,7 @@ class CI_Calendar {
$today = array('cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today');
- foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today') as $val)
+ foreach (array('table_open', 'table_close', 'heading_row_start', 'heading_previous_cell', 'heading_title_cell', 'heading_next_cell', 'heading_row_end', 'week_row_start', 'week_day_cell', 'week_row_end', 'cal_row_start', 'cal_cell_start', 'cal_cell_content', 'cal_cell_no_content', 'cal_cell_blank', 'cal_cell_end', 'cal_row_end', 'cal_cell_start_today', 'cal_cell_content_today', 'cal_cell_no_content_today', 'cal_cell_end_today', 'cal_cell_start_other', 'cal_cell_other', 'cal_cell_end_other') as $val)
{
if (preg_match('/\{'.$val.'\}(.*?)\{\/'.$val.'\}/si', $this->template, $match))
{
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 46ffaa1d4..f4efff882 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -399,9 +399,9 @@ class CI_Email {
else
{
$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
- $this->_safe_mode = (bool) @ini_get('safe_mode');
}
+ $this->_safe_mode = ( ! is_php('5.4') && (bool) @ini_get('safe_mode'));
$this->charset = strtoupper($this->charset);
log_message('debug', 'Email Class Initialized');
@@ -451,7 +451,6 @@ class CI_Email {
$this->clear();
$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
- $this->_safe_mode = (bool) @ini_get('safe_mode');
return $this;
}
@@ -711,18 +710,42 @@ class CI_Email {
/**
* Assign file attachments
*
- * @param string $filename
+ * @param string $file Can be local path, URL or buffered content
* @param string $disposition = 'attachment'
* @param string $newname = NULL
* @param string $mime = ''
* @return CI_Email
*/
- public function attach($filename, $disposition = '', $newname = NULL, $mime = '')
+ public function attach($file, $disposition = '', $newname = NULL, $mime = '')
{
+ if ($mime === '')
+ {
+ if (strpos($file, '://') === FALSE && ! file_exists($file))
+ {
+ $this->_set_error_message('lang:email_attachment_missing', $file);
+ return FALSE;
+ }
+
+ if ( ! $fp = @fopen($file, FOPEN_READ))
+ {
+ $this->_set_error_message('lang:email_attachment_unreadable', $file);
+ return FALSE;
+ }
+
+ $file_content = stream_get_contents($fp);
+ $mime = $this->_mime_types(pathinfo($file, PATHINFO_EXTENSION));
+ fclose($fp);
+ }
+ else
+ {
+ $file_content =& $file; // buffered file
+ }
+
$this->_attachments[] = array(
- 'name' => array($filename, $newname),
+ 'name' => array($file, $newname),
'disposition' => empty($disposition) ? 'attachment' : $disposition, // Can also be 'inline' Not sure if it matters
- 'type' => $mime
+ 'type' => $mime,
+ 'content' => chunk_split(base64_encode($file_content))
);
return $this;
@@ -731,6 +754,35 @@ class CI_Email {
// --------------------------------------------------------------------
/**
+ * Set and return attachment Content-ID
+ *
+ * Useful for attached inline pictures
+ *
+ * @param string $filename
+ * @return string
+ */
+ public function attachment_cid($filename)
+ {
+ if ($this->multipart !== 'related')
+ {
+ $this->multipart = 'related'; // Thunderbird need this for inline images
+ }
+
+ for ($i = 0, $c = count($this->_attachments); $i < $c; $i++)
+ {
+ if ($this->_attachments[$i]['name'][0] === $filename)
+ {
+ $this->_attachments[$i]['cid'] = uniqid(basename($this->_attachments[$i]['name'][0]).'@');
+ return $this->_attachments[$i]['cid'];
+ }
+ }
+
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
* Add a Header Item
*
* @param string
@@ -1265,7 +1317,7 @@ class CI_Email {
}
else
{
- $this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
+ $this->_finalbody = $hdr.$this->newline.$this->newline.$this->_body;
}
return;
@@ -1275,11 +1327,11 @@ class CI_Email {
if ($this->send_multipart === FALSE)
{
$hdr .= 'Content-Type: text/html; charset='.$this->charset.$this->newline
- .'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline;
+ .'Content-Transfer-Encoding: quoted-printable';
}
else
{
- $hdr .= 'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"'.$this->newline.$this->newline;
+ $hdr .= 'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"';
$body .= $this->_get_mime_message().$this->newline.$this->newline
.'--'.$this->_alt_boundary.$this->newline
@@ -1300,7 +1352,7 @@ class CI_Email {
}
else
{
- $this->_finalbody = $hdr.$this->_finalbody;
+ $this->_finalbody = $hdr.$this->newline.$this->newline.$this->_finalbody;
}
if ($this->send_multipart !== FALSE)
@@ -1312,25 +1364,25 @@ class CI_Email {
case 'plain-attach' :
- $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
+ $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"';
if ($this->_get_protocol() === 'mail')
{
$this->_header_str .= $hdr;
}
- $body .= $this->_get_mime_message().$this->newline.$this->newline
+ $body .= $this->_get_mime_message().$this->newline
+ .$this->newline
.'--'.$this->_atc_boundary.$this->newline
-
.'Content-Type: text/plain; charset='.$this->charset.$this->newline
- .'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline
-
+ .'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline
+ .$this->newline
.$this->_body.$this->newline.$this->newline;
break;
case 'html-attach' :
- $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
+ $hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"';
if ($this->_get_protocol() === 'mail')
{
@@ -1362,45 +1414,22 @@ class CI_Email {
$filename = $this->_attachments[$i]['name'][0];
$basename = ($this->_attachments[$i]['name'][1] === NULL)
? basename($filename) : $this->_attachments[$i]['name'][1];
- $ctype = $this->_attachments[$i]['type'];
- $file_content = '';
-
- if ($ctype === '')
- {
- if ( ! file_exists($filename))
- {
- $this->_set_error_message('lang:email_attachment_missing', $filename);
- return FALSE;
- }
-
- $file = filesize($filename) +1;
-
- if ( ! $fp = fopen($filename, FOPEN_READ))
- {
- $this->_set_error_message('lang:email_attachment_unreadable', $filename);
- return FALSE;
- }
-
- $ctype = $this->_mime_types(pathinfo($filename, PATHINFO_EXTENSION));
- $file_content = fread($fp, $file);
- fclose($fp);
- }
- else
- {
- $file_content =& $this->_attachments[$i]['name'][0];
- }
$attachment[$z++] = '--'.$this->_atc_boundary.$this->newline
- .'Content-type: '.$ctype.'; '
+ .'Content-type: '.$this->_attachments[$i]['type'].'; '
.'name="'.$basename.'"'.$this->newline
.'Content-Disposition: '.$this->_attachments[$i]['disposition'].';'.$this->newline
- .'Content-Transfer-Encoding: base64'.$this->newline;
+ .'Content-Transfer-Encoding: base64'.$this->newline
+ .(empty($this->_attachments[$i]['cid']) ? '' : 'Content-ID: <'.$this->_attachments[$i]['cid'].'>'.$this->newline);
- $attachment[$z++] = chunk_split(base64_encode($file_content));
+ $attachment[$z++] = $this->_attachments[$i]['content'];
}
$body .= implode($this->newline, $attachment).$this->newline.'--'.$this->_atc_boundary.'--';
- $this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr.$body;
+ $this->_finalbody = ($this->_get_protocol() === 'mail')
+ ? $body
+ : $hdr.$this->newline.$this->newline.$body;
+
return TRUE;
}
@@ -2068,7 +2097,16 @@ class CI_Email {
*/
protected function _send_data($data)
{
- if ( ! fwrite($this->_smtp_connect, $data.$this->newline))
+ $data .= $this->newline;
+ for ($written = 0, $length = strlen($data); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($this->_smtp_connect, substr($data, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
+ if ($result === FALSE)
{
$this->_set_error_message('lang:email_smtp_data_failure', $data);
return FALSE;
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 40ba01202..58485916c 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -144,14 +144,16 @@ class CI_Form_validation {
* Set Rules
*
* This function takes an array of field names and validation
- * rules as input, validates the info, and stores it
+ * rules as input, any custom error messages, validates the info,
+ * and stores it
*
* @param mixed $field
* @param string $label
* @param mixed $rules
+ * @param array $errors
* @return CI_Form_validation
*/
- public function set_rules($field, $label = '', $rules = '')
+ public function set_rules($field, $label = '', $rules = '', $errors = array())
{
// No reason to set rules if we have no POST data
// or a validation array has not been specified
@@ -175,8 +177,11 @@ class CI_Form_validation {
// If the field label wasn't passed we use the field name
$label = isset($row['label']) ? $row['label'] : $row['field'];
+ // Add the custom error message array
+ $errors = (isset($row['errors']) && is_array($row['errors'])) ? $row['errors'] : array();
+
// Here we go!
- $this->set_rules($row['field'], $label, $row['rules']);
+ $this->set_rules($row['field'], $label, $row['rules'], $errors);
}
return $this;
@@ -224,6 +229,7 @@ class CI_Form_validation {
'field' => $field,
'label' => $label,
'rules' => $rules,
+ 'errors' => $errors,
'is_array' => $is_array,
'keys' => $indexes,
'postdata' => NULL,
@@ -248,9 +254,9 @@ class CI_Form_validation {
* @param array $data
* @return void
*/
- public function set_data($data = '')
+ public function set_data(array $data)
{
- if ( ! empty($data) && is_array($data))
+ if ( ! empty($data))
{
$this->validation_data = $data;
}
@@ -304,12 +310,12 @@ class CI_Form_validation {
*
* Gets the error message associated with a particular field
*
- * @param string the field name
- * @param string the html start tag
- * @param strign the html end tag
+ * @param string $field Field name
+ * @param string $prefix HTML start tag
+ * @param string $suffix HTML end tag
* @return string
*/
- public function error($field = '', $prefix = '', $suffix = '')
+ public function error($field, $prefix = '', $suffix = '')
{
if (empty($this->_field_data[$field]['error']))
{
@@ -414,18 +420,15 @@ class CI_Form_validation {
return FALSE;
}
- // Is there a validation rule for the particular URI being accessed?
- $uri = ($group === '') ? trim($this->CI->uri->ruri_string(), '/') : $group;
-
- if ($uri !== '' && isset($this->_config_rules[$uri]))
- {
- $this->set_rules($this->_config_rules[$uri]);
- }
- else
+ if (empty($group))
{
- $this->set_rules($this->_config_rules);
+ // Is there a validation rule for the particular URI being accessed?
+ $group = trim($this->CI->uri->ruri_string(), '/');
+ isset($this->_config_rules[$group]) OR $group = $this->CI->router->class.'/'.$this->CI->router->method;
}
+ $this->set_rules(isset($this->_config_rules[$group]) ? $this->_config_rules[$group] : $this->_config_rules);
+
// Were we able to set the rules correctly?
if (count($this->_field_data) === 0)
{
@@ -583,7 +586,7 @@ class CI_Form_validation {
// If the field is blank, but NOT required, no further tests are necessary
$callback = FALSE;
- if ( ! in_array('required', $rules) && $postdata === NULL)
+ if ( ! in_array('required', $rules) && ($postdata === NULL OR $postdata === ''))
{
// Before we bail out, does the rule contain a callback?
if (preg_match('/(callback_\w+(\[.*?\])?)/', implode(' ', $rules), $match))
@@ -598,14 +601,19 @@ class CI_Form_validation {
}
// Isset Test. Typically this rule will only apply to checkboxes.
- if ($postdata === NULL && $callback === FALSE)
+ if (($postdata === NULL OR $postdata === '') && $callback === FALSE)
{
if (in_array('isset', $rules, TRUE) OR in_array('required', $rules))
{
// Set the message type
$type = in_array('required', $rules) ? 'required' : 'isset';
- if (isset($this->_error_messages[$type]))
+ // Check if a custom message is defined
+ if (isset($this->_field_data[$row['field']]['errors'][$type]))
+ {
+ $line = $this->_field_data[$row['field']]['errors'][$type];
+ }
+ elseif (isset($this->_error_messages[$type]))
{
$line = $this->_error_messages[$type];
}
@@ -749,7 +757,12 @@ class CI_Form_validation {
// Did the rule test negatively? If so, grab the error.
if ($result === FALSE)
{
- if ( ! isset($this->_error_messages[$rule]))
+ // Check if a custom message is defined
+ if (isset($this->_field_data[$row['field']]['errors'][$rule]))
+ {
+ $line = $this->_field_data[$row['field']]['errors'][$rule];
+ }
+ elseif ( ! isset($this->_error_messages[$rule]))
{
if (FALSE === ($line = $this->CI->lang->line('form_validation_'.$rule))
// DEPRECATED support for non-prefixed keys
@@ -898,12 +911,19 @@ class CI_Form_validation {
}
$field = $this->_field_data[$field]['postdata'];
+ $value = (string) $value;
if (is_array($field))
{
- if ( ! in_array($value, $field))
+ // Note: in_array('', array(0)) returns TRUE, do not use it
+ foreach ($field as &$v)
{
- return '';
+ if ($value === $v)
+ {
+ return ' selected="selected"';
+ }
}
+
+ return '';
}
elseif (($field === '' OR $value === '') OR ($field !== $value))
{
@@ -934,12 +954,19 @@ class CI_Form_validation {
}
$field = $this->_field_data[$field]['postdata'];
+ $value = (string) $value;
if (is_array($field))
{
- if ( ! in_array($value, $field))
+ // Note: in_array('', array(0)) returns TRUE, do not use it
+ foreach ($field as &$v)
{
- return '';
+ if ($value === $v)
+ {
+ return ' checked="checked"';
+ }
}
+
+ return '';
}
elseif (($field === '' OR $value === '') OR ($field !== $value))
{
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index dc6bbd226..73a68441a 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -214,12 +214,12 @@ class CI_FTP {
* Internally, this parameter is only used by the "mirror" function below.
*
* @param string $path
- * @param bool $supress_debug
+ * @param bool $suppress_debug
* @return bool
*/
- public function changedir($path = '', $supress_debug = FALSE)
+ public function changedir($path, $suppress_debug = FALSE)
{
- if ($path === '' OR ! $this->_is_conn())
+ if ( ! $this->_is_conn())
{
return FALSE;
}
@@ -228,7 +228,7 @@ class CI_FTP {
if ($result === FALSE)
{
- if ($this->debug === TRUE && $supress_debug === FALSE)
+ if ($this->debug === TRUE && $suppress_debug === FALSE)
{
$this->_error('ftp_unable_to_changedir');
}
@@ -247,7 +247,7 @@ class CI_FTP {
* @param int $permissions
* @return bool
*/
- public function mkdir($path = '', $permissions = NULL)
+ public function mkdir($path, $permissions = NULL)
{
if ($path === '' OR ! $this->_is_conn())
{
@@ -260,7 +260,7 @@ class CI_FTP {
{
if ($this->debug === TRUE)
{
- $this->_error('ftp_unable_to_makdir');
+ $this->_error('ftp_unable_to_mkdir');
}
return FALSE;
}
@@ -392,7 +392,7 @@ class CI_FTP {
{
if ($this->debug === TRUE)
{
- $this->_error('ftp_unable_to_' . ($move === FALSE ? 'rename' : 'move'));
+ $this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move'));
}
return FALSE;
}
diff --git a/system/libraries/Javascript.php b/system/libraries/Javascript.php
index 090f4c90e..26a16850c 100644
--- a/system/libraries/Javascript.php
+++ b/system/libraries/Javascript.php
@@ -172,7 +172,7 @@ class CI_Javascript {
*/
public function focus($element = 'this', $js = '')
{
- return $this->js->__add_event($element, $js);
+ return $this->js->_focus($element, $js);
}
// --------------------------------------------------------------------
@@ -189,7 +189,7 @@ class CI_Javascript {
*/
public function hover($element = 'this', $over = '', $out = '')
{
- return $this->js->__hover($element, $over, $out);
+ return $this->js->_hover($element, $over, $out);
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Javascript/Jquery.php b/system/libraries/Javascript/Jquery.php
index f5fa72d30..ab78e8b2e 100644
--- a/system/libraries/Javascript/Jquery.php
+++ b/system/libraries/Javascript/Jquery.php
@@ -923,7 +923,6 @@ class CI_Jquery extends CI_Javascript {
if (is_array($js))
{
$js = implode("\n\t\t", $js);
-
}
$event = "\n\t$(".$this->_prep_element($element).').'.$event."(function(){\n\t\t{$js}\n\t});\n";
@@ -937,7 +936,7 @@ class CI_Jquery extends CI_Javascript {
* Compile
*
* As events are specified, they are stored in an array
- * This funciton compiles them all for output on a page
+ * This function compiles them all for output on a page
*
* @param string $view_var
* @param bool $script_tags
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 10fb29dbd..c6ffd03d4 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -354,7 +354,8 @@ class CI_Pagination {
public function create_links()
{
// If our item count or per-page total is zero there is no need to continue.
- if ($this->total_rows === 0 OR $this->per_page === 0)
+ // Note: DO NOT change the operator to === here!
+ if ($this->total_rows == 0 OR $this->per_page == 0)
{
return '';
}
diff --git a/system/libraries/Parser.php b/system/libraries/Parser.php
index c1f1ad73b..399131cdd 100644
--- a/system/libraries/Parser.php
+++ b/system/libraries/Parser.php
@@ -187,26 +187,34 @@ class CI_Parser {
*/
protected function _parse_pair($variable, $data, $string)
{
- if (FALSE === ($match = $this->_match_pair($string, $variable)))
+ if (FALSE === ($matches = $this->_match_pair($string, $variable)))
{
return $string;
}
$str = '';
- foreach ($data as $row)
+ $search = $replace = array();
+ foreach ($matches as $match)
{
- $temp = $match[1];
- foreach ($row as $key => $val)
+ $str = '';
+ foreach ($data as $row)
{
- $temp = is_array($val)
+ $temp = $match[1];
+ foreach ($row as $key => $val)
+ {
+ $temp = is_array($val)
? $this->_parse_pair($key, $val, $temp)
: $this->_parse_single($key, $val, $temp);
+ }
+
+ $str .= $temp;
}
- $str .= $temp;
+ $search[] = $match[0];
+ $replace[] = $str;
}
- return str_replace($match[0], $str, $string);
+ return str_replace($search, $replace, $string);
}
// --------------------------------------------------------------------
@@ -214,14 +222,14 @@ class CI_Parser {
/**
* Matches a variable pair
*
- * @param string
- * @param string
+ * @param string $string
+ * @param string $variable
* @return mixed
*/
protected function _match_pair($string, $variable)
{
- return preg_match('|'.preg_quote($this->l_delim).$variable.preg_quote($this->r_delim).'(.+?)'.preg_quote($this->l_delim).'/'.$variable.preg_quote($this->r_delim).'|s',
- $string, $match)
+ return preg_match_all('|'.preg_quote($this->l_delim).$variable.preg_quote($this->r_delim).'(.+?)'.preg_quote($this->l_delim).'/'.$variable.preg_quote($this->r_delim).'|s',
+ $string, $match, PREG_SET_ORDER)
? $match : FALSE;
}
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index 9e9e7d08d..4e556b23d 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -278,6 +278,7 @@ class CI_Profiler {
}
$output .= "</table>\n</fieldset>";
+ $count++;
}
return $output;
@@ -307,10 +308,7 @@ class CI_Profiler {
foreach ($_GET as $key => $val)
{
- if ( ! is_numeric($key))
- {
- $key = "'".$key."'";
- }
+ is_int($key) OR $key = "'".$key."'";
$output .= '<tr><td style="width:50%;color:#000;background-color:#ddd;padding:5px;">&#36;_GET['
.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;">'
@@ -338,7 +336,7 @@ class CI_Profiler {
."\n"
.'<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data')."&nbsp;&nbsp;</legend>\n";
- if (count($_POST) === 0)
+ if (count($_POST) === 0 && count($_FILES) === 0)
{
$output .= '<div style="color:#009900;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_post').'</div>';
}
@@ -348,10 +346,7 @@ class CI_Profiler {
foreach ($_POST as $key => $val)
{
- if ( ! is_numeric($key))
- {
- $key = "'".$key."'";
- }
+ is_int($key) OR $key = "'".$key."'";
$output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">&#36;_POST['
.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">';
@@ -368,6 +363,21 @@ class CI_Profiler {
$output .= "</td></tr>\n";
}
+ foreach ($_FILES as $key => $val)
+ {
+ is_int($key) OR $key = "'".$key."'";
+
+ $output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">&#36;_FILES['
+ .$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">';
+
+ if (is_array($val) OR is_object($val))
+ {
+ $output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>';
+ }
+
+ $output .= "</td></tr>\n";
+ }
+
$output .= "</table>\n";
}
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index c7f6f828c..ac97b944c 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -60,11 +60,18 @@ class CI_Session extends CI_Driver_Library {
public $params = array();
/**
+ * Valid drivers list
+ *
+ * @var array
+ */
+ public $valid_drivers = array('native', 'cookie');
+
+ /**
* Current driver in use
*
* @var string
*/
- protected $current = NULL;
+ public $current = NULL;
/**
* User data
@@ -95,46 +102,36 @@ class CI_Session extends CI_Driver_Library {
*/
public function __construct(array $params = array())
{
- $CI =& get_instance();
+ $_config =& get_instance()->config;
// No sessions under CLI
- if ($CI->input->is_cli_request())
+ if (is_cli())
{
return;
}
log_message('debug', 'CI_Session Class Initialized');
- // Get valid drivers list
- $this->valid_drivers = array(
- 'native',
- 'cookie'
- );
- $key = 'sess_valid_drivers';
- $drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
- if ($drivers)
+ // Add possible extra entries to our valid drivers list
+ $drivers = isset($params['sess_valid_drivers']) ? $params['sess_valid_drivers'] : $_config->item('sess_valid_drivers');
+ if ( ! empty($drivers))
{
- // Add driver names to valid list
- foreach ((array) $drivers as $driver)
- {
- if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
- {
- $this->valid_drivers[] = $driver;
- }
- }
+ $drivers = array_map('strtolower', (array) $drivers);
+ $this->valid_drivers = array_merge($this->valid_drivers, array_diff($drivers, $this->valid_drivers));
}
// Get driver to load
- $key = 'sess_driver';
- $driver = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+ $driver = isset($params['sess_driver']) ? $params['sess_driver'] : $_config->item('sess_driver');
if ( ! $driver)
{
+ log_message('debug', "Session: No driver name is configured, defaulting to 'cookie'.");
$driver = 'cookie';
}
- if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+ if ( ! in_array($driver, $this->valid_drivers))
{
- $this->valid_drivers[] = $driver;
+ log_message('error', 'Session: Configured driver name is not valid, aborting.');
+ return;
}
// Save a copy of parameters in case drivers need access
@@ -291,7 +288,7 @@ class CI_Session extends CI_Driver_Library {
* @param string Item value or empty string
* @return void
*/
- public function set_userdata($newdata = array(), $newval = '')
+ public function set_userdata($newdata, $newval = '')
{
// Wrap params as array if singular
if (is_string($newdata))
@@ -320,7 +317,7 @@ class CI_Session extends CI_Driver_Library {
* @param mixed Item name or array of item names
* @return void
*/
- public function unset_userdata($newdata = array())
+ public function unset_userdata($newdata)
{
// Wrap single name as array
if (is_string($newdata))
@@ -363,7 +360,7 @@ class CI_Session extends CI_Driver_Library {
* @param string Item value or empty string
* @return void
*/
- public function set_flashdata($newdata = array(), $newval = '')
+ public function set_flashdata($newdata, $newval = '')
{
// Wrap item as array if singular
if (is_string($newdata))
@@ -437,7 +434,7 @@ class CI_Session extends CI_Driver_Library {
* @param int Item lifetime in seconds or 0 for default
* @return void
*/
- public function set_tempdata($newdata = array(), $newval = '', $expire = 0)
+ public function set_tempdata($newdata, $newval = '', $expire = 0)
{
// Set expiration time
$expire = time() + ($expire ? $expire : self::TEMP_EXP_DEF);
@@ -478,7 +475,7 @@ class CI_Session extends CI_Driver_Library {
* @param mixed Item name or array of item names
* @return void
*/
- public function unset_tempdata($newdata = array())
+ public function unset_tempdata($newdata)
{
// Get expirations list
$expirations = $this->userdata(self::EXPIRATION_KEY);
diff --git a/system/libraries/Session/drivers/Session_cookie.php b/system/libraries/Session/drivers/Session_cookie.php
index d3d22d03a..971dfeabe 100644
--- a/system/libraries/Session/drivers/Session_cookie.php
+++ b/system/libraries/Session/drivers/Session_cookie.php
@@ -165,6 +165,8 @@ class CI_Session_cookie extends CI_Session_driver {
*/
public $now;
+ // ------------------------------------------------------------------------
+
/**
* Default userdata keys
*
@@ -185,6 +187,15 @@ class CI_Session_cookie extends CI_Session_driver {
protected $data_dirty = FALSE;
/**
+ * Standardize newlines flag
+ *
+ * @var bool
+ */
+ protected $_standardize_newlines;
+
+ // ------------------------------------------------------------------------
+
+ /**
* Initialize session driver object
*
* @return void
@@ -209,9 +220,11 @@ class CI_Session_cookie extends CI_Session_driver {
'sess_time_to_update',
'time_reference',
'cookie_prefix',
- 'encryption_key'
+ 'encryption_key',
);
+ $this->_standardize_newlines = (bool) config_item('standardize_newlines');
+
foreach ($prefs as $key)
{
$this->$key = isset($this->_parent->params[$key])
@@ -397,7 +410,7 @@ class CI_Session_cookie extends CI_Session_driver {
}
// Unserialize the session array
- $session = $this->_unserialize($session);
+ $session = @unserialize($session);
// Is the session data we unserialized an array with the correct format?
if ( ! is_array($session) OR ! isset($session['session_id'], $session['ip_address'], $session['user_agent'], $session['last_activity']))
@@ -472,7 +485,7 @@ class CI_Session_cookie extends CI_Session_driver {
$row = $query->row();
if ( ! empty($row->user_data))
{
- $custom_data = $this->_unserialize($row->user_data);
+ $custom_data = unserialize(trim($row->user_data));
if (is_array($custom_data))
{
@@ -608,7 +621,7 @@ class CI_Session_cookie extends CI_Session_driver {
if ( ! empty($userdata))
{
// Serialize the custom data array so we can store it
- $set['user_data'] = $this->_serialize($userdata);
+ $set['user_data'] = serialize($userdata);
}
// Reset query builder values.
@@ -695,8 +708,18 @@ class CI_Session_cookie extends CI_Session_driver {
? array_intersect_key($this->userdata, $this->defaults)
: $this->userdata;
+ // The Input class will do this and since we use HMAC verification,
+ // unless we standardize here as well, the hash won't match.
+ if ($this->_standardize_newlines)
+ {
+ foreach (array_keys($this->userdata) as $key)
+ {
+ $this->userdata[$key] = preg_replace('/(?:\r\n|[\r\n])/', PHP_EOL, $this->userdata[$key]);
+ }
+ }
+
// Serialize the userdata for the cookie
- $cookie_data = $this->_serialize($cookie_data);
+ $cookie_data = serialize($cookie_data);
if ($this->sess_encrypt_cookie === TRUE)
{
@@ -737,93 +760,6 @@ class CI_Session_cookie extends CI_Session_driver {
// ------------------------------------------------------------------------
/**
- * Serialize an array
- *
- * This function first converts any slashes found in the array to a temporary
- * marker, so when it gets unserialized the slashes will be preserved
- *
- * @param mixed Data to serialize
- * @return string Serialized data
- */
- protected function _serialize($data)
- {
- if (is_array($data))
- {
- array_walk_recursive($data, array(&$this, '_escape_slashes'));
- }
- elseif (is_string($data))
- {
- $data = str_replace('\\', '{{slash}}', $data);
- }
-
- return serialize($data);
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Escape slashes
- *
- * This function converts any slashes found into a temporary marker
- *
- * @param string Value
- * @param string Key
- * @return void
- */
- protected function _escape_slashes(&$val, $key)
- {
- if (is_string($val))
- {
- $val = str_replace('\\', '{{slash}}', $val);
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Unserialize
- *
- * This function unserializes a data string, then converts any
- * temporary slash markers back to actual slashes
- *
- * @param mixed Data to unserialize
- * @return mixed Unserialized data
- */
- protected function _unserialize($data)
- {
- $data = @unserialize(trim($data));
-
- if (is_array($data))
- {
- array_walk_recursive($data, array(&$this, '_unescape_slashes'));
- return $data;
- }
-
- return is_string($data) ? str_replace('{{slash}}', '\\', $data) : $data;
- }
-
- // ------------------------------------------------------------------------
-
- /**
- * Unescape slashes
- *
- * This function converts any slash markers back into actual slashes
- *
- * @param string Value
- * @param string Key
- * @return void
- */
- protected function _unescape_slashes(&$val, $key)
- {
- if (is_string($val))
- {
- $val = str_replace('{{slash}}', '\\', $val);
- }
- }
-
- // ------------------------------------------------------------------------
-
- /**
* Garbage collection
*
* This deletes expired session rows from database
@@ -841,7 +777,7 @@ class CI_Session_cookie extends CI_Session_driver {
$probability = ini_get('session.gc_probability');
$divisor = ini_get('session.gc_divisor');
- if ((mt_rand(0, $divisor) / $divisor) < $probability)
+ if (mt_rand(1, $divisor) <= $probability)
{
$expire = $this->now - $this->sess_expiration;
$this->CI->db->delete($this->sess_table_name, 'last_activity < '.$expire);
diff --git a/system/libraries/Unit_test.php b/system/libraries/Unit_test.php
index 7a67c7276..e412b9858 100644
--- a/system/libraries/Unit_test.php
+++ b/system/libraries/Unit_test.php
@@ -81,7 +81,15 @@ class CI_Unit_test {
*
* @var array
*/
- protected $_test_items_visible = array();
+ protected $_test_items_visible = array(
+ 'test_name',
+ 'test_datatype',
+ 'res_datatype',
+ 'result',
+ 'file',
+ 'line',
+ 'notes'
+ );
// --------------------------------------------------------------------
@@ -92,17 +100,6 @@ class CI_Unit_test {
*/
public function __construct()
{
- // These are the default items visible when a test is run.
- $this->_test_items_visible = array (
- 'test_name',
- 'test_datatype',
- 'res_datatype',
- 'result',
- 'file',
- 'line',
- 'notes'
- );
-
log_message('debug', 'Unit Testing Class Initialized');
}
@@ -113,10 +110,10 @@ class CI_Unit_test {
*
* Runs the supplied tests
*
- * @param array
+ * @param array $items
* @return void
*/
- public function set_test_items($items = array())
+ public function set_test_items($items)
{
if ( ! empty($items) && is_array($items))
{
@@ -230,7 +227,7 @@ class CI_Unit_test {
*
* Causes the evaluation to use === rather than ==
*
- * @param bool
+ * @param bool $state
* @return void
*/
public function use_strict($state = TRUE)
@@ -288,6 +285,7 @@ class CI_Unit_test {
{
$val = $line;
}
+
$temp[$CI->lang->line('ut_'.$key, FALSE)] = $val;
}
@@ -396,4 +394,4 @@ function is_false($test)
}
/* End of file Unit_test.php */
-/* Location: ./system/libraries/Unit_test.php */
+/* Location: ./system/libraries/Unit_test.php */ \ No newline at end of file
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 85428044d..525880f62 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -234,6 +234,13 @@ class CI_Upload {
public $xss_clean = FALSE;
/**
+ * Apache mod_mime fix flag
+ *
+ * @var bool
+ */
+ public $mod_mime_fix = TRUE;
+
+ /**
* Temporary filename prefix
*
* @var string
@@ -256,6 +263,13 @@ class CI_Upload {
*/
protected $_file_name_override = '';
+ /**
+ * CI Singleton
+ *
+ * @var object
+ */
+ protected $CI;
+
// --------------------------------------------------------------------
/**
@@ -272,6 +286,7 @@ class CI_Upload {
}
$this->mimes =& get_mimes();
+ $this->CI =& get_instance();
log_message('debug', 'Upload Class Initialized');
}
@@ -314,6 +329,7 @@ class CI_Upload {
'remove_spaces' => TRUE,
'detect_mime' => TRUE,
'xss_clean' => FALSE,
+ 'mod_mime_fix' => TRUE,
'temp_prefix' => 'temp_file_',
'client_name' => ''
);
@@ -463,7 +479,7 @@ class CI_Upload {
}
// Are the image dimensions within the allowed size?
- // Note: This can fail if the server has an open_basdir restriction.
+ // Note: This can fail if the server has an open_basedir restriction.
if ( ! $this->is_allowed_dimensions())
{
$this->set_error('upload_invalid_dimensions');
@@ -471,8 +487,7 @@ class CI_Upload {
}
// Sanitize the file name for security
- $CI =& get_instance();
- $this->file_name = $CI->security->sanitize_filename($this->file_name);
+ $this->file_name = $this->CI->security->sanitize_filename($this->file_name);
// Truncate the file name if it's too long
if ($this->max_filename > 0)
@@ -1073,8 +1088,7 @@ class CI_Upload {
return FALSE;
}
- $CI =& get_instance();
- return $CI->security->xss_clean($data, TRUE);
+ return $this->CI->security->xss_clean($data, TRUE);
}
// --------------------------------------------------------------------
@@ -1087,17 +1101,13 @@ class CI_Upload {
*/
public function set_error($msg)
{
- $CI =& get_instance();
- $CI->lang->load('upload');
+ $this->CI->lang->load('upload');
- if ( ! is_array($msg))
- {
- $msg = array($msg);
- }
+ is_array($msg) OR $msg = array($msg);
foreach ($msg as $val)
{
- $msg = ($CI->lang->line($val) === FALSE) ? $val : $CI->lang->line($val);
+ $msg = ($this->CI->lang->line($val) === FALSE) ? $val : $this->CI->lang->line($val);
$this->error_msg[] = $msg;
log_message('error', $msg);
}
@@ -1148,7 +1158,7 @@ class CI_Upload {
*/
protected function _prep_filename($filename)
{
- if (strpos($filename, '.') === FALSE OR $this->allowed_types === '*')
+ if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR strpos($filename, '.') === FALSE)
{
return $filename;
}
@@ -1245,7 +1255,7 @@ class CI_Upload {
}
}
- if ( (bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec'))
+ if ((bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec'))
{
$mime = @shell_exec($cmd);
if (strlen($mime) > 0)
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 2f6f81909..1dfa3e72d 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -145,6 +145,15 @@ class CI_User_agent {
public $robot = '';
/**
+ * HTTP Referer
+ *
+ * @var mixed
+ */
+ public $referer;
+
+ // --------------------------------------------------------------------
+
+ /**
* Constructor
*
* Sets the User Agent and runs the compilation routine
@@ -282,7 +291,7 @@ class CI_User_agent {
{
foreach ($this->browsers as $key => $val)
{
- if (preg_match('|'.preg_quote($key).'.*?([0-9\.]+)|i', $this->agent, $match))
+ if (preg_match('|'.$key.'.*?([0-9\.]+)|i', $this->agent, $match))
{
$this->is_browser = TRUE;
$this->version = $match[1];
@@ -358,7 +367,7 @@ class CI_User_agent {
{
if ((count($this->languages) === 0) && ! empty($_SERVER['HTTP_ACCEPT_LANGUAGE']))
{
- $this->languages = explode(',', preg_replace('/(;q=[0-9\.]+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))));
+ $this->languages = explode(',', preg_replace('/(;\s?q=[0-9\.]+)|\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_LANGUAGE']))));
}
if (count($this->languages) === 0)
@@ -378,7 +387,7 @@ class CI_User_agent {
{
if ((count($this->charsets) === 0) && ! empty($_SERVER['HTTP_ACCEPT_CHARSET']))
{
- $this->charsets = explode(',', preg_replace('/(;q=.+)/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))));
+ $this->charsets = explode(',', preg_replace('/(;\s?q=.+)|\s/i', '', strtolower(trim($_SERVER['HTTP_ACCEPT_CHARSET']))));
}
if (count($this->charsets) === 0)
@@ -471,13 +480,22 @@ class CI_User_agent {
*/
public function is_referral()
{
- if (empty($_SERVER['HTTP_REFERER']))
+ if ( ! isset($this->referer))
{
- return FALSE;
+ if (empty($_SERVER['HTTP_REFERER']))
+ {
+ $this->referer = FALSE;
+ }
+ else
+ {
+ $referer_host = @parse_url($_SERVER['HTTP_REFERER'], PHP_URL_HOST);
+ $own_host = parse_url(config_item('base_url'), PHP_URL_HOST);
+
+ $this->referer = ($referer_host && $referer_host !== $own_host);
+ }
}
- $referer = parse_url($_SERVER['HTTP_REFERER']);
- return ! (empty($referer['host']) && strpos(config_item('base_url'), $referer['host']) !== FALSE);
+ return $this->referer;
}
// --------------------------------------------------------------------
@@ -623,6 +641,34 @@ class CI_User_agent {
return in_array(strtolower($charset), $this->charsets(), TRUE);
}
+ // --------------------------------------------------------------------
+
+ /**
+ * Parse a custom user-agent string
+ *
+ * @param string $string
+ * @return void
+ */
+ public function parse($string)
+ {
+ // Reset values
+ $this->is_browser = FALSE;
+ $this->is_robot = FALSE;
+ $this->is_mobile = FALSE;
+ $this->browser = '';
+ $this->version = '';
+ $this->mobile = '';
+ $this->robot = '';
+
+ // Set the new user-agent string and parse it, unless empty
+ $this->agent = $string;
+
+ if ( ! empty($string))
+ {
+ $this->_compile_data();
+ }
+ }
+
}
/* End of file User_agent.php */
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index 16c5b0ed8..d0f6d83b3 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -348,6 +348,11 @@ class CI_Xmlrpc {
$parts = parse_url($url);
+ if (isset($parts['user'], $parts['pass']))
+ {
+ $parts['host'] = $parts['user'].':'.$parts['pass'].'@'.$parts['host'];
+ }
+
$path = isset($parts['path']) ? $parts['path'] : '/';
if ( ! empty($parts['query']))
@@ -569,6 +574,21 @@ class XML_RPC_Client extends CI_Xmlrpc
public $port = 80;
/**
+ *
+ * Server username
+ *
+ * @var string
+ */
+ public $username;
+
+ /**
+ * Server password
+ *
+ * @var string
+ */
+ public $password;
+
+ /**
* Proxy hostname
*
* @var string
@@ -626,8 +646,16 @@ class XML_RPC_Client extends CI_Xmlrpc
{
parent::__construct();
+ $url = parse_url('http://'.$server);
+
+ if (isset($url['user'], $url['pass']))
+ {
+ $this->username = $url['user'];
+ $this->password = $url['pass'];
+ }
+
$this->port = $port;
- $this->server = $server;
+ $this->server = $url['host'];
$this->path = $path;
$this->proxy = $proxy;
$this->proxy_port = $proxy_port;
@@ -691,11 +719,20 @@ class XML_RPC_Client extends CI_Xmlrpc
$op = 'POST '.$this->path.' HTTP/1.0'.$r
.'Host: '.$this->server.$r
.'Content-Type: text/xml'.$r
+ .(isset($this->username, $this->password) ? 'Authorization: Basic '.base64_encode($this->username.':'.$this->password).$r : '')
.'User-Agent: '.$this->xmlrpcName.$r
.'Content-Length: '.strlen($msg->payload).$r.$r
.$msg->payload;
- if ( ! fwrite($fp, $op, strlen($op)))
+ for ($written = 0, $length = strlen($op); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($op, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
+ if ($result === FALSE)
{
error_log($this->xmlrpcstr['http_error']);
return new XML_RPC_Response(0, $this->xmlrpcerr['http_error'], $this->xmlrpcstr['http_error']);
@@ -855,10 +892,10 @@ class XML_RPC_Response
/**
* Decode
*
- * @param mixed
+ * @param mixed $array
* @return array
*/
- public function decode($array = FALSE)
+ public function decode($array = NULL)
{
$CI =& get_instance();
@@ -870,9 +907,9 @@ class XML_RPC_Response
{
$array[$key] = $this->decode($array[$key]);
}
- else
+ elseif ($this->xss_clean)
{
- $array[$key] = ($this->xss_clean) ? $CI->security->xss_clean($array[$key]) : $array[$key];
+ $array[$key] = $CI->security->xss_clean($array[$key]);
}
}
@@ -885,9 +922,9 @@ class XML_RPC_Response
{
$result = $this->decode($result);
}
- else
+ elseif ($this->xss_clean)
{
- $result = ($this->xss_clean) ? $CI->security->xss_clean($result) : $result;
+ $result = $CI->security->xss_clean($result);
}
return $result;
@@ -1084,15 +1121,15 @@ class XML_RPC_Message extends CI_Xmlrpc
//-------------------------------------
$parser = xml_parser_create($this->xmlrpc_defencoding);
-
- $this->xh[$parser] = array(
- 'isf' => 0,
- 'ac' => '',
- 'headers' => array(),
- 'stack' => array(),
- 'valuestack' => array(),
- 'isf_reason' => 0
- );
+ $pname = (string) $parser;
+ $this->xh[$pname] = array(
+ 'isf' => 0,
+ 'ac' => '',
+ 'headers' => array(),
+ 'stack' => array(),
+ 'valuestack' => array(),
+ 'isf_reason' => 0
+ );
xml_set_object($parser, $this);
xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, TRUE);
@@ -1108,7 +1145,7 @@ class XML_RPC_Message extends CI_Xmlrpc
{
break;
}
- $this->xh[$parser]['headers'][] = $line;
+ $this->xh[$pname]['headers'][] = $line;
}
$data = implode("\r\n", $lines);
@@ -1126,18 +1163,18 @@ class XML_RPC_Message extends CI_Xmlrpc
xml_parser_free($parser);
// Got ourselves some badness, it seems
- if ($this->xh[$parser]['isf'] > 1)
+ if ($this->xh[$pname]['isf'] > 1)
{
if ($this->debug === TRUE)
{
- echo "---Invalid Return---\n".$this->xh[$parser]['isf_reason']."---Invalid Return---\n\n";
+ echo "---Invalid Return---\n".$this->xh[$pname]['isf_reason']."---Invalid Return---\n\n";
}
- return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
+ return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
}
- elseif ( ! is_object($this->xh[$parser]['value']))
+ elseif ( ! is_object($this->xh[$pname]['value']))
{
- return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$parser]['isf_reason']);
+ return new XML_RPC_Response(0, $this->xmlrpcerr['invalid_return'], $this->xmlrpcstr['invalid_return'].' '.$this->xh[$pname]['isf_reason']);
}
// Display XML content for debugging
@@ -1145,10 +1182,10 @@ class XML_RPC_Message extends CI_Xmlrpc
{
echo '<pre>';
- if (count($this->xh[$parser]['headers'] > 0))
+ if (count($this->xh[$pname]['headers'] > 0))
{
echo "---HEADERS---\n";
- foreach ($this->xh[$parser]['headers'] as $header)
+ foreach ($this->xh[$pname]['headers'] as $header)
{
echo $header."\n";
}
@@ -1156,13 +1193,13 @@ class XML_RPC_Message extends CI_Xmlrpc
}
echo "---DATA---\n".htmlspecialchars($data)."\n---END DATA---\n\n---PARSED---\n";
- var_dump($this->xh[$parser]['value']);
+ var_dump($this->xh[$pname]['value']);
echo "\n---END PARSED---</pre>";
}
// Send response
- $v = $this->xh[$parser]['value'];
- if ($this->xh[$parser]['isf'])
+ $v = $this->xh[$pname]['value'];
+ if ($this->xh[$pname]['isf'])
{
$errno_v = $v->me['struct']['faultCode'];
$errstr_v = $v->me['struct']['faultString'];
@@ -1181,7 +1218,7 @@ class XML_RPC_Message extends CI_Xmlrpc
$r = new XML_RPC_Response($v);
}
- $r->headers = $this->xh[$parser]['headers'];
+ $r->headers = $this->xh[$pname]['headers'];
return $r;
}
@@ -1212,6 +1249,8 @@ class XML_RPC_Message extends CI_Xmlrpc
*/
public function open_tag($the_parser, $name)
{
+ $the_parser = (string) $the_parser;
+
// If invalid nesting, then return
if ($this->xh[$the_parser]['isf'] > 1) return;
@@ -1311,6 +1350,8 @@ class XML_RPC_Message extends CI_Xmlrpc
*/
public function closing_tag($the_parser, $name)
{
+ $the_parser = (string) $the_parser;
+
if ($this->xh[$the_parser]['isf'] > 1) return;
// Remove current element from stack and set variable
@@ -1443,6 +1484,8 @@ class XML_RPC_Message extends CI_Xmlrpc
*/
public function character_data($the_parser, $data)
{
+ $the_parser = (string) $the_parser;
+
if ($this->xh[$the_parser]['isf'] > 1) return; // XML Fault found already
// If a value has not been found
@@ -1480,14 +1523,14 @@ class XML_RPC_Message extends CI_Xmlrpc
/**
* Output parameters
*
- * @param array
+ * @param array $array
* @return array
*/
- public function output_parameters($array = FALSE)
+ public function output_parameters(array $array = array())
{
$CI =& get_instance();
- if (is_array($array))
+ if ( ! empty($array))
{
while (list($key) = each($array))
{
@@ -1495,11 +1538,11 @@ class XML_RPC_Message extends CI_Xmlrpc
{
$array[$key] = $this->output_parameters($array[$key]);
}
- else
+ elseif ($key !== 'bits' && $this->xss_clean)
{
// 'bits' is for the MetaWeblog API image bits
// @todo - this needs to be made more general purpose
- $array[$key] = ($key === 'bits' OR $this->xss_clean === FALSE) ? $array[$key] : $CI->security->xss_clean($array[$key]);
+ $array[$key] = $CI->security->xss_clean($array[$key]);
}
}
@@ -1684,7 +1727,7 @@ class XML_RPC_Values extends CI_Xmlrpc
{
if ($this->mytype !== 0)
{
- echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+ echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
return 0;
}
@@ -1705,7 +1748,7 @@ class XML_RPC_Values extends CI_Xmlrpc
{
if ($this->mytype !== 0)
{
- echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+ echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
return 0;
}
$this->mytype = $this->xmlrpcTypes['struct'];
diff --git a/system/libraries/Xmlrpcs.php b/system/libraries/Xmlrpcs.php
index d263d789d..50ff423f2 100644
--- a/system/libraries/Xmlrpcs.php
+++ b/system/libraries/Xmlrpcs.php
@@ -384,17 +384,13 @@ class CI_Xmlrpcs extends CI_Xmlrpc {
{
return call_user_func(array($this, $method_parts[1]), $m);
}
+ elseif ($this->object === FALSE)
+ {
+ return get_instance()->$method_parts[1]($m);
+ }
else
{
- if ($this->object === FALSE)
- {
- $CI =& get_instance();
- return $CI->$method_parts[1]($m);
- }
- else
- {
- return $this->object->$method_parts[1]($m);
- }
+ return $this->object->$method_parts[1]($m);
}
}
else
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index 6608f050e..b10b0bb0f 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -103,12 +103,12 @@ class CI_Zip {
*
* Lets you add a virtual directory into which you can place files.
*
- * @param mixed the directory name. Can be string or array
+ * @param mixed $directory the directory name. Can be string or array
* @return void
*/
public function add_dir($directory)
{
- foreach ( (array) $directory as $dir)
+ foreach ((array) $directory as $dir)
{
if ( ! preg_match('|.+/$|', $dir))
{
@@ -127,7 +127,7 @@ class CI_Zip {
*
* If this is a newly created file/dir, we will set the time to 'now'
*
- * @param string path to file
+ * @param string $dir path to file
* @return array filemtime/filemdate
*/
protected function _get_mod_time($dir)
@@ -146,9 +146,9 @@ class CI_Zip {
/**
* Add Directory
*
- * @param string the directory name
- * @param int
- * @param int
+ * @param string $dir the directory name
+ * @param int $file_mtime
+ * @param int $file_mdate
* @return void
*/
protected function _add_dir($dir, $file_mtime, $file_mdate)
@@ -199,8 +199,8 @@ class CI_Zip {
* in the filename it will be placed within a directory. Make
* sure you use add_dir() first to create the folder.
*
- * @param mixed
- * @param string
+ * @param mixed $filepath A single filepath or an array of file => data pairs
+ * @param string $data Single file contents
* @return void
*/
public function add_data($filepath, $data = NULL)
@@ -225,10 +225,10 @@ class CI_Zip {
/**
* Add Data to Zip
*
- * @param string the file name/path
- * @param string the data to be encoded
- * @param int
- * @param int
+ * @param string $filepath the file name/path
+ * @param string $data the data to be encoded
+ * @param int $file_mtime
+ * @param int $file_mdate
* @return void
*/
protected function _add_data($filepath, $data, $file_mtime, $file_mdate)
@@ -278,23 +278,26 @@ class CI_Zip {
/**
* Read the contents of a file and add it to the zip
*
- * @param string
- * @param bool
+ * @param string $path
+ * @param bool $archive_filepath
* @return bool
*/
- public function read_file($path, $preserve_filepath = FALSE)
+ public function read_file($path, $archive_filepath = FALSE)
{
- if ( ! file_exists($path))
+ if (file_exists($path) && FALSE !== ($data = file_get_contents($path)))
{
- return FALSE;
- }
-
- if (FALSE !== ($data = file_get_contents($path)))
- {
- $name = str_replace('\\', '/', $path);
- if ($preserve_filepath === FALSE)
+ if (is_string($archive_filepath))
{
- $name = preg_replace('|.*/(.+)|', '\\1', $name);
+ $name = str_replace('\\', '/', $archive_filepath);
+ }
+ else
+ {
+ $name = str_replace('\\', '/', $path);
+
+ if ($preserve_filepath === FALSE)
+ {
+ $name = preg_replace('|.*/(.+)|', '\\1', $name);
+ }
}
$this->add_data($name, $data);
@@ -313,9 +316,9 @@ class CI_Zip {
* sub-folders) and creates a zip based on it. Whatever directory structure
* is in the original file path will be recreated in the zip file.
*
- * @param string path to source
- * @param bool
- * @param bool
+ * @param string $path path to source directory
+ * @param bool $preserve_filepath
+ * @param string $root_path
* @return bool
*/
public function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL)
@@ -389,7 +392,7 @@ class CI_Zip {
*
* Lets you write a file
*
- * @param string the file name
+ * @param string $filepath the file name
* @return bool
*/
public function archive($filepath)
@@ -400,11 +403,19 @@ class CI_Zip {
}
flock($fp, LOCK_EX);
- fwrite($fp, $this->get_zip());
+
+ for ($written = 0, $data = $this->get_zip(), $length = strlen($data); $written < $length; $written += $result)
+ {
+ if (($result = fwrite($fp, substr($data, $written))) === FALSE)
+ {
+ break;
+ }
+ }
+
flock($fp, LOCK_UN);
fclose($fp);
- return TRUE;
+ return is_int($result);
}
// --------------------------------------------------------------------
@@ -412,7 +423,7 @@ class CI_Zip {
/**
* Download
*
- * @param string the file name
+ * @param string $filename the file name
* @return void
*/
public function download($filename = 'backup.zip')
@@ -422,8 +433,7 @@ class CI_Zip {
$filename .= '.zip';
}
- $CI =& get_instance();
- $CI->load->helper('download');
+ get_instance()->load->helper('download');
$get_zip = $this->get_zip();
$zip_content =& $get_zip;