Fixed conflict in url_helper docs.
diff --git a/application/config/config.php b/application/config/config.php
index 1ec6543..880393c 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -176,6 +176,10 @@
| 3 = Informational Messages
| 4 = All Messages
|
+| You can also pass in a array with threshold levels to show individual error types
+|
+| array(2) = Debug Messages, without Error Messages
+|
| For a live site you'll usually only enable Errors (1) to be logged otherwise
| your log files will fill up very fast.
|
@@ -292,11 +296,13 @@
| 'csrf_token_name' = The token name
| 'csrf_cookie_name' = The cookie name
| 'csrf_expire' = The number in seconds the token should expire.
+| 'csrf_exclude_uris' = Array of URIs which ignore CSRF checks
*/
$config['csrf_protection'] = FALSE;
$config['csrf_token_name'] = 'csrf_test_name';
$config['csrf_cookie_name'] = 'csrf_cookie_name';
$config['csrf_expire'] = 7200;
+$config['csrf_exclude_uris'] = array();
/*
|--------------------------------------------------------------------------
diff --git a/application/config/database.php b/application/config/database.php
index fa541a7..b4b34bf 100644
--- a/application/config/database.php
+++ b/application/config/database.php
@@ -27,7 +27,8 @@
| ['char_set'] The character set used in communicating with the database
| ['dbcollat'] The character collation used in communicating with the database
| NOTE: For MySQL and MySQLi databases, this setting is only used
-| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7.
+| as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7
+| (and in table creation queries made with DB Forge).
| There is an incompatibility in PHP with mysql_real_escape_string() which
| can make your site vulnerable to SQL injection if you are using a
| multi-byte character set and are running versions lower than these.
diff --git a/application/config/migration.php b/application/config/migration.php
new file mode 100644
index 0000000..dba8700
--- /dev/null
+++ b/application/config/migration.php
@@ -0,0 +1,42 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/*
+|--------------------------------------------------------------------------
+| Enable/Disable Migrations
+|--------------------------------------------------------------------------
+|
+| Migrations are disabled by default for security reasons.
+| You should enable migrations whenever you intend to do a schema migration
+| and disable it back when you're done.
+|
+*/
+$config['migration_enabled'] = FALSE;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations version
+|--------------------------------------------------------------------------
+|
+| This is used to set migration version that the file system should be on.
+| If you run $this->migration->latest() this is the version that schema will
+| be upgraded / downgraded to.
+|
+*/
+$config['migration_version'] = 0;
+
+
+/*
+|--------------------------------------------------------------------------
+| Migrations Path
+|--------------------------------------------------------------------------
+|
+| Path to your migrations folder.
+| Typically, it will be within your application path.
+| Also, writing permission is required within the migrations path.
+|
+*/
+$config['migration_path'] = APPPATH . 'migrations/';
+
+
+/* End of file migration.php */
+/* Location: ./application/config/migration.php */
\ No newline at end of file
diff --git a/application/config/mimes.php b/application/config/mimes.php
index 82767d7..90a1d18 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -8,10 +8,10 @@
|
*/
-$mimes = array( 'hqx' => 'application/mac-binhex40',
+$mimes = array('hqx' => array('application/mac-binhex40', 'application/mac-binhex', 'application/x-binhex40', 'application/x-mac-binhex40'),
'cpt' => 'application/mac-compactpro',
'csv' => array('text/x-comma-separated-values', 'text/comma-separated-values', 'application/octet-stream', 'application/vnd.ms-excel', 'application/x-csv', 'text/x-csv', 'text/csv', 'application/csv', 'application/excel', 'application/vnd.msexcel'),
- 'bin' => 'application/macbinary',
+ 'bin' => array('application/macbinary', 'application/mac-binary', 'application/octet-stream', 'application/x-binary', 'application/x-macbinary'),
'dms' => 'application/octet-stream',
'lha' => 'application/octet-stream',
'lzh' => 'application/octet-stream',
@@ -39,6 +39,7 @@
'dvi' => 'application/x-dvi',
'gtar' => 'application/x-gtar',
'gz' => 'application/x-gzip',
+ 'gzip' => 'application/x-gzip',
'php' => 'application/x-httpd-php',
'php4' => 'application/x-httpd-php',
'php3' => 'application/x-httpd-php',
@@ -51,14 +52,14 @@
'tgz' => array('application/x-tar', 'application/x-gzip-compressed'),
'xhtml' => 'application/xhtml+xml',
'xht' => 'application/xhtml+xml',
- 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
+ 'zip' => array('application/x-zip', 'application/zip', 'application/x-zip-compressed'),
'mid' => 'audio/midi',
'midi' => 'audio/midi',
'mpga' => 'audio/mpeg',
'mp2' => 'audio/mpeg',
'mp3' => array('audio/mpeg', 'audio/mpg', 'audio/mpeg3', 'audio/mp3'),
- 'aif' => 'audio/x-aiff',
- 'aiff' => 'audio/x-aiff',
+ 'aif' => array('audio/x-aiff', 'audio/aiff'),
+ 'aiff' => array('audio/x-aiff', 'audio/aiff'),
'aifc' => 'audio/x-aiff',
'ram' => 'audio/x-pn-realaudio',
'rm' => 'audio/x-pn-realaudio',
@@ -66,7 +67,7 @@
'ra' => 'audio/x-realaudio',
'rv' => 'video/vnd.rn-realvideo',
'wav' => 'audio/x-wav',
- 'bmp' => 'image/bmp',
+ 'bmp' => array('image/bmp', 'image/x-windows-bmp'),
'gif' => 'image/gif',
'jpeg' => array('image/jpeg', 'image/pjpeg'),
'jpg' => array('image/jpeg', 'image/pjpeg'),
@@ -90,7 +91,7 @@
'mpe' => 'video/mpeg',
'qt' => 'video/quicktime',
'mov' => 'video/quicktime',
- 'avi' => 'video/x-msvideo',
+ 'avi' => array('video/x-msvideo', 'video/msvideo', 'video/avi', 'application/x-troff-msvideo'),
'movie' => 'video/x-sgi-movie',
'doc' => 'application/msword',
'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
@@ -98,7 +99,40 @@
'word' => array('application/msword', 'application/octet-stream'),
'xl' => 'application/excel',
'eml' => 'message/rfc822',
- 'json' => array('application/json', 'text/json')
+ 'json' => array('application/json', 'text/json'),
+ 'pem' => array('application/x-x509-user-cert', 'application/x-pem-file', 'application/octet-stream'),
+ 'p10' => array('application/x-pkcs10', 'application/pkcs10'),
+ 'p12' => 'application/x-pkcs12',
+ 'p7a' => 'application/x-pkcs7-signature',
+ 'p7c' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'),
+ 'p7m' => array('application/pkcs7-mime', 'application/x-pkcs7-mime'),
+ 'p7r' => 'application/x-pkcs7-certreqresp',
+ 'p7s' => 'application/pkcs7-signature',
+ 'crt' => array('application/x-x509-ca-cert', 'application/x-x509-user-cert', 'application/pkix-cert'),
+ 'crl' => array('application/pkix-crl', 'application/pkcs-crl'),
+ 'der' => 'application/x-x509-ca-cert',
+ 'kdb' => 'application/octet-stream',
+ 'pgp' => 'application/pgp',
+ 'gpg' => 'application/gpg-keys',
+ 'sst' => 'application/octet-stream',
+ 'csr' => 'application/octet-stream',
+ 'rsa' => 'application/x-pkcs7',
+ 'cer' => array('application/pkix-cert', 'application/x-x509-ca-cert'),
+ '3g2' => 'video/3gpp2',
+ '3gp' => 'video/3gp',
+ 'mp4' => 'video/mp4',
+ 'm4a' => 'audio/x-m4a',
+ 'f4v' => 'video/mp4',
+ 'aac' => 'audio/x-acc',
+ 'm4u' => 'application/vnd.mpegurl',
+ 'm3u' => 'text/plain',
+ 'xspf' => 'application/xspf+xml',
+ 'vlc' => 'application/videolan',
+ 'wmv' => 'video/x-ms-wmv',
+ 'au' => 'audio/x-au',
+ 'ac3' => 'audio/ac3',
+ 'flac' => 'audio/x-flac',
+ 'ogg' => 'audio/ogg',
);
diff --git a/index.php b/index.php
index f4ac11a..c50cfed 100644
--- a/index.php
+++ b/index.php
@@ -33,7 +33,7 @@
switch (ENVIRONMENT)
{
case 'development':
- error_reporting(E_ALL);
+ error_reporting(-1);
break;
case 'testing':
@@ -73,6 +73,23 @@
*
*/
$application_folder = 'application';
+
+/*
+ *---------------------------------------------------------------
+ * VIEW FOLDER NAME
+ *---------------------------------------------------------------
+ *
+ * If you want to move the view folder out of the application
+ * folder set the path to the folder here. The folder can be renamed
+ * and relocated anywhere on your server. If blank, it will default
+ * to the standard location inside your application folder. If you
+ * do move this, use the full server path to this folder
+ *
+ * NO TRAILING SLASH!
+ *
+ */
+ $view_folder = '';
+
/*
* --------------------------------------------------------------------
@@ -190,6 +207,22 @@
define('APPPATH', BASEPATH.$application_folder.'/');
}
+
+ // The path to the "views" folder
+ if (is_dir($view_folder))
+ {
+ define ('VIEWPATH', $view_folder .'/');
+ }
+ else
+ {
+ if ( ! is_dir(APPPATH.'views/'))
+ {
+ exit("Your view folder path does not appear to be set correctly. Please open the following file and correct this: ".SELF);
+ }
+
+ define ('VIEWPATH', APPPATH.'views/' );
+ }
+
/*
* --------------------------------------------------------------------
diff --git a/readme.md b/readme.md
new file mode 100644
index 0000000..be807db
--- /dev/null
+++ b/readme.md
@@ -0,0 +1,11 @@
+# What is CodeIgniter
+
+CodeIgniter is an Application Development Framework - a toolkit - for people who build web sites using PHP. Its goal is to enable you to develop projects much faster than you could if you were writing code from scratch, by providing a rich set of libraries for commonly needed tasks, as well as a simple interface and logical structure to access these libraries. CodeIgniter lets you creatively focus on your project by minimizing the amount of code needed for a given task.
+
+# Resources
+
+ * [User Guide](http://codeigniter.com/user_guide/)
+ * [Community Forums](http://codeigniter.com/forums/)
+ * [User Voice](http://codeigniter.uservoice.com/forums/40508-codeigniter-reactor)
+ * [Community Wiki](http://codeigniter.com/wiki/)
+ * [Community IRC](http://webchat.freenode.net/?channels=codeigniter&uio=d4)
\ No newline at end of file
diff --git a/system/core/Benchmark.php b/system/core/Benchmark.php
old mode 100644
new mode 100755
index 515550e..a200727
--- a/system/core/Benchmark.php
+++ b/system/core/Benchmark.php
@@ -29,6 +29,11 @@
*/
class CI_Benchmark {
+ /**
+ * List of all benchmark markers and when they were added
+ *
+ * @var array
+ */
var $marker = array();
// --------------------------------------------------------------------
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
old mode 100644
new mode 100755
index 94fecb5..0a1391d
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -27,18 +27,32 @@
* @link http://codeigniter.com/user_guide/
*/
-/*
- * ------------------------------------------------------
- * Define the CodeIgniter Version
- * ------------------------------------------------------
+/**
+ * CodeIgniter Version
+ *
+ * @var string
+ *
*/
- define('CI_VERSION', '2.0.3');
+ /**
+ * CodeIgniter Version
+ *
+ * @var string
+ *
+ */
+ define('CI_VERSION', '2.0.2');
-/*
- * ------------------------------------------------------
- * Define the CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
- * ------------------------------------------------------
+/**
+ * CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
+ *
+ * @var boolean
+ *
*/
+ /**
+ * CodeIgniter Branch (Core = TRUE, Reactor = FALSE)
+ *
+ * @var string
+ *
+ */
define('CI_CORE', FALSE);
/*
@@ -267,7 +281,25 @@
OR in_array(strtolower($method), array_map('strtolower', get_class_methods('CI_Controller')))
)
{
- show_404("{$class}/{$method}");
+ if ( ! empty($RTR->routes['404_override']))
+ {
+ $x = explode('/', $RTR->routes['404_override']);
+ $class = $x[0];
+ $method = (isset($x[1]) ? $x[1] : 'index');
+ if ( ! class_exists($class))
+ {
+ if ( ! file_exists(APPPATH.'controllers/'.$class.'.php'))
+ {
+ show_404("{$class}/{$method}");
+ }
+
+ include_once(APPPATH.'controllers/'.$class.'.php');
+ }
+ }
+ else
+ {
+ show_404("{$class}/{$method}");
+ }
}
/*
diff --git a/system/core/Common.php b/system/core/Common.php
index db9fbeb..d793754 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -132,9 +132,9 @@
$name = FALSE;
- // Look for the class first in the native system/libraries folder
- // thenin the local application/libraries folder
- foreach (array(BASEPATH, APPPATH) as $path)
+ // Look for the class first in the local application/libraries folder
+ // then in the native system/libraries folder
+ foreach (array(APPPATH, BASEPATH) as $path)
{
if (file_exists($path.$directory.'/'.$class.'.php'))
{
@@ -536,5 +536,29 @@
}
}
+// ------------------------------------------------------------------------
+
+/**
+* Returns HTML escaped variable
+*
+* @access public
+* @param mixed
+* @return mixed
+*/
+if ( ! function_exists('html_escape'))
+{
+ function html_escape($var)
+ {
+ if (is_array($var))
+ {
+ return array_map('html_escape', $var);
+ }
+ else
+ {
+ return htmlspecialchars($var, ENT_QUOTES, config_item('charset'));
+ }
+ }
+}
+
/* End of file Common.php */
/* Location: ./system/core/Common.php */
\ No newline at end of file
diff --git a/system/core/Config.php b/system/core/Config.php
old mode 100644
new mode 100755
index 0e6f10e..714c466
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -28,8 +28,23 @@
*/
class CI_Config {
+ /**
+ * List of all loaded config values
+ *
+ * @var array
+ */
var $config = array();
+ /**
+ * List of all loaded config files
+ *
+ * @var array
+ */
var $is_loaded = array();
+ /**
+ * List of paths to search when trying to load a config file
+ *
+ * @var array
+ */
var $_config_paths = array(APPPATH);
/**
@@ -251,13 +266,13 @@
return $this->slash_item('base_url').$this->item('index_page').'?'.$this->_uri_string($uri);
}
}
-
+
// -------------------------------------------------------------
-
+
/**
* Base URL
* Returns base_url [. uri_string]
- *
+ *
* @access public
* @param string $uri
* @return string
@@ -266,12 +281,12 @@
{
return $this->slash_item('base_url').ltrim($this->_uri_string($uri),'/');
}
-
+
// -------------------------------------------------------------
-
+
/**
* Build URI string for use in Config::site_url() and Config::base_url()
- *
+ *
* @access protected
* @param $uri
* @return string
@@ -305,7 +320,7 @@
}
// --------------------------------------------------------------------
-
+
/**
* System URL
*
diff --git a/system/core/Controller.php b/system/core/Controller.php
index ec86b79..fddb81e 100644
--- a/system/core/Controller.php
+++ b/system/core/Controller.php
@@ -48,7 +48,7 @@
$this->load =& load_class('Loader', 'core');
- $this->load->set_base_classes()->ci_autoloader();
+ $this->load->initialize();
log_message('debug', "Controller Class Initialized");
}
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
old mode 100644
new mode 100755
index bff86a9..869739a
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -30,8 +30,21 @@
var $message;
var $filename;
var $line;
+
+ /**
+ * Nesting level of the output buffering mechanism
+ *
+ * @var int
+ * @access public
+ */
var $ob_level;
+ /**
+ * List if available error levels
+ *
+ * @var array
+ * @access public
+ */
var $levels = array(
E_ERROR => 'Error',
E_WARNING => 'Warning',
@@ -84,7 +97,8 @@
* 404 Page Not Found Handler
*
* @access private
- * @param string
+ * @param string the page
+ * @param bool log error yes/no
* @return string
*/
function show_404($page = '', $log_error = TRUE)
@@ -115,6 +129,7 @@
* @param string the heading
* @param string the message
* @param string the template name
+ * @param int the status code
* @return string
*/
function show_error($heading, $message, $template = 'error_general', $status_code = 500)
diff --git a/system/core/Hooks.php b/system/core/Hooks.php
old mode 100644
new mode 100755
index fd6380f..33f1c03
--- a/system/core/Hooks.php
+++ b/system/core/Hooks.php
@@ -28,8 +28,23 @@
*/
class CI_Hooks {
+ /**
+ * Determines wether hooks are enabled
+ *
+ * @var bool
+ */
var $enabled = FALSE;
+ /**
+ * List of all hooks set in config/hooks.php
+ *
+ * @var array
+ */
var $hooks = array();
+ /**
+ * Determines wether hook is in progress, used to prevent infinte loops
+ *
+ * @var bool
+ */
var $in_progress = FALSE;
/**
diff --git a/system/core/Input.php b/system/core/Input.php
old mode 100644
new mode 100755
index cfbef94..0dc2c45
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -28,15 +28,51 @@
*/
class CI_Input {
+ /**
+ * IP address of the current user
+ *
+ * @var string
+ */
var $ip_address = FALSE;
+ /**
+ * user agent (web browser) being used by the current user
+ *
+ * @var string
+ */
var $user_agent = FALSE;
+ /**
+ * If FALSE, then $_GET will be set to an empty array
+ *
+ * @var bool
+ */
var $_allow_get_array = TRUE;
+ /**
+ * If TRUE, then newlines are standardized
+ *
+ * @var bool
+ */
var $_standardize_newlines = TRUE;
- var $_enable_xss = FALSE; // Set automatically based on config setting
- var $_enable_csrf = FALSE; // Set automatically based on config setting
-
+ /**
+ * Determines whether the XSS filter is always active when GET, POST or COOKIE data is encountered
+ * Set automatically based on config setting
+ *
+ * @var bool
+ */
+ var $_enable_xss = FALSE;
+ /**
+ * Enables a CSRF cookie token to be set.
+ * Set automatically based on config setting
+ *
+ * @var bool
+ */
+ var $_enable_csrf = FALSE;
+ /**
+ * List of all HTTP request headers
+ *
+ * @var array
+ */
protected $headers = array();
-
+
/**
* Constructor
@@ -147,7 +183,7 @@
}
return $post;
}
-
+
return $this->_fetch_from_array($_POST, $index, $xss_clean);
}
@@ -287,14 +323,14 @@
$this->ip_address = in_array($_SERVER['REMOTE_ADDR'], $proxies) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
}
+ elseif (! $this->server('HTTP_CLIENT_IP') AND $this->server('REMOTE_ADDR'))
+ {
+ $this->ip_address = $_SERVER['REMOTE_ADDR'];
+ }
elseif ($this->server('REMOTE_ADDR') AND $this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
}
- elseif ($this->server('REMOTE_ADDR'))
- {
- $this->ip_address = $_SERVER['REMOTE_ADDR'];
- }
elseif ($this->server('HTTP_CLIENT_IP'))
{
$this->ip_address = $_SERVER['HTTP_CLIENT_IP'];
@@ -402,9 +438,9 @@
function _sanitize_globals()
{
// It would be "wrong" to unset any of these GLOBALS.
- $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST',
+ $protected = array('_SERVER', '_GET', '_POST', '_FILES', '_REQUEST',
'_SESSION', '_ENV', 'GLOBALS', 'HTTP_RAW_POST_DATA',
- 'system_folder', 'application_folder', 'BM', 'EXT',
+ 'system_folder', 'application_folder', 'BM', 'EXT',
'CFG', 'URI', 'RTR', 'OUT', 'IN');
// Unset globals for securiy.
@@ -523,7 +559,7 @@
{
$str = $this->uni->clean_string($str);
}
-
+
// Remove control characters
$str = remove_invisible_characters($str);
@@ -579,9 +615,11 @@
/**
* Request Headers
*
- * In Apache, you can simply call apache_request_headers(), however for
+ * In Apache, you can simply call apache_request_headers(), however for
* people running other webservers the function is undefined.
*
+ * @param bool XSS cleaning
+ *
* @return array
*/
public function request_headers($xss_clean = FALSE)
@@ -609,10 +647,10 @@
{
$key = str_replace('_', ' ', strtolower($key));
$key = str_replace(' ', '-', ucwords($key));
-
+
$this->headers[$key] = $val;
}
-
+
return $this->headers;
}
@@ -633,7 +671,7 @@
{
$this->request_headers();
}
-
+
if ( ! isset($this->headers[$index]))
{
return FALSE;
@@ -644,7 +682,7 @@
return $this->security->xss_clean($this->headers[$index]);
}
- return $this->headers[$index];
+ return $this->headers[$index];
}
// --------------------------------------------------------------------
diff --git a/system/core/Lang.php b/system/core/Lang.php
old mode 100644
new mode 100755
index 170e6c7..d61d102
--- a/system/core/Lang.php
+++ b/system/core/Lang.php
@@ -26,7 +26,17 @@
*/
class CI_Lang {
+ /**
+ * List of translations
+ *
+ * @var array
+ */
var $language = array();
+ /**
+ * List of loaded language files
+ *
+ * @var array
+ */
var $is_loaded = array();
/**
@@ -47,6 +57,9 @@
* @access public
* @param mixed the name of the language file to be loaded. Can be an array
* @param string the language (english, etc.)
+ * @param bool return loaded array of translations
+ * @param bool add suffix to $langfile
+ * @param string alternative path to look for language file
* @return mixed
*/
function load($langfile = '', $idiom = '', $return = FALSE, $add_suffix = TRUE, $alt_path = '')
@@ -99,7 +112,7 @@
}
- if ( ! isset($lang))
+ if ( ! isset($lang) OR ! is_array($lang))
{
log_message('error', 'Language file contains no data: language/'.$idiom.'/'.$langfile);
return;
@@ -111,7 +124,7 @@
}
$this->is_loaded[] = $langfile;
- $this->language = array_merge($this->language, $lang);
+ $this->language = $this->language + $lang;
unset($lang);
log_message('debug', 'Language file loaded: language/'.$idiom.'/'.$langfile);
diff --git a/system/core/Loader.php b/system/core/Loader.php
old mode 100644
new mode 100755
index 7c8b298..de0fc06
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -29,18 +29,91 @@
class CI_Loader {
// All these are set automatically. Don't mess with them.
+ /**
+ * Nesting level of the output buffering mechanism
+ *
+ * @var int
+ * @access protected
+ */
protected $_ci_ob_level;
+ /**
+ * List of paths to load views from
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_view_paths = array();
+ /**
+ * List of paths to load libraries from
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_library_paths = array();
+ /**
+ * List of paths to load models from
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_model_paths = array();
+ /**
+ * List of paths to load helpers from
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_helper_paths = array();
+ /**
+ * List of loaded base classes
+ * Set by the controller class
+ *
+ * @var array
+ * @access protected
+ */
protected $_base_classes = array(); // Set by the controller class
+ /**
+ * List of cached variables
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_cached_vars = array();
+ /**
+ * List of loaded classes
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_classes = array();
+ /**
+ * List of loaded files
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_loaded_files = array();
+ /**
+ * List of loaded models
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_models = array();
+ /**
+ * List of loaded helpers
+ *
+ * @var array
+ * @access protected
+ */
protected $_ci_helpers = array();
- protected $_ci_varmap = array('unit_test' => 'unit',
+ /**
+ * List of class name mappings
+ *
+ * @var array
+ * @access protected
+ */
+ protected $_ci_varmap = array('unit_test' => 'unit',
'user_agent' => 'agent');
/**
@@ -54,25 +127,30 @@
$this->_ci_library_paths = array(APPPATH, BASEPATH);
$this->_ci_helper_paths = array(APPPATH, BASEPATH);
$this->_ci_model_paths = array(APPPATH);
- $this->_ci_view_paths = array(APPPATH.'views/' => TRUE);
-
+ $this->_ci_view_paths = array(VIEWPATH => TRUE);
+
log_message('debug', "Loader Class Initialized");
}
// --------------------------------------------------------------------
-
+
/**
- * Set _base_classes variable
+ * Initialize the Loader
*
* This method is called once in CI_Controller.
*
- * @param array
+ * @param array
* @return object
*/
- public function set_base_classes()
+ public function initialize()
{
+ $this->_ci_classes = array();
+ $this->_ci_loaded_files = array();
+ $this->_ci_models = array();
$this->_base_classes =& is_loaded();
-
+
+ $this->_ci_autoloader();
+
return $this;
}
@@ -96,7 +174,7 @@
{
return $this->_ci_classes[$class];
}
-
+
return FALSE;
}
@@ -366,6 +444,7 @@
* the controller class and its "view" files.
*
* @param array
+ * @param string
* @return void
*/
public function vars($vars = array(), $val = '')
@@ -507,6 +586,8 @@
* Loads a config file
*
* @param string
+ * @param bool
+ * @param bool
* @return void
*/
public function config($file = '', $use_sections = FALSE, $fail_gracefully = FALSE)
@@ -553,13 +634,13 @@
* Prepends a parent path to the library, model, helper, and config path arrays
*
* @param string
- * @param boolean
+ * @param boolean
* @return void
*/
public function add_package_path($path, $view_cascade=TRUE)
{
$path = rtrim($path, '/').'/';
-
+
array_unshift($this->_ci_library_paths, $path);
array_unshift($this->_ci_model_paths, $path);
array_unshift($this->_ci_helper_paths, $path);
@@ -595,6 +676,7 @@
* If no path is provided, the most recently added path is removed.
*
* @param type
+ * @param bool
* @return type
*/
public function remove_package_path($path = '', $remove_config_path = TRUE)
@@ -619,7 +701,7 @@
unset($this->{$var}[$key]);
}
}
-
+
if (isset($this->_ci_view_paths[$path.'views/']))
{
unset($this->_ci_view_paths[$path.'views/']);
@@ -658,7 +740,7 @@
{
$$_ci_val = ( ! isset($_ci_data[$_ci_val])) ? FALSE : $_ci_data[$_ci_val];
}
-
+
$file_exists = FALSE;
// Set the path to the requested file
@@ -680,11 +762,11 @@
$file_exists = TRUE;
break;
}
-
+
if ( ! $cascade)
{
break;
- }
+ }
}
}
@@ -913,6 +995,7 @@
*
* @param string
* @param string
+ * @param bool
* @param string an optional object name
* @return null
*/
@@ -935,22 +1018,22 @@
// first, global next
if (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php'))
{
- include_once($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
+ include($path .'config/'.ENVIRONMENT.'/'.strtolower($class).'.php');
break;
}
elseif (defined('ENVIRONMENT') AND file_exists($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php'))
{
- include_once($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
+ include($path .'config/'.ENVIRONMENT.'/'.ucfirst(strtolower($class)).'.php');
break;
}
elseif (file_exists($path .'config/'.strtolower($class).'.php'))
{
- include_once($path .'config/'.strtolower($class).'.php');
+ include($path .'config/'.strtolower($class).'.php');
break;
}
elseif (file_exists($path .'config/'.ucfirst(strtolower($class)).'.php'))
{
- include_once($path .'config/'.ucfirst(strtolower($class)).'.php');
+ include($path .'config/'.ucfirst(strtolower($class)).'.php');
break;
}
}
@@ -1020,23 +1103,19 @@
* The config/autoload.php file contains an array that permits sub-systems,
* libraries, and helpers to be loaded automatically.
*
- * This function is public, as it's used in the CI_Controller class.
- * However, there is no reason you should ever needs to use it.
- *
* @param array
* @return void
*/
- public function ci_autoloader()
+ protected function _ci_autoloader()
{
if (defined('ENVIRONMENT') AND file_exists(APPPATH.'config/'.ENVIRONMENT.'/autoload.php'))
{
- include_once(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
+ include(APPPATH.'config/'.ENVIRONMENT.'/autoload.php');
}
else
{
- include_once(APPPATH.'config/autoload.php');
+ include(APPPATH.'config/autoload.php');
}
-
if ( ! isset($autoload))
{
@@ -1122,6 +1201,7 @@
/**
* Get a reference to a specific library or model
*
+ * @param string
* @return bool
*/
protected function &_ci_get_component($component)
@@ -1138,6 +1218,7 @@
* This function preps the name of various items to make loading them more reliable.
*
* @param mixed
+ * @param string
* @return array
*/
protected function _ci_prep_filename($filename, $extension)
diff --git a/system/core/Model.php b/system/core/Model.php
old mode 100644
new mode 100755
index 8566a0b..e15ffbe
--- a/system/core/Model.php
+++ b/system/core/Model.php
@@ -42,6 +42,7 @@
* Allows models to access CI's loaded classes using the same
* syntax as controllers.
*
+ * @param string
* @access private
*/
function __get($key)
diff --git a/system/core/Output.php b/system/core/Output.php
old mode 100644
new mode 100755
index 05ace91..ccecafd
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -28,15 +28,67 @@
*/
class CI_Output {
+ /**
+ * Current output string
+ *
+ * @var string
+ * @access protected
+ */
protected $final_output;
+ /**
+ * Cache expiration time
+ *
+ * @var int
+ * @access protected
+ */
protected $cache_expiration = 0;
+ /**
+ * List of server headers
+ *
+ * @var array
+ * @access protected
+ */
protected $headers = array();
- protected $mime_types = array();
+ /**
+ * List of mime types
+ *
+ * @var array
+ * @access protected
+ */
+ protected $mime_types = array();
+ /**
+ * Determines wether profiler is enabled
+ *
+ * @var book
+ * @access protected
+ */
protected $enable_profiler = FALSE;
+ /**
+ * Determines if output compression is enabled
+ *
+ * @var bool
+ * @access protected
+ */
protected $_zlib_oc = FALSE;
+ /**
+ * List of profiler sections
+ *
+ * @var array
+ * @access protected
+ */
protected $_profiler_sections = array();
- protected $parse_exec_vars = TRUE; // whether or not to parse variables like {elapsed_time} and {memory_usage}
+ /**
+ * Whether or not to parse variables like {elapsed_time} and {memory_usage}
+ *
+ * @var bool
+ * @access protected
+ */
+ protected $parse_exec_vars = TRUE;
+ /**
+ * Constructor
+ *
+ */
function __construct()
{
$this->_zlib_oc = @ini_get('zlib.output_compression');
@@ -127,6 +179,7 @@
*
* @access public
* @param string
+ * @param bool
* @return void
*/
function set_header($header, $replace = TRUE)
@@ -265,6 +318,7 @@
* benchmark timer so the page rendering speed and memory usage can be shown.
*
* @access public
+ * @param string
* @return mixed
*/
function _display($output = '')
@@ -401,6 +455,7 @@
* Write a Cache File
*
* @access public
+ * @param string
* @return void
*/
function _write_cache($output)
@@ -452,6 +507,8 @@
* Update/serve a cached file
*
* @access public
+ * @param object config class
+ * @param object uri class
* @return void
*/
function _display_cache(&$CFG, &$URI)
diff --git a/system/core/Router.php b/system/core/Router.php
old mode 100644
new mode 100755
index 5e92a04..6da6674
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -28,12 +28,54 @@
*/
class CI_Router {
+ /**
+ * Config class
+ *
+ * @var object
+ * @access public
+ */
var $config;
+ /**
+ * List of routes
+ *
+ * @var array
+ * @access public
+ */
var $routes = array();
+ /**
+ * List of error routes
+ *
+ * @var array
+ * @access public
+ */
var $error_routes = array();
+ /**
+ * Current class name
+ *
+ * @var string
+ * @access public
+ */
var $class = '';
+ /**
+ * Current method name
+ *
+ * @var string
+ * @access public
+ */
var $method = 'index';
+ /**
+ * Sub-directory that contains the requested controller class
+ *
+ * @var string
+ * @access public
+ */
var $directory = '';
+ /**
+ * Default controller (and method if specific)
+ *
+ * @var string
+ * @access public
+ */
var $default_controller;
/**
@@ -95,7 +137,7 @@
{
include(APPPATH.'config/routes.php');
}
-
+
$this->routes = ( ! isset($route) OR ! is_array($route)) ? array() : $route;
unset($route);
@@ -244,7 +286,20 @@
// Does the requested controller exist in the sub-folder?
if ( ! file_exists(APPPATH.'controllers/'.$this->fetch_directory().$segments[0].'.php'))
{
- show_404($this->fetch_directory().$segments[0]);
+ if ( ! empty($this->routes['404_override']))
+ {
+ $x = explode('/', $this->routes['404_override']);
+
+ $this->set_directory('');
+ $this->set_class($x[0]);
+ $this->set_method(isset($x[1]) ? $x[1] : 'index');
+
+ return $x;
+ }
+ else
+ {
+ show_404($this->fetch_directory().$segments[0]);
+ }
}
}
else
diff --git a/system/core/Security.php b/system/core/Security.php
old mode 100644
new mode 100755
index 3617cad..342455f
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -25,14 +25,55 @@
* @link http://codeigniter.com/user_guide/libraries/security.html
*/
class CI_Security {
-
- protected $_xss_hash = '';
- protected $_csrf_hash = '';
- protected $_csrf_expire = 7200; // Two hours (in seconds)
- protected $_csrf_token_name = 'ci_csrf_token';
- protected $_csrf_cookie_name = 'ci_csrf_token';
- /* never allowed, string replacement */
+ /**
+ * Random Hash for protecting URLs
+ *
+ * @var string
+ * @access protected
+ */
+ protected $_xss_hash = '';
+
+ /**
+ * Random Hash for Cross Site Request Forgery Protection Cookie
+ *
+ * @var string
+ * @access protected
+ */
+ protected $_csrf_hash = '';
+
+ /**
+ * Expiration time for Cross Site Request Forgery Protection Cookie
+ * Defaults to two hours (in seconds)
+ *
+ * @var int
+ * @access protected
+ */
+ protected $_csrf_expire = 7200;
+
+ /**
+ * Token name for Cross Site Request Forgery Protection Cookie
+ *
+ * @var string
+ * @access protected
+ */
+ protected $_csrf_token_name = 'ci_csrf_token';
+
+ /**
+ * Cookie name for Cross Site Request Forgery Protection Cookie
+ *
+ * @var string
+ * @access protected
+ */
+ protected $_csrf_cookie_name = 'ci_csrf_token';
+
+ /**
+ * List of never allowed strings
+ *
+ * @var array
+ * @access protected
+ */
+
protected $_never_allowed_str = array(
'document.cookie' => '[removed]',
'document.write' => '[removed]',
@@ -45,14 +86,19 @@
'<![CDATA[' => '<![CDATA['
);
- /* never allowed, regex replacement */
+ /**
+ * List of never allowed regex replacement
+ *
+ * @var array
+ * @access protected
+ */
protected $_never_allowed_regex = array(
"javascript\s*:" => '[removed]',
"expression\s*(\(|&\#40;)" => '[removed]', // CSS and IE
"vbscript\s*:" => '[removed]', // IE, surprise!
"Redirect\s+302" => '[removed]'
);
-
+
/**
* Constructor
*/
@@ -93,9 +139,19 @@
{
return $this->csrf_set_cookie();
}
+
+ // Check if URI has been whitelisted from CSRF checks
+ if ($exclude_uris = config_item('csrf_exclude_uris'))
+ {
+ $uri = load_class('URI', 'core');
+ if (in_array($uri->uri_string(), $exclude_uris))
+ {
+ return $this;
+ }
+ }
// Do the tokens exist in both the _POST and _COOKIE arrays?
- if ( ! isset($_POST[$this->_csrf_token_name]) OR
+ if ( ! isset($_POST[$this->_csrf_token_name]) OR
! isset($_COOKIE[$this->_csrf_cookie_name]))
{
$this->csrf_show_error();
@@ -107,7 +163,7 @@
$this->csrf_show_error();
}
- // We kill this since we're done and we don't want to
+ // We kill this since we're done and we don't want to
// polute the _POST array
unset($_POST[$this->_csrf_token_name]);
@@ -115,8 +171,8 @@
unset($_COOKIE[$this->_csrf_cookie_name]);
$this->_csrf_set_hash();
$this->csrf_set_cookie();
-
- log_message('debug', "CSRF token verified ");
+
+ log_message('debug', "CSRF token verified");
return $this;
}
@@ -146,7 +202,7 @@
setcookie($this->_csrf_cookie_name, $this->_csrf_hash, $expire, config_item('cookie_path'), config_item('cookie_domain'), $secure_cookie);
log_message('debug', "CRSF cookie Set");
-
+
return $this;
}
@@ -165,9 +221,9 @@
// --------------------------------------------------------------------
/**
- * Get CSRF Hash
+ * Get CSRF Hash
*
- * Getter Method
+ * Getter Method
*
* @return string self::_csrf_hash
*/
@@ -215,6 +271,7 @@
* http://ha.ckers.org/xss.html
*
* @param mixed string or array
+ * @param bool
* @return string
*/
public function xss_clean($str, $is_image = FALSE)
@@ -263,7 +320,7 @@
*/
$str = preg_replace_callback("/[a-z]+=([\'\"]).*?\\1/si", array($this, '_convert_attribute'), $str);
-
+
$str = preg_replace_callback("/<\w+.*?(?=>|<|$)/si", array($this, '_decode_entity'), $str);
/*
@@ -276,7 +333,7 @@
*
* This prevents strings like this: ja vascript
* NOTE: we deal with spaces between characters later.
- * NOTE: preg_replace was found to be amazingly slow here on
+ * NOTE: preg_replace was found to be amazingly slow here on
* large blocks of data, so we use str_replace.
*/
@@ -304,8 +361,8 @@
*/
if ($is_image === TRUE)
{
- // Images have a tendency to have the PHP short opening and
- // closing tags every so often so we skip those and only
+ // Images have a tendency to have the PHP short opening and
+ // closing tags every so often so we skip those and only
// do the long opening tags.
$str = preg_replace('/<\?(php)/i', "<?\\1", $str);
}
@@ -321,10 +378,10 @@
* These words are compacted back to their correct state.
*/
$words = array(
- 'javascript', 'expression', 'vbscript', 'script',
+ 'javascript', 'expression', 'vbscript', 'script',
'applet', 'alert', 'document', 'write', 'cookie', 'window'
);
-
+
foreach ($words as $word)
{
$temp = '';
@@ -341,8 +398,8 @@
/*
* Remove disallowed Javascript in links or img tags
- * We used to do some version comparisons and use of stripos for PHP5,
- * but it is dog slow compared to these simplified non-capturing
+ * We used to do some version comparisons and use of stripos for PHP5,
+ * but it is dog slow compared to these simplified non-capturing
* preg_match(), especially if the pattern exists in the string
*/
do
@@ -405,11 +462,11 @@
/*
* Images are Handled in a Special Way
- * - Essentially, we want to know that after all of the character
- * conversion is done whether any unwanted, likely XSS, code was found.
+ * - Essentially, we want to know that after all of the character
+ * conversion is done whether any unwanted, likely XSS, code was found.
* If not, we return TRUE, as the image is clean.
- * However, if the string post-conversion does not matched the
- * string post-removal of XSS, then it fails, as there was unwanted XSS
+ * However, if the string post-conversion does not matched the
+ * string post-removal of XSS, then it fails, as there was unwanted XSS
* code found and removed/changed during processing.
*/
@@ -478,7 +535,7 @@
// correctly. html_entity_decode() does not convert entities without
// semicolons, so we are left with our own little solution here. Bummer.
- if (function_exists('html_entity_decode') &&
+ if (function_exists('html_entity_decode') &&
(strtolower($charset) != 'utf-8'))
{
$str = html_entity_decode($str, ENT_COMPAT, $charset);
@@ -505,6 +562,7 @@
* Filename Security
*
* @param string
+ * @param bool
* @return string
*/
public function sanitize_filename($str, $relative_path = FALSE)
@@ -542,7 +600,7 @@
"%3b", // ;
"%3d" // =
);
-
+
if ( ! $relative_path)
{
$bad[] = './';
@@ -570,7 +628,7 @@
}
// --------------------------------------------------------------------
-
+
/*
* Remove Evil HTML Attributes (like evenhandlers and style)
*
@@ -578,7 +636,7 @@
* - Everything up until a space
* For example, everything between the pipes:
* <a |style=document.write('hello');alert('world');| class=link>
- * - Everything inside the quotes
+ * - Everything inside the quotes
* For example, everything between the pipes:
* <a |style="document.write('hello'); alert('world');"| class="link">
*
@@ -594,12 +652,12 @@
if ($is_image === TRUE)
{
/*
- * Adobe Photoshop puts XML metadata into JFIF images,
+ * Adobe Photoshop puts XML metadata into JFIF images,
* including namespacing, so we have to allow this for images.
*/
unset($evil_attributes[array_search('xmlns', $evil_attributes)]);
}
-
+
do {
$str = preg_replace(
"#<(/?[^><]+?)([^A-Za-z\-])(".implode('|', $evil_attributes).")(\s*=\s*)([\"][^>]*?[\"]|[\'][^>]*?[\']|[^>]*?)([\s><])([><]*)#i",
@@ -607,10 +665,10 @@
$str, -1, $count
);
} while ($count);
-
+
return $str;
}
-
+
// --------------------------------------------------------------------
/**
@@ -627,7 +685,7 @@
$str = '<'.$matches[1].$matches[2].$matches[3];
// encode captured opening or closing brace to prevent recursive vectors
- $str .= str_replace(array('>', '<'), array('>', '<'),
+ $str .= str_replace(array('>', '<'), array('>', '<'),
$matches[4]);
return $str;
@@ -649,7 +707,7 @@
protected function _js_link_removal($match)
{
$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-
+
return str_replace($match[1], preg_replace("#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
}
@@ -669,7 +727,7 @@
protected function _js_img_removal($match)
{
$attributes = $this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]));
-
+
return str_replace($match[1], preg_replace("#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si", "", $attributes), $match[0]);
}
@@ -729,13 +787,13 @@
}
// --------------------------------------------------------------------
-
+
/**
* Validate URL entities
*
* Called by xss_clean()
*
- * @param string
+ * @param string
* @return string
*/
protected function _validate_entities($str)
@@ -743,9 +801,9 @@
/*
* Protect GET variables in URLs
*/
-
+
// 901119URL5918AMP18930PROTECT8198
-
+
$str = preg_replace('|\&([a-z\_0-9\-]+)\=([a-z\_0-9\-]+)|i', $this->xss_hash()."\\1=\\2", $str);
/*
@@ -769,7 +827,7 @@
* Un-Protect GET variables in URLs
*/
$str = str_replace($this->xss_hash(), '&', $str);
-
+
return $str;
}
@@ -794,7 +852,7 @@
{
$str = preg_replace("#".$key."#i", $val, $str);
}
-
+
return $str;
}
@@ -809,16 +867,16 @@
{
if ($this->_csrf_hash == '')
{
- // If the cookie exists we will use it's value.
+ // If the cookie exists we will use it's value.
// We don't necessarily want to regenerate it with
- // each page load since a page could contain embedded
+ // each page load since a page could contain embedded
// sub-pages causing this feature to fail
- if (isset($_COOKIE[$this->_csrf_cookie_name]) &&
+ if (isset($_COOKIE[$this->_csrf_cookie_name]) &&
$_COOKIE[$this->_csrf_cookie_name] != '')
{
return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
}
-
+
return $this->_csrf_hash = md5(uniqid(rand(), TRUE));
}
@@ -826,7 +884,6 @@
}
}
-// END Security Class
/* End of file Security.php */
-/* Location: ./system/libraries/Security.php */
+/* Location: ./system/libraries/Security.php */
\ No newline at end of file
diff --git a/system/core/URI.php b/system/core/URI.php
old mode 100644
new mode 100755
index 20f0f00..8946bc7
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -28,9 +28,34 @@
*/
class CI_URI {
+ /**
+ * List of cached uri segments
+ *
+ * @var array
+ * @access public
+ */
var $keyval = array();
+ /**
+ * Current uri string
+ *
+ * @var string
+ * @access public
+ */
var $uri_string;
+ /**
+ * List of uri segments
+ *
+ * @var array
+ * @access public
+ */
var $segments = array();
+ /**
+ * Re-indexed list of uri segments
+ * Starts at 1 instead of 0
+ *
+ * @var array
+ * @access public
+ */
var $rsegments = array();
/**
@@ -127,6 +152,7 @@
* Set the URI String
*
* @access public
+ * @param string
* @return string
*/
function _set_uri_string($str)
@@ -149,7 +175,7 @@
* @access private
* @return string
*/
- private function _detect_uri()
+ protected function _detect_uri()
{
if ( ! isset($_SERVER['REQUEST_URI']) OR ! isset($_SERVER['SCRIPT_NAME']))
{
@@ -206,7 +232,7 @@
* @access private
* @return string
*/
- private function _parse_cli_args()
+ protected function _parse_cli_args()
{
$args = array_slice($_SERVER['argv'], 1);
@@ -366,6 +392,11 @@
/**
* Identical to above only it uses the re-routed segment array
*
+ * @access public
+ * @param integer the starting segment number
+ * @param array an array of default values
+ * @return array
+ *
*/
function ruri_to_assoc($n = 3, $default = array())
{
diff --git a/system/database/DB.php b/system/database/DB.php
old mode 100644
new mode 100755
index 33207d8..8314d3b
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -21,6 +21,8 @@
* @category Database
* @author ExpressionEngine Dev Team
* @link http://codeigniter.com/user_guide/database/
+ * @param string
+ * @param bool Determines if active record should be used or not
*/
function &DB($params = '', $active_record_override = NULL)
{
@@ -35,7 +37,7 @@
show_error('The configuration file database.php does not exist.');
}
}
-
+
include($file_path);
if ( ! isset($db) OR count($db) == 0)
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index 2af3553..37d162b 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -196,7 +196,7 @@
$alias = $this->_create_alias_from_table(trim($select));
}
- $sql = $type.'('.$this->_protect_identifiers(trim($select)).') AS '.$alias;
+ $sql = $type.'('.$this->_protect_identifiers(trim($select)).') AS '.$this->_protect_identifiers(trim($alias));
$this->ar_select[] = $sql;
@@ -660,8 +660,12 @@
$prefix = (count($this->ar_like) == 0) ? '' : $type;
$v = $this->escape_like_str($v);
-
- if ($side == 'before')
+
+ if ($side == 'none')
+ {
+ $like_statement = $prefix." $k $not LIKE '{$v}'";
+ }
+ elseif ($side == 'before')
{
$like_statement = $prefix." $k $not LIKE '%{$v}'";
}
@@ -870,11 +874,11 @@
*/
public function limit($value, $offset = '')
{
- $this->ar_limit = $value;
+ $this->ar_limit = (int) $value;
if ($offset != '')
{
- $this->ar_offset = $offset;
+ $this->ar_offset = (int) $offset;
}
return $this;
@@ -1322,7 +1326,7 @@
{
if ($this->db_debug)
{
- return $this->display_error('db_myst_use_index');
+ return $this->display_error('db_must_use_index');
}
return FALSE;
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 10e8ed0..f3e824d 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -218,7 +218,7 @@
// Some DBs have functions that return the version, and don't run special
// SQL queries per se. In these instances, just return the result.
- $driver_version_exceptions = array('oci8', 'sqlite');
+ $driver_version_exceptions = array('oci8', 'sqlite', 'cubrid');
if (in_array($this->dbdriver, $driver_version_exceptions))
{
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
new file mode 100644
index 0000000..d011404
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -0,0 +1,792 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0.2
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Database Adapter Class
+ *
+ * Note: _DB is an extender class that the app controller
+ * creates dynamically based on whether the active record
+ * class is being used or not.
+ *
+ * @package CodeIgniter
+ * @subpackage Drivers
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_driver extends CI_DB {
+
+ // Default CUBRID Broker port. Will be used unless user
+ // explicitly specifies another one.
+ const DEFAULT_PORT = 33000;
+
+ var $dbdriver = 'cubrid';
+
+ // The character used for escaping - no need in CUBRID
+ var $_escape_char = '';
+
+ // clause and character used for LIKE escape sequences - not used in CUBRID
+ var $_like_escape_str = '';
+ var $_like_escape_chr = '';
+
+ /**
+ * The syntax to count rows is slightly different across different
+ * database engines, so this string appears in each driver and is
+ * used for the count_all() and count_all_results() functions.
+ */
+ var $_count_string = 'SELECT COUNT(*) AS ';
+ var $_random_keyword = ' RAND()'; // database specific random keyword
+
+ /**
+ * Non-persistent database connection
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_connect()
+ {
+ // If no port is defined by the user, use the default value
+ if ($this->port == '')
+ {
+ $this->port = self::DEFAULT_PORT;
+ }
+
+ $conn = cubrid_connect($this->hostname, $this->port, $this->database, $this->username, $this->password);
+
+ if ($conn)
+ {
+ // Check if a user wants to run queries in dry, i.e. run the
+ // queries but not commit them.
+ if (isset($this->auto_commit) && ! $this->auto_commit)
+ {
+ cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_FALSE);
+ }
+ else
+ {
+ cubrid_set_autocommit($conn, CUBRID_AUTOCOMMIT_TRUE);
+ $this->auto_commit = TRUE;
+ }
+ }
+
+ return $conn;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Persistent database connection
+ * In CUBRID persistent DB connection is supported natively in CUBRID
+ * engine which can be configured in the CUBRID Broker configuration
+ * file by setting the CCI_PCONNECT parameter to ON. In that case, all
+ * connections established between the client application and the
+ * server will become persistent. This is calling the same
+ * @cubrid_connect function will establish persisten connection
+ * considering that the CCI_PCONNECT is ON.
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_pconnect()
+ {
+ return $this->db_connect();
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Reconnect
+ *
+ * Keep / reestablish the db connection if no queries have been
+ * sent for a length of time exceeding the server's idle timeout
+ *
+ * @access public
+ * @return void
+ */
+ function reconnect()
+ {
+ if (cubrid_ping($this->conn_id) === FALSE)
+ {
+ $this->conn_id = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Select the database
+ *
+ * @access private called by the base class
+ * @return resource
+ */
+ function db_select()
+ {
+ // In CUBRID there is no need to select a database as the database
+ // is chosen at the connection time.
+ // So, to determine if the database is "selected", all we have to
+ // do is ping the server and return that value.
+ return cubrid_ping($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set client character set
+ *
+ * @access public
+ * @param string
+ * @param string
+ * @return resource
+ */
+ function db_set_charset($charset, $collation)
+ {
+ // In CUBRID, there is no need to set charset or collation.
+ // This is why returning true will allow the application continue
+ // its normal process.
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Version number query string
+ *
+ * @access public
+ * @return string
+ */
+ function _version()
+ {
+ // To obtain the CUBRID Server version, no need to run the SQL query.
+ // CUBRID PHP API provides a function to determin this value.
+ // This is why we also need to add 'cubrid' value to the list of
+ // $driver_version_exceptions array in DB_driver class in
+ // version() function.
+ return cubrid_get_server_info($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Execute the query
+ *
+ * @access private called by the base class
+ * @param string an SQL query
+ * @return resource
+ */
+ function _execute($sql)
+ {
+ $sql = $this->_prep_query($sql);
+ return @cubrid_query($sql, $this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Prep the query
+ *
+ * If needed, each database adapter can prep the query string
+ *
+ * @access private called by execute()
+ * @param string an SQL query
+ * @return string
+ */
+ function _prep_query($sql)
+ {
+ // No need to prepare
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Begin Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ function trans_begin($test_mode = FALSE)
+ {
+ if ( ! $this->trans_enabled)
+ {
+ return TRUE;
+ }
+
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ if ($this->_trans_depth > 0)
+ {
+ return TRUE;
+ }
+
+ // Reset the transaction failure flag.
+ // If the $test_mode flag is set to TRUE transactions will be rolled back
+ // even if the queries produce a successful result.
+ $this->_trans_failure = ($test_mode === TRUE) ? TRUE : FALSE;
+
+ if (cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_FALSE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Commit Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ function trans_commit()
+ {
+ if ( ! $this->trans_enabled)
+ {
+ return TRUE;
+ }
+
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ if ($this->_trans_depth > 0)
+ {
+ return TRUE;
+ }
+
+ cubrid_commit($this->conn_id);
+
+ if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rollback Transaction
+ *
+ * @access public
+ * @return bool
+ */
+ function trans_rollback()
+ {
+ if ( ! $this->trans_enabled)
+ {
+ return TRUE;
+ }
+
+ // When transactions are nested we only begin/commit/rollback the outermost ones
+ if ($this->_trans_depth > 0)
+ {
+ return TRUE;
+ }
+
+ cubrid_rollback($this->conn_id);
+
+ if ($this->auto_commit && ! cubrid_get_autocommit($this->conn_id))
+ {
+ cubrid_set_autocommit($this->conn_id, CUBRID_AUTOCOMMIT_TRUE);
+ }
+
+ return TRUE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape String
+ *
+ * @access public
+ * @param string
+ * @param bool whether or not the string will be used in a LIKE condition
+ * @return string
+ */
+ function escape_str($str, $like = FALSE)
+ {
+ if (is_array($str))
+ {
+ foreach ($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
+ if (function_exists('cubrid_real_escape_string') AND is_resource($this->conn_id))
+ {
+ $str = cubrid_real_escape_string($str, $this->conn_id);
+ }
+ else
+ {
+ $str = addslashes($str);
+ }
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ }
+
+ return $str;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Affected Rows
+ *
+ * @access public
+ * @return integer
+ */
+ function affected_rows()
+ {
+ return @cubrid_affected_rows($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert ID
+ *
+ * @access public
+ * @return integer
+ */
+ function insert_id()
+ {
+ return @cubrid_insert_id($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * "Count All" query
+ *
+ * Generates a platform-specific query string that counts all records in
+ * the specified table
+ *
+ * @access public
+ * @param string
+ * @return string
+ */
+ function count_all($table = '')
+ {
+ if ($table == '')
+ {
+ return 0;
+ }
+
+ $query = $this->query($this->_count_string . $this->_protect_identifiers('numrows') . " FROM " . $this->_protect_identifiers($table, TRUE, NULL, FALSE));
+
+ if ($query->num_rows() == 0)
+ {
+ return 0;
+ }
+
+ $row = $query->row();
+ $this->_reset_select();
+ return (int) $row->numrows;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * List table query
+ *
+ * Generates a platform-specific query string so that the table names can be fetched
+ *
+ * @access private
+ * @param boolean
+ * @return string
+ */
+ function _list_tables($prefix_limit = FALSE)
+ {
+ $sql = "SHOW TABLES";
+
+ if ($prefix_limit !== FALSE AND $this->dbprefix != '')
+ {
+ $sql .= " LIKE '".$this->escape_like_str($this->dbprefix)."%'";
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Show column query
+ *
+ * Generates a platform-specific query string so that the column names can be fetched
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _list_columns($table = '')
+ {
+ return "SHOW COLUMNS FROM ".$this->_protect_identifiers($table, TRUE, NULL, FALSE);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data query
+ *
+ * Generates a platform-specific query so that the column data can be retrieved
+ *
+ * @access public
+ * @param string the table name
+ * @return object
+ */
+ function _field_data($table)
+ {
+ return "SELECT * FROM ".$table." LIMIT 1";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message string
+ *
+ * @access private
+ * @return string
+ */
+ function _error_message()
+ {
+ return cubrid_error($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * The error message number
+ *
+ * @access private
+ * @return integer
+ */
+ function _error_number()
+ {
+ return cubrid_errno($this->conn_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Escape the SQL Identifiers
+ *
+ * This function escapes column and table names
+ *
+ * @access private
+ * @param string
+ * @return string
+ */
+ function _escape_identifiers($item)
+ {
+ if ($this->_escape_char == '')
+ {
+ return $item;
+ }
+
+ foreach ($this->_reserved_identifiers as $id)
+ {
+ if (strpos($item, '.'.$id) !== FALSE)
+ {
+ $str = $this->_escape_char. str_replace('.', $this->_escape_char.'.', $item);
+
+ // remove duplicates if the user already included the escape
+ return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ }
+ }
+
+ if (strpos($item, '.') !== FALSE)
+ {
+ $str = $this->_escape_char.str_replace('.', $this->_escape_char.'.'.$this->_escape_char, $item).$this->_escape_char;
+ }
+ else
+ {
+ $str = $this->_escape_char.$item.$this->_escape_char;
+ }
+
+ // remove duplicates if the user already included the escape
+ return preg_replace('/['.$this->_escape_char.']+/', $this->_escape_char, $str);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * From Tables
+ *
+ * This function implicitly groups FROM tables so there is no confusion
+ * about operator precedence in harmony with SQL standards
+ *
+ * @access public
+ * @param type
+ * @return type
+ */
+ function _from_tables($tables)
+ {
+ if ( ! is_array($tables))
+ {
+ $tables = array($tables);
+ }
+
+ return '('.implode(', ', $tables).')';
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert($table, $keys, $values)
+ {
+ return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Replace statement
+ *
+ * Generates a platform-specific replace string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _replace($table, $keys, $values)
+ {
+ return "REPLACE INTO ".$table." (\"".implode('", "', $keys)."\") VALUES (".implode(', ', $values).")";
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Insert_batch statement
+ *
+ * Generates a platform-specific insert string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the insert keys
+ * @param array the insert values
+ * @return string
+ */
+ function _insert_batch($table, $keys, $values)
+ {
+ return "INSERT INTO ".$table." (\"".implode('", "', $keys)."\") VALUES ".implode(', ', $values);
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Update statement
+ *
+ * Generates a platform-specific update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @param array the orderby clause
+ * @param array the limit clause
+ * @return string
+ */
+ function _update($table, $values, $where, $orderby = array(), $limit = FALSE)
+ {
+ foreach ($values as $key => $val)
+ {
+ $valstr[] = sprintf('"%s" = %s', $key, $val);
+ }
+
+ $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
+
+ $orderby = (count($orderby) >= 1)?' ORDER BY '.implode(", ", $orderby):'';
+
+ $sql = "UPDATE ".$table." SET ".implode(', ', $valstr);
+
+ $sql .= ($where != '' AND count($where) >=1) ? " WHERE ".implode(" ", $where) : '';
+
+ $sql .= $orderby.$limit;
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Update_Batch statement
+ *
+ * Generates a platform-specific batch update string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the update data
+ * @param array the where clause
+ * @return string
+ */
+ function _update_batch($table, $values, $index, $where = NULL)
+ {
+ $ids = array();
+ $where = ($where != '' AND count($where) >=1) ? implode(" ", $where).' AND ' : '';
+
+ foreach ($values as $key => $val)
+ {
+ $ids[] = $val[$index];
+
+ foreach (array_keys($val) as $field)
+ {
+ if ($field != $index)
+ {
+ $final[$field][] = 'WHEN '.$index.' = '.$val[$index].' THEN '.$val[$field];
+ }
+ }
+ }
+
+ $sql = "UPDATE ".$table." SET ";
+ $cases = '';
+
+ foreach ($final as $k => $v)
+ {
+ $cases .= $k.' = CASE '."\n";
+ foreach ($v as $row)
+ {
+ $cases .= $row."\n";
+ }
+
+ $cases .= 'ELSE '.$k.' END, ';
+ }
+
+ $sql .= substr($cases, 0, -2);
+
+ $sql .= ' WHERE '.$where.$index.' IN ('.implode(',', $ids).')';
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+
+ /**
+ * Truncate statement
+ *
+ * Generates a platform-specific truncate string from the supplied data
+ * If the database does not support the truncate() command
+ * This function maps to "DELETE FROM table"
+ *
+ * @access public
+ * @param string the table name
+ * @return string
+ */
+ function _truncate($table)
+ {
+ return "TRUNCATE ".$table;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Delete statement
+ *
+ * Generates a platform-specific delete string from the supplied data
+ *
+ * @access public
+ * @param string the table name
+ * @param array the where clause
+ * @param string the limit clause
+ * @return string
+ */
+ function _delete($table, $where = array(), $like = array(), $limit = FALSE)
+ {
+ $conditions = '';
+
+ if (count($where) > 0 OR count($like) > 0)
+ {
+ $conditions = "\nWHERE ";
+ $conditions .= implode("\n", $this->ar_where);
+
+ if (count($where) > 0 && count($like) > 0)
+ {
+ $conditions .= " AND ";
+ }
+ $conditions .= implode("\n", $like);
+ }
+
+ $limit = ( ! $limit) ? '' : ' LIMIT '.$limit;
+
+ return "DELETE FROM ".$table.$conditions.$limit;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Limit string
+ *
+ * Generates a platform-specific LIMIT clause
+ *
+ * @access public
+ * @param string the sql query string
+ * @param integer the number of rows to limit the query to
+ * @param integer the offset value
+ * @return string
+ */
+ function _limit($sql, $limit, $offset)
+ {
+ if ($offset == 0)
+ {
+ $offset = '';
+ }
+ else
+ {
+ $offset .= ", ";
+ }
+
+ return $sql."LIMIT ".$offset.$limit;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Close DB Connection
+ *
+ * @access public
+ * @param resource
+ * @return void
+ */
+ function _close($conn_id)
+ {
+ @cubrid_close($conn_id);
+ }
+
+}
+
+
+/* End of file cubrid_driver.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_driver.php */
\ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_forge.php b/system/database/drivers/cubrid/cubrid_forge.php
new file mode 100644
index 0000000..bab03f7
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_forge.php
@@ -0,0 +1,288 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Forge Class
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_forge extends CI_DB_forge {
+
+ /**
+ * Create database
+ *
+ * @access private
+ * @param string the database name
+ * @return bool
+ */
+ function _create_database($name)
+ {
+ // CUBRID does not allow to create a database in SQL. The GUI tools
+ // have to be used for this purpose.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop database
+ *
+ * @access private
+ * @param string the database name
+ * @return bool
+ */
+ function _drop_database($name)
+ {
+ // CUBRID does not allow to drop a database in SQL. The GUI tools
+ // have to be used for this purpose.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Process Fields
+ *
+ * @access private
+ * @param mixed the fields
+ * @return string
+ */
+ function _process_fields($fields)
+ {
+ $current_field_count = 0;
+ $sql = '';
+
+ foreach ($fields as $field=>$attributes)
+ {
+ // Numeric field names aren't allowed in databases, so if the key is
+ // numeric, we know it was assigned by PHP and the developer manually
+ // entered the field information, so we'll simply add it to the list
+ if (is_numeric($field))
+ {
+ $sql .= "\n\t$attributes";
+ }
+ else
+ {
+ $attributes = array_change_key_case($attributes, CASE_UPPER);
+
+ $sql .= "\n\t\"" . $this->db->_protect_identifiers($field) . "\"";
+
+ if (array_key_exists('NAME', $attributes))
+ {
+ $sql .= ' '.$this->db->_protect_identifiers($attributes['NAME']).' ';
+ }
+
+ if (array_key_exists('TYPE', $attributes))
+ {
+ $sql .= ' '.$attributes['TYPE'];
+
+ if (array_key_exists('CONSTRAINT', $attributes))
+ {
+ switch ($attributes['TYPE'])
+ {
+ case 'decimal':
+ case 'float':
+ case 'numeric':
+ $sql .= '('.implode(',', $attributes['CONSTRAINT']).')';
+ break;
+ case 'enum': // As of version 8.4.0 CUBRID does not support
+ // enum data type.
+ break;
+ case 'set':
+ $sql .= '("'.implode('","', $attributes['CONSTRAINT']).'")';
+ break;
+ default:
+ $sql .= '('.$attributes['CONSTRAINT'].')';
+ }
+ }
+ }
+
+ if (array_key_exists('UNSIGNED', $attributes) && $attributes['UNSIGNED'] === TRUE)
+ {
+ //$sql .= ' UNSIGNED';
+ // As of version 8.4.0 CUBRID does not support UNSIGNED INTEGER data type.
+ // Will be supported in the next release as a part of MySQL Compatibility.
+ }
+
+ if (array_key_exists('DEFAULT', $attributes))
+ {
+ $sql .= ' DEFAULT \''.$attributes['DEFAULT'].'\'';
+ }
+
+ if (array_key_exists('NULL', $attributes) && $attributes['NULL'] === TRUE)
+ {
+ $sql .= ' NULL';
+ }
+ else
+ {
+ $sql .= ' NOT NULL';
+ }
+
+ if (array_key_exists('AUTO_INCREMENT', $attributes) && $attributes['AUTO_INCREMENT'] === TRUE)
+ {
+ $sql .= ' AUTO_INCREMENT';
+ }
+
+ if (array_key_exists('UNIQUE', $attributes) && $attributes['UNIQUE'] === TRUE)
+ {
+ $sql .= ' UNIQUE';
+ }
+ }
+
+ // don't add a comma on the end of the last field
+ if (++$current_field_count < count($fields))
+ {
+ $sql .= ',';
+ }
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Create Table
+ *
+ * @access private
+ * @param string the table name
+ * @param mixed the fields
+ * @param mixed primary key(s)
+ * @param mixed key(s)
+ * @param boolean should 'IF NOT EXISTS' be added to the SQL
+ * @return bool
+ */
+ function _create_table($table, $fields, $primary_keys, $keys, $if_not_exists)
+ {
+ $sql = 'CREATE TABLE ';
+
+ if ($if_not_exists === TRUE)
+ {
+ //$sql .= 'IF NOT EXISTS ';
+ // As of version 8.4.0 CUBRID does not support this SQL syntax.
+ }
+
+ $sql .= $this->db->_escape_identifiers($table)." (";
+
+ $sql .= $this->_process_fields($fields);
+
+ // If there is a PK defined
+ if (count($primary_keys) > 0)
+ {
+ $key_name = "pk_" . $table . "_" .
+ $this->db->_protect_identifiers(implode('_', $primary_keys));
+
+ $primary_keys = $this->db->_protect_identifiers($primary_keys);
+ $sql .= ",\n\tCONSTRAINT " . $key_name . " PRIMARY KEY(" . implode(', ', $primary_keys) . ")";
+ }
+
+ if (is_array($keys) && count($keys) > 0)
+ {
+ foreach ($keys as $key)
+ {
+ if (is_array($key))
+ {
+ $key_name = $this->db->_protect_identifiers(implode('_', $key));
+ $key = $this->db->_protect_identifiers($key);
+ }
+ else
+ {
+ $key_name = $this->db->_protect_identifiers($key);
+ $key = array($key_name);
+ }
+
+ $sql .= ",\n\tKEY \"{$key_name}\" (" . implode(', ', $key) . ")";
+ }
+ }
+
+ $sql .= "\n);";
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Drop Table
+ *
+ * @access private
+ * @return string
+ */
+ function _drop_table($table)
+ {
+ return "DROP TABLE IF EXISTS ".$this->db->_escape_identifiers($table);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Alter table query
+ *
+ * Generates a platform-specific query so that a table can be altered
+ * Called by add_column(), drop_column(), and column_alter(),
+ *
+ * @access private
+ * @param string the ALTER type (ADD, DROP, CHANGE)
+ * @param string the column name
+ * @param array fields
+ * @param string the field after which we should add the new field
+ * @return object
+ */
+ function _alter_table($alter_type, $table, $fields, $after_field = '')
+ {
+ $sql = 'ALTER TABLE '.$this->db->_protect_identifiers($table)." $alter_type ";
+
+ // DROP has everything it needs now.
+ if ($alter_type == 'DROP')
+ {
+ return $sql.$this->db->_protect_identifiers($fields);
+ }
+
+ $sql .= $this->_process_fields($fields);
+
+ if ($after_field != '')
+ {
+ $sql .= ' AFTER ' . $this->db->_protect_identifiers($after_field);
+ }
+
+ return $sql;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Rename a table
+ *
+ * Generates a platform-specific query so that a table can be renamed
+ *
+ * @access private
+ * @param string the old table name
+ * @param string the new table name
+ * @return string
+ */
+ function _rename_table($table_name, $new_table_name)
+ {
+ $sql = 'RENAME TABLE '.$this->db->_protect_identifiers($table_name)." AS ".$this->db->_protect_identifiers($new_table_name);
+ return $sql;
+ }
+
+}
+
+/* End of file cubrid_forge.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_forge.php */
\ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_result.php b/system/database/drivers/cubrid/cubrid_result.php
new file mode 100644
index 0000000..6f0c2b5
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_result.php
@@ -0,0 +1,202 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 2.0.2
+ * @filesource
+ */
+
+// --------------------------------------------------------------------
+
+/**
+ * CUBRID Result Class
+ *
+ * This class extends the parent result class: CI_DB_result
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_result extends CI_DB_result {
+
+ /**
+ * Number of rows in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_rows()
+ {
+ return @cubrid_num_rows($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Number of fields in the result set
+ *
+ * @access public
+ * @return integer
+ */
+ function num_fields()
+ {
+ return @cubrid_num_fields($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Fetch Field Names
+ *
+ * Generates an array of column names
+ *
+ * @access public
+ * @return array
+ */
+ function list_fields()
+ {
+ return cubrid_column_names($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Field data
+ *
+ * Generates an array of objects containing field meta-data
+ *
+ * @access public
+ * @return array
+ */
+ function field_data()
+ {
+ $retval = array();
+
+ $tablePrimaryKeys = array();
+
+ while ($field = cubrid_fetch_field($this->result_id))
+ {
+ $F = new stdClass();
+ $F->name = $field->name;
+ $F->type = $field->type;
+ $F->default = $field->def;
+ $F->max_length = $field->max_length;
+
+ // At this moment primary_key property is not returned when
+ // cubrid_fetch_field is called. The following code will
+ // provide a patch for it. primary_key property will be added
+ // in the next release.
+
+ // TODO: later version of CUBRID will provide primary_key
+ // property.
+ // When PK is defined in CUBRID, an index is automatically
+ // created in the db_index system table in the form of
+ // pk_tblname_fieldname. So the following will count how many
+ // columns are there which satisfy this format.
+ // The query will search for exact single columns, thus
+ // compound PK is not supported.
+ $res = cubrid_query($this->conn_id,
+ "SELECT COUNT(*) FROM db_index WHERE class_name = '" . $field->table .
+ "' AND is_primary_key = 'YES' AND index_name = 'pk_" .
+ $field->table . "_" . $field->name . "'"
+ );
+
+ if ($res)
+ {
+ $row = cubrid_fetch_array($res, CUBRID_NUM);
+ $F->primary_key = ($row[0] > 0 ? 1 : null);
+ }
+ else
+ {
+ $F->primary_key = null;
+ }
+
+ if (is_resource($res))
+ {
+ cubrid_close_request($res);
+ $this->result_id = FALSE;
+ }
+
+ $retval[] = $F;
+ }
+
+ return $retval;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Free the result
+ *
+ * @return null
+ */
+ function free_result()
+ {
+ if(is_resource($this->result_id) ||
+ get_resource_type($this->result_id) == "Unknown" &&
+ preg_match('/Resource id #/', strval($this->result_id)))
+ {
+ cubrid_close_request($this->result_id);
+ $this->result_id = FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Data Seek
+ *
+ * Moves the internal pointer to the desired offset. We call
+ * this internally before fetching results to make sure the
+ * result set starts at zero
+ *
+ * @access private
+ * @return array
+ */
+ function _data_seek($n = 0)
+ {
+ return cubrid_data_seek($this->result_id, $n);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - associative array
+ *
+ * Returns the result set as an array
+ *
+ * @access private
+ * @return array
+ */
+ function _fetch_assoc()
+ {
+ return cubrid_fetch_assoc($this->result_id);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Result - object
+ *
+ * Returns the result set as an object
+ *
+ * @access private
+ * @return object
+ */
+ function _fetch_object()
+ {
+ return cubrid_fetch_object($this->result_id);
+ }
+
+}
+
+
+/* End of file cubrid_result.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_result.php */
\ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_utility.php b/system/database/drivers/cubrid/cubrid_utility.php
new file mode 100644
index 0000000..cd16d1e
--- /dev/null
+++ b/system/database/drivers/cubrid/cubrid_utility.php
@@ -0,0 +1,108 @@
+<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author Esen Sagynov
+ * @copyright Copyright (c) 2008 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * CUBRID Utility Class
+ *
+ * @category Database
+ * @author Esen Sagynov
+ * @link http://codeigniter.com/user_guide/database/
+ */
+class CI_DB_cubrid_utility extends CI_DB_utility {
+
+ /**
+ * List databases
+ *
+ * @access private
+ * @return array
+ */
+ function _list_databases()
+ {
+ // CUBRID does not allow to see the list of all databases on the
+ // server. It is the way its architecture is designed. Every
+ // database is independent and isolated.
+ // For this reason we can return only the name of the currect
+ // connected database.
+ if ($this->conn_id)
+ {
+ return "SELECT '" . $this->database . "'";
+ }
+ else
+ {
+ return FALSE;
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Optimize table query
+ *
+ * Generates a platform-specific query so that a table can be optimized
+ *
+ * @access private
+ * @param string the table name
+ * @return object
+ * @link http://www.cubrid.org/manual/840/en/Optimize%20Database
+ */
+ function _optimize_table($table)
+ {
+ // No SQL based support in CUBRID as of version 8.4.0. Database or
+ // table optimization can be performed using CUBRID Manager
+ // database administration tool. See the link above for more info.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Repair table query
+ *
+ * Generates a platform-specific query so that a table can be repaired
+ *
+ * @access private
+ * @param string the table name
+ * @return object
+ * @link http://www.cubrid.org/manual/840/en/Checking%20Database%20Consistency
+ */
+ function _repair_table($table)
+ {
+ // Not supported in CUBRID as of version 8.4.0. Database or
+ // table consistency can be checked using CUBRID Manager
+ // database administration tool. See the link above for more info.
+ return FALSE;
+ }
+
+ // --------------------------------------------------------------------
+ /**
+ * CUBRID Export
+ *
+ * @access private
+ * @param array Preferences
+ * @return mixed
+ */
+ function _backup($params = array())
+ {
+ // No SQL based support in CUBRID as of version 8.4.0. Database or
+ // table backup can be performed using CUBRID Manager
+ // database administration tool.
+ return $this->db->display_error('db_unsuported_feature');
+ }
+}
+
+/* End of file cubrid_utility.php */
+/* Location: ./system/database/drivers/cubrid/cubrid_utility.php */
\ No newline at end of file
diff --git a/system/database/drivers/cubrid/index.html b/system/database/drivers/cubrid/index.html
new file mode 100644
index 0000000..c942a79
--- /dev/null
+++ b/system/database/drivers/cubrid/index.html
@@ -0,0 +1,10 @@
+<html>
+<head>
+ <title>403 Forbidden</title>
+</head>
+<body>
+
+<p>Directory access is forbidden.</p>
+
+</body>
+</html>
\ No newline at end of file
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 65397ed..b39bd93 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -367,6 +367,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index b7d547c..f87cfea 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -54,6 +54,9 @@
var $_count_string = 'SELECT COUNT(*) AS ';
var $_random_keyword = ' RAND()'; // database specific random keyword
+ // whether SET NAMES must be used to set the character set
+ var $use_set_names;
+
/**
* Non-persistent database connection
*
@@ -132,15 +135,13 @@
*/
function db_set_charset($charset, $collation)
{
- static $use_set_names;
-
- if ( ! isset($use_set_names))
+ if ( ! isset($this->use_set_names))
{
// mysql_set_charset() requires PHP >= 5.2.3 and MySQL >= 5.0.7, use SET NAMES as fallback
- $use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
+ $this->use_set_names = (version_compare(PHP_VERSION, '5.2.3', '>=') && version_compare(mysql_get_server_info(), '5.0.7', '>=')) ? FALSE : TRUE;
}
- if ($use_set_names)
+ if ($this->use_set_names === TRUE)
{
return @mysql_query("SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'", $this->conn_id);
}
@@ -384,6 +385,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
@@ -439,7 +441,7 @@
*/
function _field_data($table)
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ return "DESCRIBE ".$table;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/mysql_result.php b/system/database/drivers/mysql/mysql_result.php
index 5073896..2d2905c 100644
--- a/system/database/drivers/mysql/mysql_result.php
+++ b/system/database/drivers/mysql/mysql_result.php
@@ -84,14 +84,19 @@
function field_data()
{
$retval = array();
- while ($field = mysql_fetch_field($this->result_id))
+ while ($field = mysql_fetch_object($this->result_id))
{
+ preg_match('/([a-zA-Z]+)\((\d+)\)/', $field->Type, $matches);
+
+ $type = $matches[1];
+ $length = (int)$matches[2];
+
$F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->default = $field->def;
- $F->max_length = $field->max_length;
- $F->primary_key = $field->primary_key;
+ $F->name = $field->Field;
+ $F->type = $type;
+ $F->default = $field->Default;
+ $F->max_length = $length;
+ $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );
$retval[] = $F;
}
diff --git a/system/database/drivers/mysql/mysql_utility.php b/system/database/drivers/mysql/mysql_utility.php
index e9747c5..48c4d63 100644
--- a/system/database/drivers/mysql/mysql_utility.php
+++ b/system/database/drivers/mysql/mysql_utility.php
@@ -96,7 +96,7 @@
}
// Get the table schema
- $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.'.$table);
+ $query = $this->db->query("SHOW CREATE TABLE `".$this->db->database.'`.`'.$table.'`');
// No result means the table name was invalid
if ($query === FALSE)
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index b8586c2..ccd110f 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -54,6 +54,9 @@
*/
var $delete_hack = TRUE;
+ // whether SET NAMES must be used to set the character set
+ var $use_set_names;
+
// --------------------------------------------------------------------
/**
@@ -132,15 +135,13 @@
*/
function _db_set_charset($charset, $collation)
{
- static $use_set_names;
-
- if ( ! isset($use_set_names))
+ if ( ! isset($this->use_set_names))
{
// mysqli_set_charset() requires MySQL >= 5.0.7, use SET NAMES as fallback
- $use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
+ $this->use_set_names = (version_compare(mysqli_get_server_info($this->conn_id), '5.0.7', '>=')) ? FALSE : TRUE;
}
- if ($use_set_names)
+ if ($this->use_set_names === TRUE)
{
return @mysqli_query($this->conn_id, "SET NAMES '".$this->escape_str($charset)."' COLLATE '".$this->escape_str($collation)."'");
}
@@ -385,6 +386,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
@@ -440,7 +442,7 @@
*/
function _field_data($table)
{
- return "SELECT * FROM ".$table." LIMIT 1";
+ return "DESCRIBE ".$table;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_result.php b/system/database/drivers/mysqli/mysqli_result.php
index c4d8f5d..ac86305 100644
--- a/system/database/drivers/mysqli/mysqli_result.php
+++ b/system/database/drivers/mysqli/mysqli_result.php
@@ -84,21 +84,26 @@
function field_data()
{
$retval = array();
- while ($field = mysqli_fetch_field($this->result_id))
+ while ($field = mysqli_fetch_object($this->result_id))
{
+ preg_match('/([a-zA-Z]+)\((\d+)\)/', $field->Type, $matches);
+
+ $type = $matches[1];
+ $length = (int)$matches[2];
+
$F = new stdClass();
- $F->name = $field->name;
- $F->type = $field->type;
- $F->default = $field->def;
- $F->max_length = $field->max_length;
- $F->primary_key = ($field->flags & MYSQLI_PRI_KEY_FLAG) ? 1 : 0;
+ $F->name = $field->Field;
+ $F->type = $type;
+ $F->default = $field->Default;
+ $F->max_length = $length;
+ $F->primary_key = ( $field->Key == 'PRI' ? 1 : 0 );
$retval[] = $F;
}
return $retval;
}
-
+
// --------------------------------------------------------------------
/**
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 14df104..42cfaae 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -470,6 +470,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 81e0d7c..08cd27b 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -50,7 +50,7 @@
function CI_DB_odbc_driver($params)
{
- parent::CI_DB($params);
+ parent::CI_DB_driver($params);
$this->_random_keyword = ' RND('.time().')'; // database specific random keyword
}
@@ -339,6 +339,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 1403968..5367f97 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -385,6 +385,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index eb4e585..0cc898b 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -354,6 +354,7 @@
}
$row = $query->row();
+ $this->_reset_select();
return (int) $row->numrows;
}
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 1d32792..400fd31 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -344,6 +344,7 @@
return '0';
$row = $query->row();
+ $this->_reset_select();
return $row->numrows;
}
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
index 553e8d7..6c559bb 100644
--- a/system/helpers/date_helper.php
+++ b/system/helpers/date_helper.php
@@ -491,6 +491,72 @@
// ------------------------------------------------------------------------
/**
+ * Turns many "reasonably-date-like" strings into something
+ * that is actually useful. This only works for dates after unix epoch.
+ *
+ * @access public
+ * @param string The terribly formatted date-like string
+ * @param string Date format to return (same as php date function)
+ * @return string
+ */
+if ( ! function_exists('nice_date'))
+{
+ function nice_date($bad_date='', $format=false)
+ {
+ if (empty($bad_date))
+ {
+ return 'Unknown';
+ }
+ // Date like: YYYYMM
+ if (preg_match('/^\d{6}$/',$bad_date))
+ {
+ //echo $bad_date." ";
+ if (in_array(substr($bad_date, 0, 2),array('19', '20')))
+ {
+ $year = substr($bad_date, 0, 4);
+ $month = substr($bad_date, 4, 2);
+ }
+ else
+ {
+ $month = substr($bad_date, 0, 2);
+ $year = substr($bad_date, 2, 4);
+ }
+ return date($format, strtotime($year . '-' . $month . '-01'));
+
+ }
+
+ // Date Like: YYYYMMDD
+ if (preg_match('/^\d{8}$/',$bad_date))
+ {
+ $month = substr($bad_date, 0, 2);
+ $day = substr($bad_date, 2, 2);
+ $year = substr($bad_date, 4, 4);
+ return date($format, strtotime($month . '/01/' . $year));
+ }
+
+ // Date Like: MM-DD-YYYY __or__ M-D-YYYY (or anything in between)
+ if (preg_match('/^\d{1,2}-\d{1,2}-\d{4}$/',$bad_date))
+ {
+ list($m, $d, $y) = explode('-', $bad_date);
+ return date($format, strtotime("{$y}-{$m}-{$d}"));
+ }
+
+ // Any other kind of string, when converted into UNIX time,
+ // produces "0 seconds after epoc..." is probably bad...
+ // return "Invalid Date".
+ if (date('U', strtotime($bad_date)) == '0')
+ {
+ return "Invalid Date";
+ }
+
+ // It's probably a valid-ish date format already
+ return date($format, strtotime($bad_date));
+ }
+}
+
+// ------------------------------------------------------------------------
+
+/**
* Timezone Menu
*
* Generates a drop-down menu of timezones.
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 2925d3c..d9305c0 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -64,8 +64,8 @@
$form .= '>';
- // CSRF
- if ($CI->config->item('csrf_protection') === TRUE)
+ // Add CSRF field if enabled, but leave it out for GET requests and requests to external websites
+ if ($CI->config->item('csrf_protection') === TRUE AND ! (strpos($action, $CI->config->site_url()) === FALSE OR strpos($form, 'method="get"')))
{
$hidden[$CI->security->get_csrf_token_name()] = $CI->security->get_csrf_hash();
}
@@ -94,7 +94,7 @@
*/
if ( ! function_exists('form_open_multipart'))
{
- function form_open_multipart($action, $attributes = array(), $hidden = array())
+ function form_open_multipart($action = '', $attributes = array(), $hidden = array())
{
if (is_string($attributes))
{
@@ -249,7 +249,7 @@
{
function form_textarea($data = '', $value = '', $extra = '')
{
- $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '90', 'rows' => '12');
+ $defaults = array('name' => (( ! is_array($data)) ? $data : ''), 'cols' => '40', 'rows' => '10');
if ( ! is_array($data) OR ! isset($data['value']))
{
diff --git a/system/helpers/string_helper.php b/system/helpers/string_helper.php
index 7765bba..9fa69f4 100644
--- a/system/helpers/string_helper.php
+++ b/system/helpers/string_helper.php
@@ -243,6 +243,23 @@
// ------------------------------------------------------------------------
/**
+ * Add's _1 to a string or increment the ending number to allow _2, _3, etc
+ *
+ * @param string $str required
+ * @param string $separator What should the duplicate number be appended with
+ * @param string $first Which number should be used for the first dupe increment
+ * @return string
+ */
+function increment_string($str, $separator = '_', $first = 1)
+{
+ preg_match('/(.+)'.$separator.'([0-9]+)$/', $str, $match);
+
+ return isset($match[2]) ? $match[1].$separator.($match[2] + 1) : $str.$separator.$first;
+}
+
+// ------------------------------------------------------------------------
+
+/**
* Alternator
*
* Allows strings to be alternated. See docs...
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
old mode 100644
new mode 100755
index 9f4b852..c524ddd
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -512,7 +512,7 @@
$str = strtolower($str);
}
- return trim(stripslashes($str));
+ return trim(trim(stripslashes($str)), $replace);
}
}
@@ -527,7 +527,7 @@
*
* @access public
* @param string the URL
- * @param string the method: location or redirect
+ * @param string the method: location or refresh
* @return string
*/
if ( ! function_exists('redirect'))
diff --git a/system/language/english/form_validation_lang.php b/system/language/english/form_validation_lang.php
index 3f24090..d1cf039 100644
--- a/system/language/english/form_validation_lang.php
+++ b/system/language/english/form_validation_lang.php
@@ -7,7 +7,7 @@
$lang['valid_url'] = "The %s field must contain a valid URL.";
$lang['valid_ip'] = "The %s field must contain a valid IP.";
$lang['min_length'] = "The %s field must be at least %s characters in length.";
-$lang['max_length'] = "The %s field can not exceed %s characters in length.";
+$lang['max_length'] = "The %s field cannot exceed %s characters in length.";
$lang['exact_length'] = "The %s field must be exactly %s characters in length.";
$lang['alpha'] = "The %s field may only contain alphabetical characters.";
$lang['alpha_numeric'] = "The %s field may only contain alpha-numeric characters.";
@@ -17,6 +17,7 @@
$lang['integer'] = "The %s field must contain an integer.";
$lang['regex_match'] = "The %s field is not in the correct format.";
$lang['matches'] = "The %s field does not match the %s field.";
+$lang['is_unique'] = "The %s field must contain a unique value.";
$lang['is_natural'] = "The %s field must contain only positive numbers.";
$lang['is_natural_no_zero'] = "The %s field must contain a number greater than zero.";
$lang['decimal'] = "The %s field must contain a decimal number.";
diff --git a/system/language/english/migration_lang.php b/system/language/english/migration_lang.php
new file mode 100644
index 0000000..4763ca2
--- /dev/null
+++ b/system/language/english/migration_lang.php
@@ -0,0 +1,13 @@
+<?php
+
+$lang['migration_none_found'] = "No migrations were found.";
+$lang['migration_not_found'] = "This migration could not be found.";
+$lang['migration_multiple_version'] = "This are multiple migrations with the same version number: %d.";
+$lang['migration_class_doesnt_exist'] = "The migration class \"%s\" could not be found.";
+$lang['migration_missing_up_method'] = "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_missing_down_method'] = "The migration class \"%s\" is missing an 'up' method.";
+$lang['migration_invalid_filename'] = "Migration \"%s\" has an invalid filename.";
+
+
+/* End of file migration_lang.php */
+/* Location: ./system/language/english/migration_lang.php */
\ No newline at end of file
diff --git a/system/libraries/Cache/drivers/Cache_file.php b/system/libraries/Cache/drivers/Cache_file.php
index 13e2d1a..6c37e70 100644
--- a/system/libraries/Cache/drivers/Cache_file.php
+++ b/system/libraries/Cache/drivers/Cache_file.php
@@ -157,17 +157,16 @@
if (is_array($data))
{
- $data = $data['data'];
$mtime = filemtime($this->_cache_path.$id);
- if ( ! isset($data['ttl']))
+ if ( ! isset($data['data']['ttl']))
{
return FALSE;
}
return array(
- 'expire' => $mtime + $data['ttl'],
- 'mtime' => $mtime
+ 'expire' => $mtime + $data['data']['ttl'],
+ 'mtime' => $mtime
);
}
diff --git a/system/libraries/Cache/drivers/Cache_memcached.php b/system/libraries/Cache/drivers/Cache_memcached.php
index ec2fd21..04aa81a 100644
--- a/system/libraries/Cache/drivers/Cache_memcached.php
+++ b/system/libraries/Cache/drivers/Cache_memcached.php
@@ -10,19 +10,19 @@
* @license http://codeigniter.com/user_guide/license.html
* @link http://codeigniter.com
* @since Version 2.0
- * @filesource
+ * @filesource
*/
// ------------------------------------------------------------------------
/**
- * CodeIgniter Memcached Caching Class
+ * CodeIgniter Memcached Caching Class
*
* @package CodeIgniter
* @subpackage Libraries
* @category Core
* @author ExpressionEngine Dev Team
- * @link
+ * @link
*/
class CI_Cache_memcached extends CI_Driver {
@@ -37,18 +37,18 @@
)
);
- // ------------------------------------------------------------------------
+ // ------------------------------------------------------------------------
/**
* Fetch from cache
*
* @param mixed unique key 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;
}
@@ -64,11 +64,11 @@
*/
public function save($id, $data, $ttl = 60)
{
- return $this->_memcached->add($id, array($data, time(), $ttl), $ttl);
+ return $this->_memcached->set($id, array($data, time(), $ttl), $ttl);
}
// ------------------------------------------------------------------------
-
+
/**
* Delete from Cache
*
@@ -81,7 +81,7 @@
}
// ------------------------------------------------------------------------
-
+
/**
* Clean the Cache
*
@@ -106,7 +106,7 @@
}
// ------------------------------------------------------------------------
-
+
/**
* Get Cache Metadata
*
@@ -140,6 +140,7 @@
{
// Try to load memcached server info from the config file.
$CI =& get_instance();
+
if ($CI->config->load('memcached', TRUE, TRUE))
{
if (is_array($CI->config->config['memcached']))
@@ -149,11 +150,24 @@
foreach ($CI->config->config['memcached'] as $name => $conf)
{
$this->_memcache_conf[$name] = $conf;
- }
- }
+ }
+ }
}
-
- $this->_memcached = new Memcached();
+
+ if (class_exists('Memcached'))
+ {
+ $this->_memcached = new Memcached();
+ }
+ else if (class_exists('Memcache'))
+ {
+ $this->_memcached = new Memcache();
+ }
+ else
+ {
+ log_message('error', 'Failed to create object for Memcached Cache; extension not loaded?');
+
+ return FALSE;
+ }
foreach ($this->_memcache_conf as $name => $cache_server)
{
@@ -161,26 +175,42 @@
{
$cache_server['hostname'] = $this->_default_options['default_host'];
}
-
+
if ( ! array_key_exists('port', $cache_server))
{
$cache_server['port'] = $this->_default_options['default_port'];
}
-
+
if ( ! array_key_exists('weight', $cache_server))
{
$cache_server['weight'] = $this->_default_options['default_weight'];
}
-
- $this->_memcached->addServer(
- $cache_server['hostname'], $cache_server['port'], $cache_server['weight']
- );
+
+ if (get_class($this->_memcached) == 'Memcache')
+ {
+ // Third parameter is persistance and defaults to TRUE.
+ $this->_memcached->addServer(
+ $cache_server['hostname'],
+ $cache_server['port'],
+ TRUE,
+ $cache_server['weight']
+ );
+ }
+ else
+ {
+ $this->_memcached->addServer(
+ $cache_server['hostname'],
+ $cache_server['port'],
+ $cache_server['weight']
+ );
+ }
}
+
+ return TRUE;
}
// ------------------------------------------------------------------------
-
/**
* Is supported
*
@@ -189,15 +219,14 @@
*/
public function is_supported()
{
- if ( ! extension_loaded('memcached'))
+ if ( ! extension_loaded('memcached') && ! extension_loaded('memcache'))
{
log_message('error', 'The Memcached Extension must be loaded to use Memcached Cache.');
-
+
return FALSE;
}
-
- $this->_setup_memcached();
- return TRUE;
+
+ return $this->_setup_memcached();
}
// ------------------------------------------------------------------------
diff --git a/system/libraries/Cart.php b/system/libraries/Cart.php
index b2eaa9a..ab5a70c 100644
--- a/system/libraries/Cart.php
+++ b/system/libraries/Cart.php
@@ -99,7 +99,7 @@
$save_cart = FALSE;
if (isset($items['id']))
{
- if ($this->_insert($items) == TRUE)
+ if (($rowid = $this->_insert($items)))
{
$save_cart = TRUE;
}
@@ -110,7 +110,7 @@
{
if (is_array($val) AND isset($val['id']))
{
- if ($this->_insert($val) == TRUE)
+ if ($this->_insert($val))
{
$save_cart = TRUE;
}
@@ -122,7 +122,7 @@
if ($save_cart == TRUE)
{
$this->_save_cart();
- return TRUE;
+ return isset($rowid) ? $rowid : TRUE;
}
return FALSE;
@@ -244,7 +244,7 @@
}
// Woot!
- return TRUE;
+ return $rowid;
}
// --------------------------------------------------------------------
diff --git a/system/libraries/Driver.php b/system/libraries/Driver.php
index c32f2c1..9881c1e 100644
--- a/system/libraries/Driver.php
+++ b/system/libraries/Driver.php
@@ -54,7 +54,7 @@
if ( ! class_exists($child_class))
{
// check application path first
- foreach (array(APPPATH, BASEPATH) as $path)
+ foreach (get_instance()->load->get_package_paths(TRUE) as $path)
{
// loves me some nesting!
foreach (array(ucfirst($driver_name), $driver_name) as $class)
@@ -226,4 +226,4 @@
// END CI_Driver CLASS
/* End of file Driver.php */
-/* Location: ./system/libraries/Driver.php */
+/* Location: ./system/libraries/Driver.php */
\ No newline at end of file
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 03eccea..28a3d17 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -405,12 +405,12 @@
/**
* Add a Header Item
*
- * @access private
+ * @access protected
* @param string
* @param string
* @return void
*/
- private function _set_header($header, $value)
+ protected function _set_header($header, $value)
{
$this->_headers[$header] = $value;
}
@@ -420,11 +420,11 @@
/**
* Convert a String to an Array
*
- * @access private
+ * @access protected
* @param string
* @return array
*/
- private function _str_to_array($email)
+ protected function _str_to_array($email)
{
if ( ! is_array($email))
{
@@ -452,7 +452,7 @@
*/
public function set_alt_message($str = '')
{
- $this->alt_message = ($str == '') ? '' : $str;
+ $this->alt_message = (string) $str;
return $this;
}
@@ -477,12 +477,12 @@
* Set Wordwrap
*
* @access public
- * @param string
+ * @param bool
* @return void
*/
public function set_wordwrap($wordwrap = TRUE)
{
- $this->wordwrap = ($wordwrap === FALSE) ? FALSE : TRUE;
+ $this->wordwrap = (bool) $wordwrap;
return $this;
}
@@ -577,10 +577,10 @@
/**
* Set Message Boundary
*
- * @access private
+ * @access protected
* @return void
*/
- private function _set_boundaries()
+ protected function _set_boundaries()
{
$this->_alt_boundary = "B_ALT_".uniqid(''); // multipart/alternative
$this->_atc_boundary = "B_ATC_".uniqid(''); // attachment boundary
@@ -591,10 +591,10 @@
/**
* Get the Message ID
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_message_id()
+ protected function _get_message_id()
{
$from = $this->_headers['Return-Path'];
$from = str_replace(">", "", $from);
@@ -608,11 +608,11 @@
/**
* Get Mail Protocol
*
- * @access private
+ * @access protected
* @param bool
* @return string
*/
- private function _get_protocol($return = TRUE)
+ protected function _get_protocol($return = TRUE)
{
$this->protocol = strtolower($this->protocol);
$this->protocol = ( ! in_array($this->protocol, $this->_protocols, TRUE)) ? 'mail' : $this->protocol;
@@ -628,11 +628,11 @@
/**
* Get Mail Encoding
*
- * @access private
+ * @access protected
* @param bool
* @return string
*/
- private function _get_encoding($return = TRUE)
+ protected function _get_encoding($return = TRUE)
{
$this->_encoding = ( ! in_array($this->_encoding, $this->_bit_depths)) ? '8bit' : $this->_encoding;
@@ -655,10 +655,10 @@
/**
* Get content type (text/html/attachment)
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_content_type()
+ protected function _get_content_type()
{
if ($this->mailtype == 'html' && count($this->_attach_name) == 0)
{
@@ -683,10 +683,10 @@
/**
* Set RFC 822 Date
*
- * @access private
+ * @access protected
* @return string
*/
- private function _set_date()
+ protected function _set_date()
{
$timezone = date("Z");
$operator = (strncmp($timezone, '-', 1) == 0) ? '-' : '+';
@@ -701,10 +701,10 @@
/**
* Mime message
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_mime_message()
+ protected function _get_mime_message()
{
return "This is a multi-part message in MIME format.".$this->newline."Your email application may not support this format.";
}
@@ -802,10 +802,10 @@
* If the user hasn't specified his own alternative message
* it creates one by stripping the HTML
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_alt_message()
+ protected function _get_alt_message()
{
if ($this->alt_message != "")
{
@@ -941,11 +941,11 @@
/**
* Build final headers
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _build_headers()
+ protected function _build_headers()
{
$this->_set_header('X-Sender', $this->clean_email($this->_headers['From']));
$this->_set_header('X-Mailer', $this->useragent);
@@ -959,10 +959,10 @@
/**
* Write Headers as a string
*
- * @access private
+ * @access protected
* @return void
*/
- private function _write_headers()
+ protected function _write_headers()
{
if ($this->protocol == 'mail')
{
@@ -994,10 +994,10 @@
/**
* Build Final Body and attachments
*
- * @access private
+ * @access protected
* @return void
*/
- private function _build_message()
+ protected function _build_message()
{
if ($this->wordwrap === TRUE AND $this->mailtype != 'html')
{
@@ -1177,12 +1177,12 @@
* Prepares string for Quoted-Printable Content-Transfer-Encoding
* Refer to RFC 2045 http://www.ietf.org/rfc/rfc2045.txt
*
- * @access private
+ * @access protected
* @param string
* @param integer
* @return string
*/
- private function _prep_quoted_printable($str, $charlim = '')
+ protected function _prep_quoted_printable($str, $charlim = '')
{
// Set the character limit
// Don't allow over 76, as that will make servers and MUAs barf
@@ -1275,7 +1275,7 @@
* @param bool // set to TRUE for processing From: headers
* @return str
*/
- private function _prep_q_encoding($str, $from = FALSE)
+ protected function _prep_q_encoding($str, $from = FALSE)
{
$str = str_replace(array("\r", "\n"), array('', ''), $str);
@@ -1440,10 +1440,10 @@
/**
* Unwrap special elements
*
- * @access private
+ * @access protected
* @return void
*/
- private function _unwrap_specials()
+ protected function _unwrap_specials()
{
$this->_finalbody = preg_replace_callback("/\{unwrap\}(.*?)\{\/unwrap\}/si", array($this, '_remove_nl_callback'), $this->_finalbody);
}
@@ -1453,10 +1453,10 @@
/**
* Strip line-breaks via callback
*
- * @access private
+ * @access protected
* @return string
*/
- private function _remove_nl_callback($matches)
+ protected function _remove_nl_callback($matches)
{
if (strpos($matches[1], "\r") !== FALSE OR strpos($matches[1], "\n") !== FALSE)
{
@@ -1471,10 +1471,10 @@
/**
* Spool mail to the mail server
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _spool_email()
+ protected function _spool_email()
{
$this->_unwrap_specials();
@@ -1516,10 +1516,10 @@
/**
* Send using mail()
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_mail()
+ protected function _send_with_mail()
{
if ($this->_safe_mode == TRUE)
{
@@ -1553,10 +1553,10 @@
/**
* Send using Sendmail
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_sendmail()
+ protected function _send_with_sendmail()
{
$fp = @popen($this->mailpath . " -oi -f ".$this->clean_email($this->_headers['From'])." -t", 'w');
@@ -1591,10 +1591,10 @@
/**
* Send using SMTP
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_with_smtp()
+ protected function _send_with_smtp()
{
if ($this->smtp_host == '')
{
@@ -1660,11 +1660,11 @@
/**
* SMTP Connect
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _smtp_connect()
+ protected function _smtp_connect()
{
$this->_smtp_connect = fsockopen($this->smtp_host,
$this->smtp_port,
@@ -1687,12 +1687,12 @@
/**
* Send SMTP command
*
- * @access private
+ * @access protected
* @param string
* @param string
* @return string
*/
- private function _send_command($cmd, $data = '')
+ protected function _send_command($cmd, $data = '')
{
switch ($cmd)
{
@@ -1754,10 +1754,10 @@
/**
* SMTP Authenticate
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _smtp_authenticate()
+ protected function _smtp_authenticate()
{
if ( ! $this->_smtp_auth)
{
@@ -1808,10 +1808,10 @@
/**
* Send SMTP data
*
- * @access private
+ * @access protected
* @return bool
*/
- private function _send_data($data)
+ protected function _send_data($data)
{
if ( ! fwrite($this->_smtp_connect, $data . $this->newline))
{
@@ -1829,10 +1829,10 @@
/**
* Get SMTP data
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_smtp_data()
+ protected function _get_smtp_data()
{
$data = "";
@@ -1854,10 +1854,10 @@
/**
* Get Hostname
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_hostname()
+ protected function _get_hostname()
{
return (isset($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : 'localhost.localdomain';
}
@@ -1867,10 +1867,10 @@
/**
* Get IP
*
- * @access private
+ * @access protected
* @return string
*/
- private function _get_ip()
+ protected function _get_ip()
{
if ($this->_IP !== FALSE)
{
@@ -1933,11 +1933,11 @@
/**
* Set Message
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _set_error_message($msg, $val = '')
+ protected function _set_error_message($msg, $val = '')
{
$CI =& get_instance();
$CI->lang->load('email');
@@ -1957,11 +1957,11 @@
/**
* Mime Types
*
- * @access private
+ * @access protected
* @param string
* @return string
*/
- private function _mime_types($ext = "")
+ protected function _mime_types($ext = "")
{
$mimes = array( 'hqx' => 'application/mac-binhex40',
'cpt' => 'application/mac-compactpro',
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 6f79a55..a34809e 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -26,16 +26,15 @@
*/
class CI_Form_validation {
- var $CI;
- var $_field_data = array();
- var $_config_rules = array();
- var $_error_array = array();
- var $_error_messages = array();
- var $_error_prefix = '<p>';
- var $_error_suffix = '</p>';
- var $error_string = '';
- var $_safe_form_data = FALSE;
-
+ protected $CI;
+ protected $_field_data = array();
+ protected $_config_rules = array();
+ protected $_error_array = array();
+ protected $_error_messages = array();
+ protected $_error_prefix = '<p>';
+ protected $_error_suffix = '</p>';
+ protected $error_string = '';
+ protected $_safe_form_data = FALSE;
/**
* Constructor
@@ -72,7 +71,7 @@
* @param string
* @return void
*/
- function set_rules($field, $label = '', $rules = '')
+ public function set_rules($field, $label = '', $rules = '')
{
// No reason to set rules if we have no POST data
if (count($_POST) == 0)
@@ -163,7 +162,7 @@
* @param string
* @return string
*/
- function set_message($lang, $val = '')
+ public function set_message($lang, $val = '')
{
if ( ! is_array($lang))
{
@@ -187,7 +186,7 @@
* @param string
* @return void
*/
- function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
+ public function set_error_delimiters($prefix = '<p>', $suffix = '</p>')
{
$this->_error_prefix = $prefix;
$this->_error_suffix = $suffix;
@@ -206,7 +205,7 @@
* @param string the field name
* @return void
*/
- function error($field = '', $prefix = '', $suffix = '')
+ public function error($field = '', $prefix = '', $suffix = '')
{
if ( ! isset($this->_field_data[$field]['error']) OR $this->_field_data[$field]['error'] == '')
{
@@ -238,7 +237,7 @@
* @param string
* @return str
*/
- function error_string($prefix = '', $suffix = '')
+ public function error_string($prefix = '', $suffix = '')
{
// No errrors, validation passes!
if (count($this->_error_array) === 0)
@@ -279,7 +278,7 @@
* @access public
* @return bool
*/
- function run($group = '')
+ public function run($group = '')
{
// Do we even have any data to process? Mm?
if (count($_POST) == 0)
@@ -374,7 +373,7 @@
* @param integer
* @return mixed
*/
- function _reduce_array($array, $keys, $i = 0)
+ protected function _reduce_array($array, $keys, $i = 0)
{
if (is_array($array))
{
@@ -406,7 +405,7 @@
* @access private
* @return null
*/
- function _reset_post_array()
+ protected function _reset_post_array()
{
foreach ($this->_field_data as $field => $row)
{
@@ -468,7 +467,7 @@
* @param integer
* @return mixed
*/
- function _execute($row, $rules, $postdata = NULL, $cycles = 0)
+ protected function _execute($row, $rules, $postdata = NULL, $cycles = 0)
{
// If the $_POST data is an array we will run a recursive call
if (is_array($postdata))
@@ -489,7 +488,7 @@
if ( ! in_array('required', $rules) AND is_null($postdata))
{
// Before we bail out, does the rule contain a callback?
- if (preg_match("/(callback_\w+)/", implode(' ', $rules), $match))
+ if (preg_match("/(callback_\w+(\[.*?\])?)/", implode(' ', $rules), $match))
{
$callback = TRUE;
$rules = (array('1' => $match[1]));
@@ -695,7 +694,7 @@
* @param string the field name
* @return string
*/
- function _translate_fieldname($fieldname)
+ protected function _translate_fieldname($fieldname)
{
// Do we need to translate the field name?
// We look for the prefix lang: to determine this
@@ -727,7 +726,7 @@
* @param string
* @return void
*/
- function set_value($field = '', $default = '')
+ public function set_value($field = '', $default = '')
{
if ( ! isset($this->_field_data[$field]))
{
@@ -757,7 +756,7 @@
* @param string
* @return string
*/
- function set_select($field = '', $value = '', $default = FALSE)
+ public function set_select($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -801,7 +800,7 @@
* @param string
* @return string
*/
- function set_radio($field = '', $value = '', $default = FALSE)
+ public function set_radio($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -845,7 +844,7 @@
* @param string
* @return string
*/
- function set_checkbox($field = '', $value = '', $default = FALSE)
+ public function set_checkbox($field = '', $value = '', $default = FALSE)
{
if ( ! isset($this->_field_data[$field]) OR ! isset($this->_field_data[$field]['postdata']))
{
@@ -885,7 +884,7 @@
* @param string
* @return bool
*/
- function required($str)
+ public function required($str)
{
if ( ! is_array($str))
{
@@ -907,7 +906,7 @@
* @param regex
* @return bool
*/
- function regex_match($str, $regex)
+ public function regex_match($str, $regex)
{
if ( ! preg_match($regex, $str))
{
@@ -927,7 +926,7 @@
* @param field
* @return bool
*/
- function matches($str, $field)
+ public function matches($str, $field)
{
if ( ! isset($_POST[$field]))
{
@@ -938,6 +937,24 @@
return ($str !== $field) ? FALSE : TRUE;
}
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Match one field to another
+ *
+ * @access public
+ * @param string
+ * @param field
+ * @return bool
+ */
+ public function is_unique($str, $field)
+ {
+ list($table, $field)=explode('.', $field);
+ $query = $this->CI->db->limit(1)->get_where($table, array($field => $str));
+
+ return $query->num_rows() === 0;
+ }
// --------------------------------------------------------------------
@@ -949,7 +966,7 @@
* @param value
* @return bool
*/
- function min_length($str, $val)
+ public function min_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -974,7 +991,7 @@
* @param value
* @return bool
*/
- function max_length($str, $val)
+ public function max_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -999,7 +1016,7 @@
* @param value
* @return bool
*/
- function exact_length($str, $val)
+ public function exact_length($str, $val)
{
if (preg_match("/[^0-9]/", $val))
{
@@ -1023,7 +1040,7 @@
* @param string
* @return bool
*/
- function valid_email($str)
+ public function valid_email($str)
{
return ( ! preg_match("/^([a-z0-9\+_\-]+)(\.[a-z0-9\+_\-]+)*@([a-z0-9\-]+\.)+[a-z]{2,6}$/ix", $str)) ? FALSE : TRUE;
}
@@ -1037,7 +1054,7 @@
* @param string
* @return bool
*/
- function valid_emails($str)
+ public function valid_emails($str)
{
if (strpos($str, ',') === FALSE)
{
@@ -1064,7 +1081,7 @@
* @param string
* @return string
*/
- function valid_ip($ip)
+ public function valid_ip($ip)
{
return $this->CI->input->valid_ip($ip);
}
@@ -1078,7 +1095,7 @@
* @param string
* @return bool
*/
- function alpha($str)
+ public function alpha($str)
{
return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1092,7 +1109,7 @@
* @param string
* @return bool
*/
- function alpha_numeric($str)
+ public function alpha_numeric($str)
{
return ( ! preg_match("/^([a-z0-9])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1106,7 +1123,7 @@
* @param string
* @return bool
*/
- function alpha_dash($str)
+ public function alpha_dash($str)
{
return ( ! preg_match("/^([-a-z0-9_-])+$/i", $str)) ? FALSE : TRUE;
}
@@ -1120,7 +1137,7 @@
* @param string
* @return bool
*/
- function numeric($str)
+ public function numeric($str)
{
return (bool)preg_match( '/^[\-+]?[0-9]*\.?[0-9]+$/', $str);
@@ -1135,7 +1152,7 @@
* @param string
* @return bool
*/
- function is_numeric($str)
+ public function is_numeric($str)
{
return ( ! is_numeric($str)) ? FALSE : TRUE;
}
@@ -1149,7 +1166,7 @@
* @param string
* @return bool
*/
- function integer($str)
+ public function integer($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+$/', $str);
}
@@ -1163,7 +1180,7 @@
* @param string
* @return bool
*/
- function decimal($str)
+ public function decimal($str)
{
return (bool) preg_match('/^[\-+]?[0-9]+\.[0-9]+$/', $str);
}
@@ -1177,7 +1194,7 @@
* @param string
* @return bool
*/
- function greater_than($str, $min)
+ public function greater_than($str, $min)
{
if ( ! is_numeric($str))
{
@@ -1195,7 +1212,7 @@
* @param string
* @return bool
*/
- function less_than($str, $max)
+ public function less_than($str, $max)
{
if ( ! is_numeric($str))
{
@@ -1213,7 +1230,7 @@
* @param string
* @return bool
*/
- function is_natural($str)
+ public function is_natural($str)
{
return (bool) preg_match( '/^[0-9]+$/', $str);
}
@@ -1227,7 +1244,7 @@
* @param string
* @return bool
*/
- function is_natural_no_zero($str)
+ public function is_natural_no_zero($str)
{
if ( ! preg_match( '/^[0-9]+$/', $str))
{
@@ -1254,7 +1271,7 @@
* @param string
* @return bool
*/
- function valid_base64($str)
+ public function valid_base64($str)
{
return (bool) ! preg_match('/[^a-zA-Z0-9\/\+=]/', $str);
}
@@ -1271,7 +1288,7 @@
* @param string
* @return string
*/
- function prep_for_form($data = '')
+ public function prep_for_form($data = '')
{
if (is_array($data))
{
@@ -1300,7 +1317,7 @@
* @param string
* @return string
*/
- function prep_url($str = '')
+ public function prep_url($str = '')
{
if ($str == 'http://' OR $str == '')
{
@@ -1324,7 +1341,7 @@
* @param string
* @return string
*/
- function strip_image_tags($str)
+ public function strip_image_tags($str)
{
return $this->CI->input->strip_image_tags($str);
}
@@ -1338,7 +1355,7 @@
* @param string
* @return string
*/
- function xss_clean($str)
+ public function xss_clean($str)
{
return $this->CI->security->xss_clean($str);
}
@@ -1352,7 +1369,7 @@
* @param string
* @return string
*/
- function encode_php_tags($str)
+ public function encode_php_tags($str)
{
return str_replace(array('<?php', '<?PHP', '<?', '?>'), array('<?php', '<?PHP', '<?', '?>'), $str);
}
diff --git a/system/libraries/Image_lib.php b/system/libraries/Image_lib.php
index 8902f52..a8a0387 100644
--- a/system/libraries/Image_lib.php
+++ b/system/libraries/Image_lib.php
@@ -1334,7 +1334,7 @@
return FALSE;
}
- $vals = @getimagesize($path);
+ $vals = getimagesize($path);
$types = array(1 => 'gif', 2 => 'jpeg', 3 => 'png');
diff --git a/system/libraries/Log.php b/system/libraries/Log.php
index 9f1db76..bf10d47 100644
--- a/system/libraries/Log.php
+++ b/system/libraries/Log.php
@@ -27,10 +27,12 @@
class CI_Log {
protected $_log_path;
- protected $_threshold = 1;
- protected $_date_fmt = 'Y-m-d H:i:s';
- protected $_enabled = TRUE;
- protected $_levels = array('ERROR' => '1', 'DEBUG' => '2', 'INFO' => '3', 'ALL' => '4');
+ protected $_threshold = 1;
+ protected $_threshold_max = 0;
+ protected $_threshold_array = array();
+ protected $_date_fmt = 'Y-m-d H:i:s';
+ protected $_enabled = TRUE;
+ protected $_levels = array('ERROR' => '1', 'DEBUG' => '2', 'INFO' => '3', 'ALL' => '4');
/**
* Constructor
@@ -50,6 +52,11 @@
{
$this->_threshold = $config['log_threshold'];
}
+ elseif (is_array($config['log_threshold']))
+ {
+ $this->_threshold = $this->_threshold_max;
+ $this->_threshold_array = array_flip($config['log_threshold']);
+ }
if ($config['log_date_format'] != '')
{
@@ -80,9 +87,13 @@
if ( ! isset($this->_levels[$level]) OR ($this->_levels[$level] > $this->_threshold))
{
- return FALSE;
+ if (empty($this->_threshold_array) OR ! isset($this->_threshold_array[$this->_levels[$level]]))
+ {
+ return FALSE;
+ }
}
+
$filepath = $this->_log_path.'log-'.date('Y-m-d').'.php';
$message = '';
diff --git a/system/libraries/Migration.php b/system/libraries/Migration.php
new file mode 100644
index 0000000..3943ec1
--- /dev/null
+++ b/system/libraries/Migration.php
@@ -0,0 +1,338 @@
+<?php defined('BASEPATH') OR exit('No direct script access allowed');
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.1.6 or newer
+ *
+ * @package CodeIgniter
+ * @author EllisLab Dev Team
+ * @copyright Copyright (c) 2006 - 2011, EllisLab, Inc.
+ * @license http://codeigniter.com/user_guide/license.html
+ * @link http://codeigniter.com
+ * @since Version 1.0
+ * @filesource
+ */
+
+// ------------------------------------------------------------------------
+
+/**
+ * Migration Class
+ *
+ * All migrations should implement this, forces up() and down() and gives
+ * access to the CI super-global.
+ *
+ * @package CodeIgniter
+ * @subpackage Libraries
+ * @category Libraries
+ * @author Reactor Engineers
+ * @link
+ */
+class CI_Migration {
+
+ protected $_migration_enabled = FALSE;
+ protected $_migration_path = NULL;
+ protected $_migration_version = 0;
+
+ protected $_error_string = '';
+
+ public function __construct($config = array())
+ {
+ # Only run this constructor on main library load
+ if (get_parent_class($this) !== FALSE)
+ {
+ return;
+ }
+
+ foreach ($config as $key => $val)
+ {
+ $this->{'_' . $key} = $val;
+ }
+
+ log_message('debug', 'Migrations class initialized');
+
+ // Are they trying to use migrations while it is disabled?
+ if ($this->_migration_enabled !== TRUE)
+ {
+ show_error('Migrations has been loaded but is disabled or set up incorrectly.');
+ }
+
+ // If not set, set it
+ $this->_migration_path == '' OR $this->_migration_path = APPPATH . 'migrations/';
+
+ // Add trailing slash if not set
+ $this->_migration_path = rtrim($this->_migration_path, '/').'/';
+
+ // Load migration language
+ $this->lang->load('migration');
+
+ // They'll probably be using dbforge
+ $this->load->dbforge();
+
+ // If the migrations table is missing, make it
+ if ( ! $this->db->table_exists('migrations'))
+ {
+ $this->dbforge->add_field(array(
+ 'version' => array('type' => 'INT', 'constraint' => 3),
+ ));
+
+ $this->dbforge->create_table('migrations', TRUE);
+
+ $this->db->insert('migrations', array('version' => 0));
+ }
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Migrate to a schema version
+ *
+ * Calls each migration step required to get to the schema version of
+ * choice
+ *
+ * @access public
+ * @param $version integer Target schema version
+ * @return mixed TRUE if already latest, FALSE if failed, int if upgraded
+ */
+ public function version($target_version)
+ {
+ $start = $current_version = $this->_get_version();
+ $stop = $target_version;
+
+ if ($target_version > $current_version)
+ {
+ // Moving Up
+ ++$start;
+ ++$stop;
+ $step = 1;
+ }
+
+ else
+ {
+ // Moving Down
+ $step = -1;
+ }
+
+ $method = $step === 1 ? 'up' : 'down';
+ $migrations = array();
+
+ // We now prepare to actually DO the migrations
+ // But first let's make sure that everything is the way it should be
+ for ($i = $start; $i != $stop; $i += $step)
+ {
+ $f = glob(sprintf($this->_migration_path . '%03d_*.php', $i));
+
+ // Only one migration per step is permitted
+ if (count($f) > 1)
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $i);
+ return FALSE;
+ }
+
+ // Migration step not found
+ if (count($f) == 0)
+ {
+ // If trying to migrate up to a version greater than the last
+ // existing one, migrate to the last one.
+ if ($step == 1)
+ {
+ break;
+ }
+
+ // If trying to migrate down but we're missing a step,
+ // something must definitely be wrong.
+ $this->_error_string = sprintf($this->lang->line('migration_not_found'), $i);
+ return FALSE;
+ }
+
+ $file = basename($f[0]);
+ $name = basename($f[0], '.php');
+
+ // Filename validations
+ if (preg_match('/^\d{3}_(\w+)$/', $name, $match))
+ {
+ $match[1] = strtolower($match[1]);
+
+ // Cannot repeat a migration at different steps
+ if (in_array($match[1], $migrations))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_multiple_version'), $match[1]);
+ return FALSE;
+ }
+
+ include $f[0];
+ $class = 'Migration_' . ucfirst($match[1]);
+
+ if ( ! class_exists($class))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_class_doesnt_exist'), $class);
+ return FALSE;
+ }
+
+ if ( ! is_callable(array($class, $method)))
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_missing_'.$method.'_method'), $class);
+ return FALSE;
+ }
+
+ $migrations[] = $match[1];
+ }
+ else
+ {
+ $this->_error_string = sprintf($this->lang->line('migration_invalid_filename'), $file);
+ return FALSE;
+ }
+ }
+
+ log_message('debug', 'Current migration: ' . $current_version);
+
+ $version = $i + ($step == 1 ? -1 : 0);
+
+ // If there is nothing to do so quit
+ if ($migrations === array())
+ {
+ return TRUE;
+ }
+
+ log_message('debug', 'Migrating from ' . $method . ' to version ' . $version);
+
+ // Loop through the migrations
+ foreach ($migrations AS $migration)
+ {
+ // Run the migration class
+ $class = 'Migration_' . ucfirst(strtolower($migration));
+ call_user_func(array(new $class, $method));
+
+ $current_version += $step;
+ $this->_update_version($current_version);
+ }
+
+ log_message('debug', 'Finished migrating to '.$current_version);
+
+ return $current_version;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the latest migration
+ *
+ * @access public
+ * @return mixed true if already latest, false if failed, int if upgraded
+ */
+ public function latest()
+ {
+ if ( ! $migrations = $this->find_migrations())
+ {
+ $this->_error_string = $this->line->lang('migration_none_found');
+ return false;
+ }
+
+ $last_migration = basename(end($migrations));
+
+ // Calculate the last migration step from existing migration
+ // filenames and procceed to the standard version migration
+ return $this->version((int) substr($last_migration, 0, 3));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the migration version set in config
+ *
+ * @access public
+ * @return mixed true if already current, false if failed, int if upgraded
+ */
+ public function current()
+ {
+ return $this->version($this->_migration_version);
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Error string
+ *
+ * @access public
+ * @return string Error message returned as a string
+ */
+ public function error_string()
+ {
+ return $this->_error_string;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Set's the schema to the latest migration
+ *
+ * @access protected
+ * @return mixed true if already latest, false if failed, int if upgraded
+ */
+ protected function find_migrations()
+ {
+ // Load all *_*.php files in the migrations path
+ $files = glob($this->_migration_path . '*_*.php');
+ $file_count = count($files);
+
+ for ($i = 0; $i < $file_count; $i++)
+ {
+ // Mark wrongly formatted files as false for later filtering
+ $name = basename($files[$i], '.php');
+ if ( ! preg_match('/^\d{3}_(\w+)$/', $name))
+ {
+ $files[$i] = FALSE;
+ }
+ }
+
+ sort($files);
+
+ return $files;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Retrieves current schema version
+ *
+ * @access protected
+ * @return integer Current Migration
+ */
+ protected function _get_version()
+ {
+ $row = $this->db->get('migrations')->row();
+ return $row ? $row->version : 0;
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Stores the current schema version
+ *
+ * @access protected
+ * @param $migrations integer Migration reached
+ * @return void Outputs a report of the migration
+ */
+ protected function _update_version($migrations)
+ {
+ return $this->db->update('migrations', array(
+ 'version' => $migrations
+ ));
+ }
+
+ // --------------------------------------------------------------------
+
+ /**
+ * Enable the use of CI super-global
+ *
+ * @access public
+ * @param $var
+ * @return mixed
+ */
+ public function __get($var)
+ {
+ return get_instance()->$var;
+ }
+}
+
+/* End of file Migration.php */
+/* Location: ./system/libraries/Migration.php */
\ No newline at end of file
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index 082a5ee..330acce 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -493,7 +493,7 @@
*
* @return string
*/
- private function _compile_session_data()
+ protected function _compile_session_data()
{
if ( ! isset($this->CI->session))
{
@@ -555,4 +555,4 @@
// END CI_Profiler class
/* End of file Profiler.php */
-/* Location: ./system/libraries/Profiler.php */
\ No newline at end of file
+/* Location: ./system/libraries/Profiler.php */
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 3177424..8f324de 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -30,6 +30,7 @@
public $max_width = 0;
public $max_height = 0;
public $max_filename = 0;
+ public $max_filename_increment = 100;
public $allowed_types = "";
public $file_temp = "";
public $file_name = "";
@@ -80,31 +81,32 @@
public function initialize($config = array())
{
$defaults = array(
- 'max_size' => 0,
- 'max_width' => 0,
- 'max_height' => 0,
- 'max_filename' => 0,
- 'allowed_types' => "",
- 'file_temp' => "",
- 'file_name' => "",
- 'orig_name' => "",
- 'file_type' => "",
- 'file_size' => "",
- 'file_ext' => "",
- 'upload_path' => "",
- 'overwrite' => FALSE,
- 'encrypt_name' => FALSE,
- 'is_image' => FALSE,
- 'image_width' => '',
- 'image_height' => '',
- 'image_type' => '',
- 'image_size_str' => '',
- 'error_msg' => array(),
- 'mimes' => array(),
- 'remove_spaces' => TRUE,
- 'xss_clean' => FALSE,
- 'temp_prefix' => "temp_file_",
- 'client_name' => ''
+ 'max_size' => 0,
+ 'max_width' => 0,
+ 'max_height' => 0,
+ 'max_filename' => 0,
+ 'max_filename_increment' => 100,
+ 'allowed_types' => "",
+ 'file_temp' => "",
+ 'file_name' => "",
+ 'orig_name' => "",
+ 'file_type' => "",
+ 'file_size' => "",
+ 'file_ext' => "",
+ 'upload_path' => "",
+ 'overwrite' => FALSE,
+ 'encrypt_name' => FALSE,
+ 'is_image' => FALSE,
+ 'image_width' => '',
+ 'image_height' => '',
+ 'image_type' => '',
+ 'image_size_str' => '',
+ 'error_msg' => array(),
+ 'mimes' => array(),
+ 'remove_spaces' => TRUE,
+ 'xss_clean' => FALSE,
+ 'temp_prefix' => "temp_file_",
+ 'client_name' => ''
);
@@ -402,7 +404,7 @@
$filename = str_replace($this->file_ext, '', $filename);
$new_filename = '';
- for ($i = 1; $i < 100; $i++)
+ for ($i = 1; $i < $this->max_filename_increment; $i++)
{
if ( ! file_exists($path.$filename.$i.$this->file_ext))
{
diff --git a/system/libraries/User_agent.php b/system/libraries/User_agent.php
index 016102a..0b77a7d 100644
--- a/system/libraries/User_agent.php
+++ b/system/libraries/User_agent.php
@@ -142,7 +142,7 @@
{
$this->_set_platform();
- foreach (array('_set_browser', '_set_robot', '_set_mobile') as $function)
+ foreach (array('_set_robot', '_set_browser', '_set_mobile') as $function)
{
if ($this->$function() === TRUE)
{
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index c52a33e..c030ce7 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -59,6 +59,65 @@
<p>The <img src="images/reactor-bullet.png" width="16" height="16" alt="Reactor Marker" /> indicates items that were contributed to CodeIgniter via CodeIgniter Reactor.</p>
+<h2>Version 2.1.0 (planned)</h2>
+<p>Release Date: Not Released</p>
+
+<ul>
+ <li>General Changes
+ <ul>
+ <li class="reactor">Callback validation rules can now accept parameters like any other validation rule.</li>
+ <li class="reactor">Ability to log certain error types, not all under a threshold.</li>
+ <li class="reactor">Added html_escape() to <a href="general/common_functions.html">Common functions</a> to escape HTML output for preventing XSS.</li>
+ </ul>
+ </li>
+ <li>Helpers
+ <ul>
+ <li class="reactor">Added <samp>increment_string()</samp> to <a href="helpers/string_helper.html">String Helper</a> to turn "foo" into "foo-1" or "foo-1" into "foo-2".</li>
+ <li>Altered form helper - made action on form_open_multipart helper function call optional. Fixes (#65)</li>
+ <li><samp>url_title()</samp> will now trim extra dashes from beginning and end.</li>
+ </ul>
+ </li>
+ <li>Database
+ <ul>
+ <li class="reactor">Added a <a href="http://www.cubrid.org/" target="_blank">CUBRID</a> driver to the <a href="database/index.html">Database Driver</a>. Thanks to the CUBRID team for supplying this patch.</li>
+ <li class="reactor">Typecast limit and offset in the <a href="database/queries.html">Database Driver</a> to integers to avoid possible injection.</li>
+ <li class="reactor">
+ Added additional option 'none' for the optional third argument for <kbd>$this->db->like()</kbd> in the <a href="database/active_record.html">Database Driver</a>.
+ </li>
+ </ul>
+ </li>
+ <li>Libraries
+ <ul>
+ <li class="reactor">Changed <kbd>$this->cart->insert()</kbd> in the <a href="libraries/cart.html">Cart Library</a> to return the Row ID if a single item was inserted successfully.</li>
+ <li class="reactor">Added support to set an optional parameter in your callback rules of validation using the <a href="libraries/form_validation.html">Form Validation Library</a>.</li>
+ <li class="reactor">Added a <a href="libraries/migration.html">Migration Library</a> to assist with applying incremental updates to your database schema.</li>
+ <li class="reactor">Driver children can be located in any package path.</li>
+ <li class="reactor">Added max_filename_increment config setting for Upload library.</li>
+ <li><samp>CI_Loader::_ci_autoloader()</samp> is now a protected method.</li>
+ <li class="reactor">Added <kbd>is_unique</kbd> to the <a href="libraries/form_validation.html">Form Validation library</a>.</li>
+ </ul>
+ </li>
+ <li>Core
+ <ul>
+ <li class="reactor">Changed private functions in CI_URI to protected so MY_URI can override them.</li>
+ </ul>
+ </li>
+</ul>
+
+<h3>Bug fixes for 2.1.0</h3>
+<ul>
+ <li class="reactor">Fixed #378 Robots identified as regular browsers by the User Agent class.</li>
+ <li class="reactor">If a config class was loaded first then a library with the same name is loaded, the config would be ignored.</li>
+ <li class="reactor">Fixed a bug (Reactor #19) where 1) the 404_override route was being ignored in some cases, and 2) auto-loaded libraries were not available to the 404_override controller when a controller existed but the requested method did not.</li>
+ <li class="rector">Fixed a bug (Reactor #89) where MySQL export would fail if the table had hyphens or other non alphanumeric/underscore characters.</li>
+ <li class="reactor">Fixed a bug (#200) where MySQL queries would be malformed after calling <samp>count_all()</samp> then <samp>db->get()</samp></li>
+ <li>Fixed a bug (#181) where a mis-spelling was in the form validation language file.</li>
+ <li>Fixed a bug (#160) - Removed unneeded array copy in the file cache driver.</li>
+ <li>Fixed a bug (#150) - <samp>field_data()</samp> now correctly returns column length.</li>
+ <li>Fixed a bug (#8) - <samp>load_class()</samp> now looks for core classes in <samp>APPPATH</samp> first, allowing them to be replaced.</li>
+ <li>Fixed a bug (#24) - ODBC database driver called incorrect parent in __construct().</li>
+</ul>
+
<h2>Version 2.0.3</h2>
<p>Release Date: August 20, 2011</p>
@@ -67,6 +126,7 @@
<ul>
<li>An improvement was made to the MySQL and MySQLi drivers to prevent exposing a potential vector for SQL injection on sites using multi-byte character sets in the database client connection. <p>An incompatibility in PHP versions < 5.2.3 and MySQL < 5.0.7 with <em>mysql_set_charset()</em> creates a situation where using multi-byte character sets on these environments may potentially expose a SQL injection attack vector. Latin-1, UTF-8, and other "low ASCII" character sets are unaffected on all environments.</p> <p class="critical">If you are running or considering running a multi-byte character set for your database connection, please pay close attention to the server environment you are deploying on to ensure you are not vulnerable.</p></li>
</ul>
+ </li>
<li>General Changes
<ul>
<li>Fixed a bug where there was a misspelling within a code comment in the index.php file.</li>
@@ -75,22 +135,29 @@
<li>Visual updates to the welcome_message view file and default error templates. Thanks to <a href="https://bitbucket.org/danijelb">danijelb</a> for the pull request.</li>
<li class="reactor">Added <samp>insert_batch()</samp> function to the PostgreSQL database driver. Thanks to epallerols for the patch.</li>
<li class="reactor">Added "application/x-csv" to mimes.php.</li>
+ <li class="reactor">Added CSRF protection URI whitelisting.</li>
<li>Fixed a bug where <a href="libraries/email.html">Email library</a> attachments with a "." in the name would using invalid MIME-types.</li>
+ <li>Added support for pem,p10,p12,p7a,p7c,p7m,p7r,p7s,crt,crl,der,kdb,rsa,cer,sst,csr Certs to mimes.php.</li>
+ <li>Added support pgp,gpg to mimes.php.</li>
+ <li>Added support 3gp, 3g2, mp4, wmv, f4v, vlc Video files to mimes.php.</li>
+ <li>Added support m4a, aac, m4u, xspf, au, ac3, flac, ogg Audio files to mimes.php.</li>
+
</ul>
</li>
<li>Helpers
<ul>
<li>Added an optional third parameter to <samp>heading()</samp> which allows adding html attributes to the rendered heading tag.</li>
+ <li class="reactor"><kbd>form_open()</kbd> now only adds a hidden (Cross-site Reference Forgery) protection field when the form's action is internal and is set to the post method. (Reactor #165)</li>
+ <li class="reactor">Re-worked <samp>plural()</samp> and <samp>singular()</samp> functions in the <a href="helpers/inflector_helper.html">Inflector helper</a> to support considerably more words.</li>
</ul>
</li>
<li>Libraries
<ul>
<li>Altered Session to use a longer match against the user_agent string. See upgrade notes if using database sessions.</li>
- <li class="reactor">Added <kbd>is_unique</kbd> to the <a href="libraries/form_validation.html">Form Validation library</a>.</li>
<li class="reactor">Added <kbd>$this->db->set_dbprefix()</kbd> to the <a href="database/queries.html">Database Driver</a>.</li>
<li class="reactor">Changed <kbd>$this->cart->insert()</kbd> in the <a href="libraries/cart.html">Cart Library</a> to return the Row ID if a single item was inserted successfully.</li>
<li class="reactor">Added <kbd>$this->load->get_var()</kbd> to the <a href="libraries/loader.html">Loader library</a> to retrieve global vars set with <kbd>$this->load->view()</kbd> and <kbd>$this->load->vars()</kbd>.</li>
- <li>Changed <kbd>$this->db->having()</kbd> to insert quotes using escape() rather than escape_str().</li>
+ <li class="reactor">Changed <kbd>$this->db->having()</kbd> to insert quotes using escape() rather than escape_str().</li>
</ul>
</li>
</ul>
diff --git a/user_guide/database/active_record.html b/user_guide/database/active_record.html
index 3f44fcd..92d9614 100644
--- a/user_guide/database/active_record.html
+++ b/user_guide/database/active_record.html
@@ -334,6 +334,13 @@
$this->db->like('title', 'match', 'both'); <br />
// Produces: WHERE title LIKE '%match%' </code> </li>
+If you do not want to use the wildcard (%) you can pass to the optional third argument the option 'none'.
+
+<code>
+ $this->db->like('title', 'match', 'none'); <br />
+// Produces: WHERE title LIKE 'match'
+</code>
+
<li><strong>Associative array method:</strong>
<code>
@@ -525,7 +532,7 @@
<p>Generates an insert string based on the data you supply, and runs the query. You can either pass an
<strong>array</strong> or an <strong>object</strong> to the function. Here is an example using an array:</p>
-<code>
+<code>
$data = array(<br/>
array(<br />
'title' => 'My title' ,<br />
@@ -537,7 +544,7 @@
'name' => 'Another Name' ,<br />
'date' => 'Another date'<br />
)<br/>
-);<br />
+);<br />
<br />
$this->db->update_batch('mytable', $data);
<br /><br />
diff --git a/user_guide/database/configuration.html b/user_guide/database/configuration.html
index bbdd0a3..f06b08f 100644
--- a/user_guide/database/configuration.html
+++ b/user_guide/database/configuration.html
@@ -132,8 +132,8 @@
<li><strong>cache_on</strong> - TRUE/FALSE (boolean) - Whether database query caching is enabled, see also <a href="caching.html">Database Caching Class</a>.</li>
<li><strong>cachedir</strong> - The absolute server path to your database query cache directory.</li>
<li><strong>char_set</strong> - The character set used in communicating with the database.</li>
-<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7. There is an incompatibility in PHP with mysql_real_escape_string() which can make your site vulnerable to SQL injection if you are using a multi-byte character set and are running versions lower than these. Sites using Latin-1 or UTF-8 database character set and collation are unaffected.</p></li>
-<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
+<li><strong>dbcollat</strong> - The character collation used in communicating with the database. <p class="important"><strong>Note:</strong> For MySQL and MySQLi databases, this setting is only used as a backup if your server is running PHP < 5.2.3 or MySQL < 5.0.7 (and in table creation queries made with DB Forge). There is an incompatibility in PHP with mysql_real_escape_string() which can make your site vulnerable to SQL injection if you are using a multi-byte character set and are running versions lower than these. Sites using Latin-1 or UTF-8 database character set and collation are unaffected.</p></li>
+<li><strong>swap_pre</strong> - A default table prefix that should be swapped with <var>dbprefix</var>. This is useful for distributed applications where you might run manually written queries, and need the prefix to still be customizable by the end user.</li>
<li><strong>autoinit</strong> - Whether or not to automatically connect to the database when the library loads. If set to false, the connection will take place prior to executing the first query.</li>
<li><strong>stricton</strong> - TRUE/FALSE (boolean) - Whether to force "Strict Mode" connections, good for ensuring strict SQL while developing an application.</li>
<li><strong>port</strong> - The database port number. To use this value you have to add a line to the database config array.<code>$db['default']['port'] = 5432;</code>
diff --git a/user_guide/general/common_functions.html b/user_guide/general/common_functions.html
index 6545775..7cff632 100644
--- a/user_guide/general/common_functions.html
+++ b/user_guide/general/common_functions.html
@@ -104,6 +104,8 @@
<p>This function prevents inserting null characters between ascii characters, like Java\0script.</p>
+<h2>html_escape(<var>$mixed</var>)</h2>
+<p>This function provides short cut for htmlspecialchars() function. It accepts string and array. To prevent Cross Site Scripting (XSS), it is very useful.</p>
</div>
diff --git a/user_guide/helpers/date_helper.html b/user_guide/helpers/date_helper.html
index f930ea3..5b00e25 100644
--- a/user_guide/helpers/date_helper.html
+++ b/user_guide/helpers/date_helper.html
@@ -234,6 +234,20 @@
+<h2>nice_date()</h2>
+
+<p>This function can take a number poorly-formed date formats and convert them into something useful. It also accepts well-formed dates.</p>
+<p>The function will return a Unix timestamp by default. You can, optionally, pass a format string (the same type as the PHP date function accepts) as the second parameter. Example:</p>
+
+<code>$bad_time = 199605<br />
+<br />
+// Should Produce: 1996-05-01<br />
+$better_time = nice_date($bad_time,'Y-m-d');<br />
+<br />
+$bad_time = 9-11-2001<br />
+// Should Produce: 2001-09-11<br />
+$better_time = nice_date($human,'Y-m-d');</code>
+
<h2>timespan()</h2>
diff --git a/user_guide/helpers/string_helper.html b/user_guide/helpers/string_helper.html
index a3dc165..3141240 100644
--- a/user_guide/helpers/string_helper.html
+++ b/user_guide/helpers/string_helper.html
@@ -90,6 +90,17 @@
<code>echo random_string('alnum', 16);</code>
+<h2>increment_string()</h2>
+
+<p>Increments a string by appending a number to it or increasing the number. Useful for creating "copies" or a file or duplicating database content which has unique titles or slugs.</p>
+
+<p>Usage example:</p>
+
+<code>echo increment_string('file', '_'); // "file_1"<br/>
+echo increment_string('file', '-', 2); // "file-2"<br/>
+echo increment_string('file-4'); // "file-5"<br/></code>
+
+
<h2>alternator()</h2>
<p>Allows two or more items to be alternated between, when cycling through a loop. Example:</p>
diff --git a/user_guide/images/appflowchart.gif b/user_guide/images/appflowchart.gif
index 422332c..4328e48 100644
--- a/user_guide/images/appflowchart.gif
+++ b/user_guide/images/appflowchart.gif
Binary files differ
diff --git a/user_guide/installation/index.html b/user_guide/installation/index.html
index 5e8ab38..84338e2 100644
--- a/user_guide/installation/index.html
+++ b/user_guide/installation/index.html
@@ -72,7 +72,9 @@
<p>For the best security, both the <dfn>system</dfn> and any <dfn>application</dfn> folders should be placed above web root so that they are not directly accessible via a browser. By default, .htaccess files are included in each folder to help prevent direct access, but it is best to remove them from public access entirely in case the web server configuration changes or doesn't abide by the .htaccess.</p>
-<p>After moving them, open your main <kdb>index.php</kbd> file and set the <samp>$system_folder</samp> and <samp>$application_folder</samp> variables, preferably with a full path, e.g. '<dfn>/www/MyUser/system</dfn>'.</p>
+<p>If you would like to keep your views public it is also possible to move the <dfn>views</dfn> folder out of your application folder.</p>
+
+<p>After moving them, open your main <kdb>index.php</kbd> file and set the <samp>$system_folder</samp>, <samp>$application_folder</samp> and <samp>$view_folder</samp> variables, preferably with a full path, e.g. '<dfn>/www/MyUser/system</dfn>'.</p>
<p>
One additional measure to take in production environments is to disable
diff --git a/user_guide/installation/upgrade_203.html b/user_guide/installation/upgrade_203.html
index 1d37a05..0489983 100644
--- a/user_guide/installation/upgrade_203.html
+++ b/user_guide/installation/upgrade_203.html
@@ -81,7 +81,7 @@
<h2>Step 5: Remove APPPATH.'third_party' from autoload.php</h2>
-<p>Open application/autoload.php, and look for the following:</p>
+<p>Open application/config/autoload.php, and look for the following:</p>
<code>$autoload['packages'] = array(APPPATH.'third_party');</code>
diff --git a/user_guide/libraries/cart.html b/user_guide/libraries/cart.html
index 3471eeb..f1e8473 100644
--- a/user_guide/libraries/cart.html
+++ b/user_guide/libraries/cart.html
@@ -61,7 +61,7 @@
<p>The Cart Class permits items to be added to a session that stays active while a user is browsing your site.
These items can be retrieved and displayed in a standard "shopping cart" format, allowing the user to update the quantity or remove items from the cart.</p>
-<p>Please note that the Cart Class ONLY provides the core "cart" functionality. It does not provide shipping, credit card authorization, or other processing components.</p>
+<p>Please note that the Cart Class ONLY provides the core "cart" functionality. It does not provide shipping, credit card authorization, or other processing components.</p>
<h2>Initializing the Shopping Cart Class</h2>
@@ -106,20 +106,20 @@
<li><strong>qty</strong> - The quantity being purchased.
<li><strong>price</strong> - The price of the item.
<li><strong>name</strong> - The name of the item.
-<li><strong>options</strong> - Any additional attributes that are needed to identify the product. These must be passed via an array.
+<li><strong>options</strong> - Any additional attributes that are needed to identify the product. These must be passed via an array.
</ul>
<p>In addition to the five indexes above, there are two reserved words: <dfn>rowid</dfn> and <dfn>subtotal</dfn>. These are used internally by the Cart class, so
please do NOT use those words as index names when inserting data into the cart.</p>
-<p>Your array may contain additional data. Anything you include in your array will be stored in the session. However, it is best to standardize your data among
-all your products in order to make displaying the information in a table easier.</p>
+<p>Your array may contain additional data. Anything you include in your array will be stored in the session. However, it is best to standardize your data among all your products in order to make displaying the information in a table easier.</p>
+
+<p>The insert() method will return the $rowid if you successfully insert a single item.</p>
<h2>Adding Multiple Items to The Cart</h2>
-<p>By using a multi-dimensional array, as shown below, it is possible to add multiple products to the cart in one action. This is useful in cases where you wish to allow
-people to select from among several items on the same page.</p>
+<p>By using a multi-dimensional array, as shown below, it is possible to add multiple products to the cart in one action. This is useful in cases where you wish to allow people to select from among several items on the same page.</p>
<code>
@@ -268,8 +268,8 @@
<p><strong>What is a Row ID?</strong> The <kbd>row ID</kbd> is a unique identifier that is generated by the cart code when an item is added to the cart. The reason a
unique ID is created is so that identical products with different options can be managed by the cart.</p>
-<p>For example, let's say someone buys two identical t-shirts (same product ID), but in different sizes. The product ID (and other attributes) will be
-identical for both sizes because it's the same shirt. The only difference will be the size. The cart must therefore have a means of identifying this
+<p>For example, let's say someone buys two identical t-shirts (same product ID), but in different sizes. The product ID (and other attributes) will be
+identical for both sizes because it's the same shirt. The only difference will be the size. The cart must therefore have a means of identifying this
difference so that the two sizes of shirts can be managed independently. It does so by creating a unique "row ID" based on the product ID and any options associated with it.</p>
<p>In nearly all cases, updating the cart will be something the user does via the "view cart" page, so as a developer, it is unlikely that you will ever have to concern yourself
@@ -311,7 +311,7 @@
<h2>$this->cart->has_options(rowid);</h2>
-<p>Returns TRUE (boolean) if a particular row in the cart contains options. This function is designed to be used in a loop with <dfn>$this->cart->contents()</dfn>, since you must pass the <kbd>rowid</kbd> to this function, as shown in the <dfn>Displaying the Cart</dfn> example above.</p>
+<p>Returns TRUE (boolean) if a particular row in the cart contains options. This function is designed to be used in a loop with <dfn>$this->cart->contents()</dfn>, since you must pass the <kbd>rowid</kbd> to this function, as shown in the <dfn>Displaying the Cart</dfn> example above.</p>
<h2>$this->cart->product_options(rowid);</h2>
@@ -322,7 +322,7 @@
<h2>$this->cart->destroy();</h2>
-<p>Permits you to destroy the cart. This function will likely be called when you are finished processing the customer's order.</p>
+<p>Permits you to destroy the cart. This function will likely be called when you are finished processing the customer's order.</p>
diff --git a/user_guide/libraries/file_uploading.html b/user_guide/libraries/file_uploading.html
index a88c672..94b2193 100644
--- a/user_guide/libraries/file_uploading.html
+++ b/user_guide/libraries/file_uploading.html
@@ -305,6 +305,13 @@
</tr>
<tr>
+<td class="td"><strong>max_filename_increment</strong></td>
+<td class="td">100</td>
+<td class="td">None</td>
+<td class="td">When overwrite is set to FALSE, use this to set the maximum filename increment for CodeIgniter to append to the filename.</td>
+</tr>
+
+<tr>
<td class="td"><strong>encrypt_name</strong></td>
<td class="td">FALSE</td>
<td class="td">TRUE/FALSE (boolean)</td>
diff --git a/user_guide/libraries/form_validation.html b/user_guide/libraries/form_validation.html
index 7c544b6..ede1913 100644
--- a/user_guide/libraries/form_validation.html
+++ b/user_guide/libraries/form_validation.html
@@ -390,10 +390,10 @@
<p>CodeIgniter lets you pipe multiple rules together. Let's try it. Change your rules in the third parameter of rule setting function, like this:</p>
<code>
-$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]');<br />
+$this->form_validation->set_rules('username', 'Username', 'required|min_length[5]|max_length[12]|is_unique[users.username]');<br />
$this->form_validation->set_rules('password', 'Password', 'required|matches[passconf]');<br />
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');<br />
-$this->form_validation->set_rules('email', 'Email', 'required|valid_email');<br />
+$this->form_validation->set_rules('email', 'Email', 'required|valid_email|is_unique[users.email]');<br />
</code>
<p>The above code sets the following rules:</p>
@@ -508,15 +508,13 @@
<code>$this->form_validation->set_rules('username', 'Username', '<kbd>callback_username_check</kbd>');</code>
-
<p>Then add a new function called <dfn>username_check</dfn> to your controller. Here's how your controller should now look:</p>
-
-<textarea class="textarea" style="width:100%" cols="50" rows="44"><?php
+<textarea class="textarea" style="width:100%" cols="50" rows="40"><?php
class Form extends CI_Controller {
- function index()
+ public function index()
{
$this->load->helper(array('form', 'url'));
@@ -525,7 +523,7 @@
$this->form_validation->set_rules('username', 'Username', 'callback_username_check');
$this->form_validation->set_rules('password', 'Password', 'required');
$this->form_validation->set_rules('passconf', 'Password Confirmation', 'required');
- $this->form_validation->set_rules('email', 'Email', 'required');
+ $this->form_validation->set_rules('email', 'Email', 'required|is_unique[users.email]');
if ($this->form_validation->run() == FALSE)
{
@@ -537,7 +535,7 @@
}
}
- function username_check($str)
+ public function username_check($str)
{
if ($str == 'test')
{
@@ -556,14 +554,13 @@
<p><dfn>Reload your form and submit it with the word "test" as the username. You can see that the form field data was passed to your
callback function for you to process.</dfn></p>
-<p><strong>To invoke a callback just put the function name in a rule, with "callback_" as the rule prefix.</strong></p>
+<p>To invoke a callback just put the function name in a rule, with "callback_" as the rule <strong>prefix</strong>. If you need
+to receive an extra parameter in your callback function, just add it normally after the function name between square brackets,
+as in: "callback_foo<strong>[bar]</strong>", then it will be passed as the second argument of your callback function.</p>
-<p>You can also process the form data that is passed to your callback and return it. If your callback returns anything other than a boolean TRUE/FALSE
+<p><strong>Note:</strong> You can also process the form data that is passed to your callback and return it. If your callback returns anything other than a boolean TRUE/FALSE
it is assumed that the data is your newly processed form data.</p>
-
-
-
<a name="settingerrors"></a>
<h2>Setting Error Messages</h2>
@@ -947,6 +944,13 @@
</tr>
<tr>
+ <td class="td"><strong>is_unique</strong></td>
+ <td class="td">Yes</td>
+ <td class="td">Returns FALSE if the form element is not unique to the table and field name in the parameter.</td>
+ <td class="td">is_unique[table.field]</td>
+ </tr>
+
+ <tr>
<td class="td"><strong>min_length</strong></td>
<td class="td">Yes</td>
<td class="td">Returns FALSE if the form element is shorter then the parameter value.</td>
@@ -1038,6 +1042,13 @@
</tr>
<tr>
+ <td class="td"><strong>is_unique</strong></td>
+ <td class="td">Yes</td>
+ <td class="td">Returns FALSE if the form element is not unique in a database table.</td>
+ <td class="td">is_unique[table.field]</td>
+ </tr>
+
+ <tr>
<td class="td"><strong>valid_email</strong></td>
<td class="td">No</td>
<td class="td">Returns FALSE if the form element does not contain a valid email address.</td>
diff --git a/user_guide/libraries/input.html b/user_guide/libraries/input.html
index 311f76e..77e2848 100644
--- a/user_guide/libraries/input.html
+++ b/user_guide/libraries/input.html
@@ -73,11 +73,11 @@
<p>The security filtering function is called automatically when a new <a href="../general/controllers.html">controller</a> is invoked. It does the following:</p>
<ul>
-<li>Destroys the global GET array. Since CodeIgniter does not utilize GET strings, there is no reason to allow it.</li>
+<li>If $config['allow_get_array'] is FALSE(default is TRUE), destroys the global GET array.</li>
<li>Destroys all global variables in the event register_globals is turned on.</li>
-<li>Filters the POST/COOKIE array keys, permitting only alpha-numeric (and a few other) characters.</li>
+<li>Filters the GET/POST/COOKIE array keys, permitting only alpha-numeric (and a few other) characters.</li>
<li>Provides XSS (Cross-site Scripting Hacks) filtering. This can be enabled globally, or upon request.</li>
-<li>Standardizes newline characters to \n</li>
+<li>Standardizes newline characters to \n(In Windows \r\n)</li>
</ul>
@@ -133,13 +133,13 @@
<code>$this->input->post('some_data', TRUE);</code>
<p>To return an array of all POST items call without any parameters.</p>
-<p>To return all POST items and pass them through the XSS filter leave the first parameter blank while setting the second parameter to boolean;</p>
+<p>To return all POST items and pass them through the XSS filter set the first parameter NULL while setting the second parameter to boolean;</p>
<p>The function returns FALSE (boolean) if there are no items in the POST.</p>
<code>
- $this->input->post(); // returns all POST items with XSS filter
+ $this->input->post(NULL, TRUE); // returns all POST items with XSS filter
<br />
- $this->input->post(NULL, FALSE); // returns all POST items without XSS
+ $this->input->post(); // returns all POST items without XSS filter
</code>
<h2>$this->input->get()</h2>
@@ -149,13 +149,13 @@
<code>$this->input->get('some_data', TRUE);</code>
<p>To return an array of all GET items call without any parameters.</p>
-<p>To return all GET items and pass them through the XSS filter leave the first parameter blank while setting the second parameter to boolean;</p>
+<p>To return all GET items and pass them through the XSS filter set the first parameter NULL while setting the second parameter to boolean;</p>
<p>The function returns FALSE (boolean) if there are no items in the GET.</p>
<code>
- $this->input->get(); // returns all GET items with XSS filter
+ $this->input->get(NULL, TRUE); // returns all GET items with XSS filter
<br />
- $this->input->get(NULL, FALSE); // returns all GET items without XSS filtering
+ $this->input->get(); // returns all GET items without XSS filtering
</code>
<h2>$this->input->get_post()</h2>
diff --git a/user_guide/libraries/security.html b/user_guide/libraries/security.html
index dd62a43..cbe12d8 100644
--- a/user_guide/libraries/security.html
+++ b/user_guide/libraries/security.html
@@ -116,6 +116,9 @@
<p>If you use the <a href="../helpers/form_helper.html">form helper</a> the <var>form_open()</var> function will automatically insert a hidden csrf field in your forms.</p>
+<p>Select URIs can be whitelisted from csrf protection (for example API endpoints expecting externally POSTed content). You can add these URIs by editing the 'csrf_exclude_uris' config parameter:</p>
+<code>$config['csrf_exclude_uris'] = array('api/person/add');</code>
+
</div>
<!-- END CONTENT -->
diff --git a/user_guide/overview/appflow.html b/user_guide/overview/appflow.html
index c6bf857..fbc68fa 100644
--- a/user_guide/overview/appflow.html
+++ b/user_guide/overview/appflow.html
@@ -60,7 +60,7 @@
<p>The following graphic illustrates how data flows throughout the system:</p>
-<div><img src="../images/appflowchart.gif" width="697" height="205" border="0" alt="CodeIgniter application flow" /></div>
+<div><img src="../images/appflowchart.gif" width="769" height="212" alt="CodeIgniter application flow"></div>
<ol>