Merge pull request #2764 from refringe/feature/cookie_session

Issue #2763 - Fixes Session GC Probability Calculation
diff --git a/.travis.yml b/.travis.yml
index ab0aa56..fa9d5e5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -3,6 +3,7 @@
 php:
   - 5.3
   - 5.4
+  - 5.5
   
 env:
   - DB=mysql
diff --git a/application/config/config.php b/application/config/config.php
index 0608348..8d08a74 100644
--- a/application/config/config.php
+++ b/application/config/config.php
@@ -282,7 +282,7 @@
 | 'sess_driver'				= the driver to load: cookie (Classic), native (PHP sessions),
 |	or your custom driver name
 | 'sess_valid_drivers'		= additional valid drivers which may be loaded
-| 'sess_cookie_name'		= the name you want for the cookie
+| 'sess_cookie_name'		= the name you want for the cookie, must contain only [0-9a-z_-] characters
 | 'sess_expiration'			= the number of SECONDS you want the session to last.
 |   by default sessions last 7200 seconds (two hours).  Set to zero for no expiration.
 | 'sess_expire_on_close'	= Whether to cause the session to expire automatically
diff --git a/application/config/constants.php b/application/config/constants.php
index dc84712..e71097b 100644
--- a/application/config/constants.php
+++ b/application/config/constants.php
@@ -81,11 +81,11 @@
 | Used to indicate the conditions under which the script is exit()ing.
 | While there is no universal standard for error codes, there are some
 | broad conventions.  Three such conventions are mentioned below, for
-| those who wish to make use of them.  The CodeIgniter defaults were 
+| those who wish to make use of them.  The CodeIgniter defaults were
 | chosen for the least overlap with these conventions, while still
 | leaving room for others to be defined in future versions and user
 | applications.
-| 
+|
 | The three main conventions used for determining exit status codes
 | are as follows:
 |
@@ -108,7 +108,6 @@
 define('EXIT_DATABASE', 8); // database error
 define('EXIT__AUTO_MIN', 9); // lowest automatically-assigned error code
 define('EXIT__AUTO_MAX', 125); // highest automatically-assigned error code
- 
 
 /* End of file constants.php */
 /* Location: ./application/config/constants.php */
\ No newline at end of file
diff --git a/application/config/doctypes.php b/application/config/doctypes.php
index fe54202..b1a8959 100644
--- a/application/config/doctypes.php
+++ b/application/config/doctypes.php
@@ -26,19 +26,19 @@
  */
 
 $_doctypes = array(
-	'xhtml11'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
+	'xhtml11'			=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">',
 	'xhtml1-strict'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">',
 	'xhtml1-trans'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">',
 	'xhtml1-frame'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">',
 	'xhtml-basic11'		=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML Basic 1.1//EN" "http://www.w3.org/TR/xhtml-basic/xhtml-basic11.dtd">',
-	'html5'			=> '<!DOCTYPE html>',
+	'html5'				=> '<!DOCTYPE html>',
 	'html4-strict'		=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">',
 	'html4-trans'		=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">',
 	'html4-frame'		=> '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">',
-	'mathml1'		=> '<!DOCTYPE math SYSTEM "http://www.w3.org/Math/DTD/mathml1/mathml.dtd">',
-	'mathml2'		=> '<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">',
-	'svg10'			=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">',
-	'svg11'			=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
+	'mathml1'			=> '<!DOCTYPE math SYSTEM "http://www.w3.org/Math/DTD/mathml1/mathml.dtd">',
+	'mathml2'			=> '<!DOCTYPE math PUBLIC "-//W3C//DTD MathML 2.0//EN" "http://www.w3.org/Math/DTD/mathml2/mathml2.dtd">',
+	'svg10'				=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">',
+	'svg11'				=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">',
 	'svg11-basic'		=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Basic//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-basic.dtd">',
 	'svg11-tiny'		=> '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1 Tiny//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11-tiny.dtd">',
 	'xhtml-math-svg-xh'	=> '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">',
diff --git a/application/config/foreign_chars.php b/application/config/foreign_chars.php
index b0c32cf..ab98224 100644
--- a/application/config/foreign_chars.php
+++ b/application/config/foreign_chars.php
@@ -50,16 +50,16 @@
 	'/д/' => 'd',
 	'/Ð|Ď|Đ|Δ/' => 'Dj',
 	'/ð|ď|đ|δ/' => 'dj',
-	'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Ε|Έ|Ẽ|Ẻ|Ẹ|Ề|Ế|Ễ|Ể|Ệ|Е|Ё|Э/' => 'E',
-	'/è|é|ê|ë|ē|ĕ|ė|ę|ě|έ|ε|ẽ|ẻ|ẹ|ề|ế|ễ|ể|ệ|е|ё|э/' => 'e',
+	'/È|É|Ê|Ë|Ē|Ĕ|Ė|Ę|Ě|Ε|Έ|Ẽ|Ẻ|Ẹ|Ề|Ế|Ễ|Ể|Ệ|Е|Э/' => 'E',
+	'/è|é|ê|ë|ē|ĕ|ė|ę|ě|έ|ε|ẽ|ẻ|ẹ|ề|ế|ễ|ể|ệ|е|э/' => 'e',
 	'/Ф/' => 'F',
 	'/ф/' => 'f',
-	'/Ĝ|Ğ|Ġ|Ģ|Γ|Г/' => 'G',
-	'/ĝ|ğ|ġ|ģ|γ|г/' => 'g',
+	'/Ĝ|Ğ|Ġ|Ģ|Γ|Г|Ґ/' => 'G',
+	'/ĝ|ğ|ġ|ģ|γ|г|ґ/' => 'g',
 	'/Ĥ|Ħ/' => 'H',
 	'/ĥ|ħ/' => 'h',
-	'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|Η|Ή|Ί|Ι|Ϊ|Ỉ|Ị|И|Й/' => 'I',
-	'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|η|ή|ί|ι|ϊ|ỉ|ị|и|й/' => 'i',
+	'/Ì|Í|Î|Ï|Ĩ|Ī|Ĭ|Ǐ|Į|İ|Η|Ή|Ί|Ι|Ϊ|Ỉ|Ị|И|Ы/' => 'I',
+	'/ì|í|î|ï|ĩ|ī|ĭ|ǐ|į|ı|η|ή|ί|ι|ϊ|ỉ|ị|и|ы|ї/' => 'i',
 	'/Ĵ/' => 'J',
 	'/ĵ/' => 'j',
 	'/Ķ|Κ|К/' => 'K',
@@ -80,10 +80,10 @@
 	'/ś|ŝ|ş|ș|š|ſ|σ|ς|с/' => 's',
 	'/Ț|Ţ|Ť|Ŧ|τ|Т/' => 'T',
 	'/ț|ţ|ť|ŧ|т/' => 't',
-	'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|Ũ|Ủ|Ụ|Ừ|Ứ|Ữ|Ử|Ự|У|Ъ/' => 'U',
-	'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|υ|ύ|ϋ|ủ|ụ|ừ|ứ|ữ|ử|ự|у|ъ/' => 'u',
-	'/Ý|Ÿ|Ŷ|Υ|Ύ|Ϋ|Ỳ|Ỹ|Ỷ|Ỵ/' => 'Y',
-	'/ý|ÿ|ŷ|ỳ|ỹ|ỷ|ỵ/' => 'y',
+	'/Ù|Ú|Û|Ũ|Ū|Ŭ|Ů|Ű|Ų|Ư|Ǔ|Ǖ|Ǘ|Ǚ|Ǜ|Ũ|Ủ|Ụ|Ừ|Ứ|Ữ|Ử|Ự|У/' => 'U',
+	'/ù|ú|û|ũ|ū|ŭ|ů|ű|ų|ư|ǔ|ǖ|ǘ|ǚ|ǜ|υ|ύ|ϋ|ủ|ụ|ừ|ứ|ữ|ử|ự|у/' => 'u',
+	'/Ý|Ÿ|Ŷ|Υ|Ύ|Ϋ|Ỳ|Ỹ|Ỷ|Ỵ|Й/' => 'Y',
+	'/ý|ÿ|ŷ|ỳ|ỹ|ỷ|ỵ|й/' => 'y',
 	'/В/' => 'V',
 	'/в/' => 'v',
 	'/Ŵ/' => 'W',
@@ -91,7 +91,7 @@
 	'/Ź|Ż|Ž|Ζ|З/' => 'Z',
 	'/ź|ż|ž|ζ|з/' => 'z',
 	'/Æ|Ǽ/' => 'AE',
-	'/ß/'=> 'ss',
+	'/ß/' => 'ss',
 	'/IJ/' => 'IJ',
 	'/ij/' => 'ij',
 	'/Œ/' => 'OE',
@@ -101,22 +101,28 @@
 	'/β/' => 'v',
 	'/μ/' => 'm',
 	'/ψ/' => 'ps',
-	'/Ж/'=>'Zh',
-	'/ж/'=>'zh',
-	'/Х/'=>'Kh',
-	'/х/'=>'kh',
-	'/Ц/'=>'Tc',
-	'/ц/'=>'tc',
-	'/Ч/'=>'Ch',
-	'/ч/'=>'ch',
-	'/Ш/'=>'Sh',
-	'/ш/'=>'sh',
-	'/Щ/'=>'Shch',
-	'/щ/'=>'shch',
-	'/Ю/'=>'Iu',
-	'/ю/'=>'iu',
-	'/Я/'=>'Ia',
-	'/я/'=>'ia'
+	'/Ё/' => 'Yo',
+	'/ё/' => 'yo',
+	'/Є/' => 'Ye',
+	'/є/' => 'ye',
+	'/Ї/' => 'Yi',
+	'/Ж/' => 'Zh',
+	'/ж/' => 'zh',
+	'/Х/' => 'Kh',
+	'/х/' => 'kh',
+	'/Ц/' => 'Ts',
+	'/ц/' => 'ts',
+	'/Ч/' => 'Ch',
+	'/ч/' => 'ch',
+	'/Ш/' => 'Sh',
+	'/ш/' => 'sh',
+	'/Щ/' => 'Shch',
+	'/щ/' => 'shch',
+	'/Ъ|ъ|Ь|ь/' => '',
+	'/Ю/' => 'Yu',
+	'/ю/' => 'yu',
+	'/Я/' => 'Ya',
+	'/я/' => 'ya'
 );
 
 /* End of file foreign_chars.php */
diff --git a/application/config/migration.php b/application/config/migration.php
index b348fb3..a7576ca 100644
--- a/application/config/migration.php
+++ b/application/config/migration.php
@@ -105,7 +105,7 @@
 | Also, writing permission is required within the migrations path.
 |
 */
-$config['migration_path'] = APPPATH . 'migrations/';
+$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 32d10f6..27d4b25 100644
--- a/application/config/mimes.php
+++ b/application/config/mimes.php
@@ -78,6 +78,7 @@
 	'sit'	=>	'application/x-stuffit',
 	'tar'	=>	'application/x-tar',
 	'tgz'	=>	array('application/x-tar', 'application/x-gzip-compressed'),
+	'z'	=>	'application/x-compress',
 	'xhtml'	=>	'application/xhtml+xml',
 	'xht'	=>	'application/xhtml+xml',
 	'zip'	=>	array('application/x-zip', 'application/zip', 'application/x-zip-compressed', 'application/s-compressed', 'multipart/x-zip'),
@@ -96,7 +97,7 @@
 	'ra'	=>	'audio/x-realaudio',
 	'rv'	=>	'video/vnd.rn-realvideo',
 	'wav'	=>	array('audio/x-wav', 'audio/wave', 'audio/wav'),
-	'bmp'	=>	array('image/bmp', 'image/x-windows-bmp'),
+	'bmp'	=>	array('image/bmp', 'image/x-bmp', 'image/x-bitmap', 'image/x-xbitmap', 'image/x-win-bitmap', 'image/x-windows-bmp', 'image/ms-bmp', 'image/x-ms-bmp', 'application/bmp', 'application/x-bmp', 'application/x-win-bitmap'),
 	'gif'	=>	'image/gif',
 	'jpeg'	=>	array('image/jpeg', 'image/pjpeg'),
 	'jpg'	=>	array('image/jpeg', 'image/pjpeg'),
diff --git a/application/config/smileys.php b/application/config/smileys.php
index 4b25309..3c49c46 100644
--- a/application/config/smileys.php
+++ b/application/config/smileys.php
@@ -30,7 +30,7 @@
 | SMILEYS
 | -------------------------------------------------------------------
 | This file contains an array of smileys for use with the emoticon helper.
-| Individual images can be used to replace multiple simileys.  For example:
+| Individual images can be used to replace multiple smileys.  For example:
 | :-) and :) use the same image replacement.
 |
 | Please see user guide for more info:
@@ -84,7 +84,7 @@
 	':vampire:'		=>	array('vampire.gif',		'19',	'19',	'vampire'),
 	':snake:'		=>	array('snake.gif',			'19',	'19',	'snake'),
 	':exclaim:'		=>	array('exclaim.gif',		'19',	'19',	'excaim'),
-	':question:'	=>	array('question.gif',		'19',	'19',	'question') // no comma after last item
+	':question:'	=>	array('question.gif',		'19',	'19',	'question')
 
 );
 
diff --git a/application/config/user_agents.php b/application/config/user_agents.php
index 88ab063..0953dea 100644
--- a/application/config/user_agents.php
+++ b/application/config/user_agents.php
@@ -50,6 +50,7 @@
 	'win98'				=> 'Windows 98',
 	'windows 95'		=> 'Windows 95',
 	'win95'				=> 'Windows 95',
+	'windows phone'			=> 'Windows Phone',
 	'windows'			=> 'Unknown Windows OS',
 	'android'			=> 'Android',
 	'blackberry'		=> 'BlackBerry',
@@ -80,6 +81,7 @@
 // The order of this array should NOT be changed. Many browsers return
 // multiple browser types so we want to identify the sub-type first.
 $browsers = array(
+	'OPR'			=> 'Opera',
 	'Flock'			=> 'Flock',
 	'Chrome'		=> 'Chrome',
 	'Opera'			=> 'Opera',
@@ -102,7 +104,8 @@
 	'hotjava'		=> 'HotJava',
 	'amaya'			=> 'Amaya',
 	'IBrowse'		=> 'IBrowse',
-	'Maxthon'		=> 'Maxthon'
+	'Maxthon'		=> 'Maxthon',
+	'Ubuntu'		=> 'Ubuntu Web Browser'
 );
 
 $mobiles = array(
@@ -182,7 +185,7 @@
 	'operamini'		=> 'Opera Mini',
 	'opera mini'	=> 'Opera Mini',
 	'opera mobi'	=> 'Opera Mobile',
-	'fennec'	=> 'Firefox Mobile',
+	'fennec'		=> 'Firefox Mobile',
 
 	// Other
 	'digital paths'	=> 'Digital Paths',
diff --git a/application/views/errors/cli/error_404.php b/application/views/errors/cli/error_404.php
new file mode 100644
index 0000000..68ffdb3
--- /dev/null
+++ b/application/views/errors/cli/error_404.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Academic Free License version 3.0
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0) that is
+ * bundled with this package in the files license_afl.txt / license_afl.rst.
+ * It is also available through the world wide web at this URL:
+ * http://opensource.org/licenses/AFL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @license		http://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ * @link		http://codeigniter.com
+ * @since		Version 3.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+echo "\nERROR: ",
+	$heading,
+	"\n\n",
+	$message,
+	"\n\n";
\ No newline at end of file
diff --git a/application/views/errors/cli/error_db.php b/application/views/errors/cli/error_db.php
new file mode 100644
index 0000000..aca3a34
--- /dev/null
+++ b/application/views/errors/cli/error_db.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Academic Free License version 3.0
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0) that is
+ * bundled with this package in the files license_afl.txt / license_afl.rst.
+ * It is also available through the world wide web at this URL:
+ * http://opensource.org/licenses/AFL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @license		http://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ * @link		http://codeigniter.com
+ * @since		Version 3.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+echo "\nDatabase error: ",
+	$heading,
+	"\n\n",
+	$message,
+	"\n\n";
\ No newline at end of file
diff --git a/application/views/errors/cli/error_general.php b/application/views/errors/cli/error_general.php
new file mode 100644
index 0000000..1e5ffe5
--- /dev/null
+++ b/application/views/errors/cli/error_general.php
@@ -0,0 +1,33 @@
+<?php
+/**
+ * CodeIgniter
+ *
+ * An open source application development framework for PHP 5.2.4 or newer
+ *
+ * NOTICE OF LICENSE
+ *
+ * Licensed under the Academic Free License version 3.0
+ *
+ * This source file is subject to the Academic Free License (AFL 3.0) that is
+ * bundled with this package in the files license_afl.txt / license_afl.rst.
+ * It is also available through the world wide web at this URL:
+ * http://opensource.org/licenses/AFL-3.0
+ * If you did not receive a copy of the license and are unable to obtain it
+ * through the world wide web, please send an email to
+ * licensing@ellislab.com so we can send you a copy immediately.
+ *
+ * @package		CodeIgniter
+ * @author		EllisLab Dev Team
+ * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @license		http://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
+ * @link		http://codeigniter.com
+ * @since		Version 1.0
+ * @filesource
+ */
+defined('BASEPATH') OR exit('No direct script access allowed');
+
+echo "\nERROR: ",
+	$heading,
+	"\n\n",
+	$message,
+	"\n\n";
\ No newline at end of file
diff --git a/application/views/errors/error_php.php b/application/views/errors/cli/error_php.php
similarity index 61%
copy from application/views/errors/error_php.php
copy to application/views/errors/cli/error_php.php
index c4e6b29..4dbc410 100644
--- a/application/views/errors/error_php.php
+++ b/application/views/errors/cli/error_php.php
@@ -21,39 +21,30 @@
  * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
  * @license		http://opensource.org/licenses/AFL-3.0 Academic Free License (AFL 3.0)
  * @link		http://codeigniter.com
- * @since		Version 1.0
+ * @since		Version 3.0
  * @filesource
  */
 defined('BASEPATH') OR exit('No direct script access allowed');
 ?>
 
-<div style="border:1px solid #990000;padding-left:20px;margin:0 0 10px 0;">
+A PHP Error was encountered
 
-<h4>A PHP Error was encountered</h4>
-
-<p>Severity: <?php echo $severity; ?></p>
-<p>Message:  <?php echo $message; ?></p>
-<p>Filename: <?php echo $filepath; ?></p>
-<p>Line Number: <?php echo $line; ?></p>
+Severity: <?php echo $severity;?>
+Message:  <?php echo $message;?>
+Filename: <?php echo $filepath;?>
+Line Number: <?php echo $line;?>
 
 <?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
 
-	<p>Backtrace: </p>
-	<?php foreach(debug_backtrace() as $error): ?>
+Backtrace:
+	<?php foreach (debug_backtrace() as $error): ?>
+		<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
 
-		<?php if(isset($error['file']) &&
-		         strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
-
-			<p style="margin-left:10px">
-			File: <?php echo $error['file'] ?><br />
-			Line: <?php echo $error['line'] ?><br />
-			Function: <?php echo $error['function'] ?>
-			</p>
+	File: <?php echo $error['file'];?>
+	Line: <?php echo $error['line'];?>
+	Function: <?php echo $error['function'];?>
 
 		<?php endif ?>
 
-	<?php endforeach ?></p>
-
-<?php endif ?>
-
-</div>
\ No newline at end of file
+	<?php endforeach ?>
+<?php endif ?>
\ No newline at end of file
diff --git a/application/views/errors/cli/index.html b/application/views/errors/cli/index.html
new file mode 100644
index 0000000..c942a79
--- /dev/null
+++ b/application/views/errors/cli/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/application/views/errors/error_404.php b/application/views/errors/html/error_404.php
similarity index 100%
rename from application/views/errors/error_404.php
rename to application/views/errors/html/error_404.php
diff --git a/application/views/errors/error_db.php b/application/views/errors/html/error_db.php
similarity index 100%
rename from application/views/errors/error_db.php
rename to application/views/errors/html/error_db.php
diff --git a/application/views/errors/error_general.php b/application/views/errors/html/error_general.php
similarity index 100%
rename from application/views/errors/error_general.php
rename to application/views/errors/html/error_general.php
diff --git a/application/views/errors/error_php.php b/application/views/errors/html/error_php.php
similarity index 90%
rename from application/views/errors/error_php.php
rename to application/views/errors/html/error_php.php
index c4e6b29..2267d98 100644
--- a/application/views/errors/error_php.php
+++ b/application/views/errors/html/error_php.php
@@ -38,11 +38,10 @@
 
 <?php if (defined('SHOW_DEBUG_BACKTRACE') && SHOW_DEBUG_BACKTRACE === TRUE): ?>
 
-	<p>Backtrace: </p>
-	<?php foreach(debug_backtrace() as $error): ?>
+	<p>Backtrace:</p>
+	<?php foreach (debug_backtrace() as $error): ?>
 
-		<?php if(isset($error['file']) &&
-		         strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
+		<?php if (isset($error['file']) && strpos($error['file'], realpath(BASEPATH)) !== 0): ?>
 
 			<p style="margin-left:10px">
 			File: <?php echo $error['file'] ?><br />
diff --git a/application/views/errors/html/index.html b/application/views/errors/html/index.html
new file mode 100644
index 0000000..c942a79
--- /dev/null
+++ b/application/views/errors/html/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/index.php b/index.php
index f93cadb..72c97c4 100755
--- a/index.php
+++ b/index.php
@@ -77,7 +77,7 @@
  *---------------------------------------------------------------
  *
  * This variable must contain the name of your "system" folder.
- * Include the path if the folder is not in the same  directory
+ * Include the path if the folder is not in the same directory
  * as this file.
  */
 	$system_path = 'system';
@@ -220,28 +220,28 @@
 			$application_folder = $_temp;
 		}
 
-		define('APPPATH', $application_folder.'/');
+		define('APPPATH', $application_folder.DIRECTORY_SEPARATOR);
 	}
 	else
 	{
-		if ( ! is_dir(BASEPATH.$application_folder.'/'))
+		if ( ! is_dir(BASEPATH.$application_folder.DIRECTORY_SEPARATOR))
 		{
 			header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
 			echo 'Your application folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
 			exit(3); // EXIT_* constants not yet defined; 3 is EXIT_CONFIG.
 		}
 
-		define('APPPATH', BASEPATH.$application_folder.'/');
+		define('APPPATH', BASEPATH.$application_folder.DIRECTORY_SEPARATOR);
 	}
 
 	// The path to the "views" folder
 	if ( ! is_dir($view_folder))
 	{
-		if ( ! empty($view_folder) && is_dir(APPPATH.$view_folder.'/'))
+		if ( ! empty($view_folder) && is_dir(APPPATH.$view_folder.DIRECTORY_SEPARATOR))
 		{
 			$view_folder = APPPATH.$view_folder;
 		}
-		elseif ( ! is_dir(APPPATH.'views/'))
+		elseif ( ! is_dir(APPPATH.'views'.DIRECTORY_SEPARATOR))
 		{
 			header('HTTP/1.1 503 Service Unavailable.', TRUE, 503);
 			echo 'Your view folder path does not appear to be set correctly. Please open the following file and correct this: '.SELF;
@@ -255,11 +255,11 @@
 
 	if (($_temp = realpath($view_folder)) !== FALSE)
 	{
-		$view_folder = $_temp.'/';
+		$view_folder = $_temp.DIRECTORY_SEPARATOR;
 	}
 	else
 	{
-		$view_folder = rtrim($view_folder, '/').'/';
+		$view_folder = rtrim($view_folder, '/\\').DIRECTORY_SEPARATOR;
 	}
 
 	define('VIEWPATH', $view_folder);
diff --git a/readme.rst b/readme.rst
index d768162..619c7ae 100644
--- a/readme.rst
+++ b/readme.rst
@@ -14,7 +14,7 @@
 Release Information
 *******************
 
-This repo contains in development code for future releases. To download the
+This repo contains in-development code for future releases. To download the
 latest stable release please visit the `CodeIgniter Downloads
 <http://codeigniter.com/downloads/>`_ page.
 
@@ -49,9 +49,9 @@
 Resources
 *********
 
--  `User Guide <http://codeigniter.com/user_guide/>`_
--  `Community Forums <http://codeigniter.com/forums/>`_
--  `Community Wiki <http://codeigniter.com/wiki/>`_
+-  `User Guide <http://ellislab.com/codeigniter/user_guide/>`_
+-  `Community Forums <http://ellislab.com/codeigniter/forums/>`_
+-  `Community Wiki <http://ellislab.com/codeigniter/wiki/>`_
 -  `Community IRC <http://ellislab.com/codeigniter/irc>`_
 
 ***************
diff --git a/system/core/CodeIgniter.php b/system/core/CodeIgniter.php
index a026920..45c3485 100644
--- a/system/core/CodeIgniter.php
+++ b/system/core/CodeIgniter.php
@@ -48,13 +48,6 @@
 
 /*
  * ------------------------------------------------------
- *  Load the global functions
- * ------------------------------------------------------
- */
-	require_once(BASEPATH.'core/Common.php');
-
-/*
- * ------------------------------------------------------
  *  Load the framework constants
  * ------------------------------------------------------
  */
@@ -62,10 +55,15 @@
 	{
 		require(APPPATH.'config/'.ENVIRONMENT.'/constants.php');
 	}
-	else
-	{
-		require(APPPATH.'config/constants.php');
-	}
+
+	require(APPPATH.'config/constants.php');
+
+/*
+ * ------------------------------------------------------
+ *  Load the global functions
+ * ------------------------------------------------------
+ */
+	require_once(BASEPATH.'core/Common.php');
 
 /*
  * ------------------------------------------------------
@@ -73,11 +71,10 @@
  * ------------------------------------------------------
  */
 	set_error_handler('_exception_handler');
+	register_shutdown_function('_shutdown_handler');
 
-	if ( ! is_php('5.4'))
-	{
-		@ini_set('magic_quotes_runtime', 0); // Kill magic quotes
-	}
+	// Kill magic quotes
+	is_php('5.4') OR @ini_set('magic_quotes_runtime', 0);
 
 /*
  * ------------------------------------------------------
@@ -88,7 +85,7 @@
  * The subclass prefix allows CI to know if a core class is
  * being extended via a library in the local application
  * "libraries" folder. Since CI allows config items to be
- * overriden via data set in the main index. php file,
+ * overriden via data set in the main index.php file,
  * before proceeding we need to know if a subclass_prefix
  * override exists. If so, we will set this value now,
  * before any classes are loaded
diff --git a/system/core/Common.php b/system/core/Common.php
index b95a05d..00e3030 100644
--- a/system/core/Common.php
+++ b/system/core/Common.php
@@ -82,7 +82,7 @@
 	function is_really_writable($file)
 	{
 		// If we're on a Unix server with safe_mode off we call is_writable
-		if (DIRECTORY_SEPARATOR === '/' && (bool) @ini_get('safe_mode') === FALSE)
+		if (DIRECTORY_SEPARATOR === '/' && (is_php('5.4') OR (bool) @ini_get('safe_mode') === FALSE))
 		{
 			return is_writable($file);
 		}
@@ -224,56 +224,51 @@
 	 * @param	array
 	 * @return	array
 	 */
-	function &get_config($replace = array())
+	function &get_config(Array $replace = array())
 	{
 		static $_config;
 
-		if (isset($_config))
+		if (empty($_config))
 		{
-			return $_config[0];
-		}
-
-		$file_path = APPPATH.'config/config.php';
-		$found = FALSE;
-		if (file_exists($file_path))
-		{
-			$found = TRUE;
-			require($file_path);
-		}
-
-		// Is the config file in the environment folder?
-		if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
-		{
-			require($file_path);
-		}
-		elseif ( ! $found)
-		{
-			set_status_header(503);
-			echo 'The configuration file does not exist.';
-			exit(EXIT_CONFIG);
-		}
-
-		// Does the $config array exist in the file?
-		if ( ! isset($config) OR ! is_array($config))
-		{
-			set_status_header(503);
-			echo 'Your config file does not appear to be formatted correctly.';
-			exit(EXIT_CONFIG);
-		}
-
-		// Are any values being dynamically replaced?
-		if (count($replace) > 0)
-		{
-			foreach ($replace as $key => $val)
+			$file_path = APPPATH.'config/config.php';
+			$found = FALSE;
+			if (file_exists($file_path))
 			{
-				if (isset($config[$key]))
-				{
-					$config[$key] = $val;
-				}
+				$found = TRUE;
+				require($file_path);
 			}
+
+			// Is the config file in the environment folder?
+			if (file_exists($file_path = APPPATH.'config/'.ENVIRONMENT.'/config.php'))
+			{
+				require($file_path);
+			}
+			elseif ( ! $found)
+			{
+				set_status_header(503);
+				echo 'The configuration file does not exist.';
+				exit(EXIT_CONFIG);
+			}
+
+			// Does the $config array exist in the file?
+			if ( ! isset($config) OR ! is_array($config))
+			{
+				set_status_header(503);
+				echo 'Your config file does not appear to be formatted correctly.';
+				exit(EXIT_CONFIG);
+			}
+
+			// references cannot be directly assigned to static variables, so we use an array
+			$_config[0] =& $config;
 		}
 
-		return $_config[0] =& $config;
+		// Are any values being dynamically added or replaced?
+		foreach ($replace as $key => $val)
+		{
+			$_config[0][$key] = $val;
+		}
+
+		return $_config[0];
 	}
 }
 
@@ -360,6 +355,24 @@
 
 // ------------------------------------------------------------------------
 
+if ( ! function_exists('is_cli'))
+{
+
+	/**
+	 * Is CLI?
+	 *
+	 * Test to see if a request was made from the command line.
+	 *
+	 * @return 	bool
+	 */
+	function is_cli()
+	{
+		return (PHP_SAPI === 'cli' OR defined('STDIN'));
+	}
+}
+
+// ------------------------------------------------------------------------
+
 if ( ! function_exists('show_error'))
 {
 	/**
@@ -434,29 +447,19 @@
 	 *
 	 * @param	string	the error level: 'error', 'debug' or 'info'
 	 * @param	string	the error message
-	 * @param	bool	whether the error is a native PHP error
 	 * @return	void
 	 */
-	function log_message($level, $message, $php_error = FALSE)
+	function log_message($level, $message)
 	{
-		static $_log, $_log_threshold;
-
-		if ($_log_threshold === NULL)
-		{
-			$_log_threshold = config_item('log_threshold');
-		}
-
-		if ($_log_threshold === 0)
-		{
-			return;
-		}
+		static $_log;
 
 		if ($_log === NULL)
 		{
-			$_log =& load_class('Log', 'core');
+			// references cannot be directly assigned to static variables, so we use an array
+			$_log[0] =& load_class('Log', 'core');
 		}
 
-		$_log->write_log($level, $message, $php_error);
+		$_log[0]->write_log($level, $message);
 	}
 }
 
@@ -538,7 +541,7 @@
 
 		$server_protocol = isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : FALSE;
 
-		if (strpos(php_sapi_name(), 'cgi') === 0)
+		if (strpos(PHP_SAPI, 'cgi') === 0)
 		{
 			header('Status: '.$code.' '.$text, TRUE);
 		}
@@ -556,22 +559,35 @@
 	/**
 	 * Exception Handler
 	 *
-	 * This is the custom exception handler that is declaired at the top
-	 * of Codeigniter.php. The main reason we use this is to permit
+	 * This is the custom exception handler that is declared at the top
+	 * of CodeIgniter.php. The main reason we use this is to permit
 	 * PHP errors to be logged in our own log files since the user may
 	 * not have access to server logs. Since this function
 	 * effectively intercepts PHP errors, however, we also need
 	 * to display errors based on the current error_reporting level.
 	 * We do that with the use of a PHP error template.
 	 *
-	 * @param	int
-	 * @param	string
-	 * @param	string
-	 * @param	int
+	 * @param	int	$severity
+	 * @param	string	$message
+	 * @param	string	$filepath
+	 * @param	int	$line
 	 * @return	void
 	 */
 	function _exception_handler($severity, $message, $filepath, $line)
 	{
+		$is_error = (((E_ERROR | E_COMPILE_ERROR | E_CORE_ERROR | E_USER_ERROR) & $severity) === $severity);
+
+		// When an error occurred, set the status header to '500 Internal Server Error'
+		// to indicate to the client something went wrong.
+		// This can't be done within the $_error->show_php_error method because
+		// it is only called when the display_errors flag is set (which isn't usually
+		// the case in a production environment) or when errors are ignored because
+		// they are above the error_reporting threshold.
+		if ($is_error)
+		{
+			set_status_header(500);
+		}
+
 		$_error =& load_class('Exceptions', 'core');
 
 		// Should we ignore the error? We'll get the current error_reporting
@@ -588,6 +604,42 @@
 		}
 
 		$_error->log_exception($severity, $message, $filepath, $line);
+
+		// If the error is fatal, the execution of the script should be stopped because
+		// errors can't be recovered from. Halting the script conforms with PHP's
+		// default error handling. See http://www.php.net/manual/en/errorfunc.constants.php
+		if ($is_error)
+		{
+			exit(EXIT_ERROR);
+		}
+	}
+}
+
+// ------------------------------------------------------------------------
+
+if ( ! function_exists('_shutdown_handler'))
+{
+	/**
+	 * Shutdown Handler
+	 *
+	 * This is the shutdown handler that is declared at the top
+	 * of CodeIgniter.php. The main reason we use this is to simulate
+	 * a complete custom exception handler.
+	 *
+	 * E_STRICT is purposivly neglected because such events may have
+	 * been caught. Duplication or none? None is preferred for now.
+	 *
+	 * @link	http://insomanic.me.uk/post/229851073/php-trick-catching-fatal-errors-e-error-with-a
+	 * @return	void
+	 */
+	function _shutdown_handler()
+	{
+		$last_error = error_get_last();
+		if (isset($last_error) &&
+			($last_error['type'] & (E_ERROR | E_PARSE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING)))
+		{
+			_exception_handler($last_error['type'], $last_error['message'], $last_error['file'], $last_error['line']);
+		}
 	}
 }
 
diff --git a/system/core/Config.php b/system/core/Config.php
index 109ee64..a0e830a 100644
--- a/system/core/Config.php
+++ b/system/core/Config.php
@@ -228,13 +228,21 @@
 	 * @uses	CI_Config::_uri_string()
 	 *
 	 * @param	string|string[]	$uri	URI string or an array of segments
+	 * @param	string	$protocol
 	 * @return	string
 	 */
-	public function site_url($uri = '')
+	public function site_url($uri = '', $protocol = NULL)
 	{
+		$base_url = $this->slash_item('base_url');
+
+		if (isset($protocol))
+		{
+			$base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+		}
+
 		if (empty($uri))
 		{
-			return $this->slash_item('base_url').$this->item('index_page');
+			return $base_url.$this->item('index_page');
 		}
 
 		$uri = $this->_uri_string($uri);
@@ -255,14 +263,14 @@
 				}
 			}
 
-			return $this->slash_item('base_url').$this->slash_item('index_page').$uri;
+			return $base_url.$this->slash_item('index_page').$uri;
 		}
 		elseif (strpos($uri, '?') === FALSE)
 		{
 			$uri = '?'.$uri;
 		}
 
-		return $this->slash_item('base_url').$this->item('index_page').$uri;
+		return $base_url.$this->item('index_page').$uri;
 	}
 
 	// -------------------------------------------------------------
@@ -275,11 +283,19 @@
 	 * @uses	CI_Config::_uri_string()
 	 *
 	 * @param	string|string[]	$uri	URI string or an array of segments
+	 * @param	string	$protocol
 	 * @return	string
 	 */
-	public function base_url($uri = '')
+	public function base_url($uri = '', $protocol = NULL)
 	{
-		return $this->slash_item('base_url').ltrim($this->_uri_string($uri), '/');
+		$base_url = $this->slash_item('base_url');
+
+		if (isset($protocol))
+		{
+			$base_url = $protocol.substr($base_url, strpos($base_url, '://'));
+		}
+
+		return $base_url.ltrim($this->_uri_string($uri), '/');
 	}
 
 	// -------------------------------------------------------------
diff --git a/system/core/Exceptions.php b/system/core/Exceptions.php
index 9c68d06..809dc02 100644
--- a/system/core/Exceptions.php
+++ b/system/core/Exceptions.php
@@ -91,7 +91,7 @@
 	public function log_exception($severity, $message, $filepath, $line)
 	{
 		$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
-		log_message('error', 'Severity: '.$severity.'  --> '.$message. ' '.$filepath.' '.$line, TRUE);
+		log_message('error', 'Severity: '.$severity.' --> '.$message.' '.$filepath.' '.$line);
 	}
 
 	// --------------------------------------------------------------------
@@ -107,13 +107,21 @@
 	 */
 	public function show_404($page = '', $log_error = TRUE)
 	{
-		$heading = '404 Page Not Found';
-		$message = 'The page you requested was not found.';
+		if (is_cli())
+		{
+			$heading = 'Not Found';
+			$message = 'The controller/method pair you requested was not found.';
+		}
+		else
+		{
+			$heading = '404 Page Not Found';
+			$message = 'The page you requested was not found.';
+		}
 
 		// By default we log this, but allow a dev to skip it
 		if ($log_error)
 		{
-			log_message('error', '404 Page Not Found --> '.$page);
+			log_message('error', $heading.': '.$page);
 		}
 
 		echo $this->show_error($heading, $message, 'error_404', 404);
@@ -137,16 +145,24 @@
 	 */
 	public function show_error($heading, $message, $template = 'error_general', $status_code = 500)
 	{
-		set_status_header($status_code);
-
-		$message = '<p>'.implode('</p><p>', is_array($message) ? $message : array($message)).'</p>';
+		if (is_cli())
+		{
+			$message = "\t".(is_array($message) ? implode("\n\t", $message) : $message);
+			$template = 'cli'.DIRECTORY_SEPARATOR.$template;
+		}
+		else
+		{
+			set_status_header($status_code);
+			$message = '<p>'.(is_array($message) ? implode('</p><p>', $message) : $message).'</p>';
+			$template = 'html'.DIRECTORY_SEPARATOR.$template;
+		}
 
 		if (ob_get_level() > $this->ob_level + 1)
 		{
 			ob_end_flush();
 		}
 		ob_start();
-		include(VIEWPATH.'errors/'.$template.'.php');
+		include(VIEWPATH.'errors'.DIRECTORY_SEPARATOR.$template.'.php');
 		$buffer = ob_get_contents();
 		ob_end_clean();
 		return $buffer;
@@ -166,13 +182,22 @@
 	public function show_php_error($severity, $message, $filepath, $line)
 	{
 		$severity = isset($this->levels[$severity]) ? $this->levels[$severity] : $severity;
-		$filepath = str_replace('\\', '/', $filepath);
 
-		// For safety reasons we do not show the full file path
-		if (FALSE !== strpos($filepath, '/'))
+		// For safety reasons we don't show the full file path in non-CLI requests
+		if ( ! is_cli())
 		{
-			$x = explode('/', $filepath);
-			$filepath = $x[count($x)-2].'/'.end($x);
+			$filepath = str_replace('\\', '/', $filepath);
+			if (FALSE !== strpos($filepath, '/'))
+			{
+				$x = explode('/', $filepath);
+				$filepath = $x[count($x)-2].'/'.end($x);
+			}
+
+			$template = 'html'.DIRECTORY_SEPARATOR.'error_php';
+		}
+		else
+		{
+			$template = 'cli'.DIRECTORY_SEPARATOR.'error_php';
 		}
 
 		if (ob_get_level() > $this->ob_level + 1)
@@ -180,7 +205,7 @@
 			ob_end_flush();
 		}
 		ob_start();
-		include(VIEWPATH.'errors/error_php.php');
+		include(VIEWPATH.'errors'.DIRECTORY_SEPARATOR.$template.'.php');
 		$buffer = ob_get_contents();
 		ob_end_clean();
 		echo $buffer;
diff --git a/system/core/Input.php b/system/core/Input.php
index 0ef8112..384e30d 100644
--- a/system/core/Input.php
+++ b/system/core/Input.php
@@ -47,7 +47,7 @@
 	public $ip_address = FALSE;
 
 	/**
-	 * User agent strin
+	 * User agent string
 	 *
 	 * @var	string
 	 */
@@ -261,7 +261,7 @@
 	 * @param	bool	$xss_clean	Whether to apply XSS filtering
 	 * @return	mixed
 	 */
-	public function get_post($index = '', $xss_clean = FALSE)
+	public function post_get($index = '', $xss_clean = FALSE)
 	{
 		return isset($_POST[$index])
 			? $this->post($index, $xss_clean)
@@ -271,6 +271,22 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Fetch an item from GET data with fallback to POST
+	 *
+	 * @param	string	$index		Index for item to be fetched from $_GET or $_POST
+	 * @param	bool	$xss_clean	Whether to apply XSS filtering
+	 * @return	mixed
+	 */
+	public function get_post($index = '', $xss_clean = FALSE)
+	{
+		return isset($_GET[$index])
+			? $this->get($index, $xss_clean)
+			: $this->post($index, $xss_clean);
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * Fetch an item from the COOKIE array
 	 *
 	 * @param	string	$index		Index for item to be fetched from $_COOKIE
@@ -677,7 +693,14 @@
 
 			foreach ($_COOKIE as $key => $val)
 			{
-				$_COOKIE[$this->_clean_input_keys($key)] = $this->_clean_input_data($val);
+				if (($cookie_key = $this->_clean_input_keys($key)) !== FALSE)
+				{
+					$_COOKIE[$cookie_key] = $this->_clean_input_data($val);
+				}
+				else
+				{
+					unset($_COOKIE[$key]);
+				}
 			}
 		}
 
@@ -685,12 +708,12 @@
 		$_SERVER['PHP_SELF'] = strip_tags($_SERVER['PHP_SELF']);
 
 		// CSRF Protection check
-		if ($this->_enable_csrf === TRUE && ! $this->is_cli_request())
+		if ($this->_enable_csrf === TRUE && ! is_cli())
 		{
 			$this->security->csrf_verify();
 		}
 
-		log_message('debug', 'Global POST and COOKIE data sanitized');
+		log_message('debug', 'Global POST, GET and COOKIE data sanitized');
 	}
 
 	// --------------------------------------------------------------------
@@ -760,15 +783,25 @@
 	 * only named with alpha-numeric text and a few other items.
 	 *
 	 * @param	string	$str	Input string
-	 * @return	string
+	 * @param	string	$fatal	Whether to terminate script exection
+	 *				or to return FALSE if an invalid
+	 *				key is encountered
+	 * @return	string|bool
 	 */
-	protected function _clean_input_keys($str)
+	protected function _clean_input_keys($str, $fatal = TRUE)
 	{
 		if ( ! preg_match('/^[a-z0-9:_\/|-]+$/i', $str))
 		{
-			set_status_header(503);
-			echo 'Disallowed Key Characters.';
-			exit(EXIT_USER_INPUT);
+			if ($fatal === TRUE)
+			{
+				return FALSE;
+			}
+			else
+			{
+				set_status_header(503);
+				echo 'Disallowed Key Characters.';
+				exit(EXIT_USER_INPUT);
+			}
 		}
 
 		// Clean UTF-8 if supported
@@ -868,11 +901,12 @@
 	 *
 	 * Test to see if a request was made from the command line.
 	 *
-	 * @return 	bool
+	 * @deprecated	3.0.0	Use is_cli() instead
+	 * @return      bool
 	 */
 	public function is_cli_request()
 	{
-		return (php_sapi_name() === 'cli' OR defined('STDIN'));
+		return is_cli();
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/core/Loader.php b/system/core/Loader.php
index 1709c2d..70c1e41 100644
--- a/system/core/Loader.php
+++ b/system/core/Loader.php
@@ -222,7 +222,7 @@
 		{
 			foreach ($model as $key => $value)
 			{
-				$this->model(is_int($key) ? $value : $key, $value);
+				is_int($key) ? $this->model($value, '', $db_conn) : $this->model($key, $value, $db_conn);
 			}
 			return;
 		}
@@ -415,7 +415,7 @@
 	 *				to be extracted for use in the view
 	 * @param	bool	$return	Whether to return the view output
 	 *				or leave it to the Output class
-	 * @return	void
+	 * @return	void|string
 	 */
 	public function view($view, $vars = array(), $return = FALSE)
 	{
@@ -471,6 +471,20 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Clear Cached Variables
+	 * 
+	 * Clears the cached variables.
+	 * 
+	 * @return  void
+	 */
+	public function clear_vars()
+	{
+		$this->_ci_cached_vars = array();
+	}
+	
+	// --------------------------------------------------------------------
+
+	/**
 	 * Get Variable
 	 *
 	 * Check if a variable is set and retrieve it.
diff --git a/system/core/Log.php b/system/core/Log.php
index e4d72b5..b2327b8 100644
--- a/system/core/Log.php
+++ b/system/core/Log.php
@@ -140,10 +140,9 @@
 	 *
 	 * @param	string	the error level: 'error', 'debug' or 'info'
 	 * @param	string	the error message
-	 * @param	bool	whether the error is a native PHP error
 	 * @return	bool
 	 */
-	public function write_log($level, $msg, $php_error = FALSE)
+	public function write_log($level, $msg)
 	{
 		if ($this->_enabled === FALSE)
 		{
diff --git a/system/core/Output.php b/system/core/Output.php
index 06d7a86..10332f0 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -701,7 +701,7 @@
 		else
 		{
 			header('Pragma: public');
-			header('Cache-Control: max-age=' . $max_age . ', public');
+			header('Cache-Control: max-age='.$max_age.', public');
 			header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT');
 			header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT');
 		}
@@ -740,13 +740,13 @@
 				preg_match_all('{<style.+</style>}msU', $output, $style_clean);
 				foreach ($style_clean[0] as $s)
 				{
-					$output = str_replace($s, $this->_minify_script_style($s, TRUE), $output);
+					$output = str_replace($s, $this->_minify_js_css($s, 'css', TRUE), $output);
 				}
 
 				// Minify the javascript in <script> tags.
 				foreach ($javascript_clean[0] as $s)
 				{
-					$javascript_mini[] = $this->_minify_script_style($s, TRUE);
+					$javascript_mini[] = $this->_minify_js_css($s, 'js', TRUE);
 				}
 
 				// Replace multiple spaces with a single space.
@@ -792,13 +792,14 @@
 			break;
 
 			case 'text/css':
+
+				return $this->_minify_js_css($output, 'css');
+
 			case 'text/javascript':
 			case 'application/javascript':
 			case 'application/x-javascript':
 
-				$output = $this->_minify_script_style($output);
-
-			break;
+				return $this->_minify_js_css($output, 'js');
 
 			default: break;
 		}
@@ -809,134 +810,100 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Minify Style and Script
+	 * Minify JavaScript and CSS code
 	 *
-	 * Reduce excessive size of CSS/JavaScript content.  To remove spaces this
-	 * script walks the string as an array and determines if the pointer is inside
-	 * a string created by single quotes or double quotes.  spaces inside those
-	 * strings are not stripped.  Opening and closing tags are severed from
-	 * the string initially and saved without stripping whitespace to preserve
-	 * the tags and any associated properties if tags are present
+	 * Strips comments and excessive whitespace characters
 	 *
-	 * Minification logic/workflow is similar to methods used by Douglas Crockford
-	 * in JSMIN. http://www.crockford.com/javascript/jsmin.html
-	 *
-	 * KNOWN ISSUE: ending a line with a closing parenthesis ')' and no semicolon
-	 * where there should be one will break the Javascript. New lines after a
-	 * closing parenthesis are not recognized by the script. For best results
-	 * be sure to terminate lines with a semicolon when appropriate.
-	 *
-	 * @param	string	$output		Output to minify
-	 * @param	bool	$has_tags	Specify if the output has style or script tags
-	 * @return	string	Minified output
+	 * @param	string	$output
+	 * @param	string	$type	'js' or 'css'
+	 * @param	bool	$tags	Whether $output contains the 'script' or 'style' tag
+	 * @return	string
 	 */
-	protected function _minify_script_style($output, $has_tags = FALSE)
+	protected function _minify_js_css($output, $type, $tags = FALSE)
 	{
-		// We only need this if there are tags in the file
-		if ($has_tags === TRUE)
+		if ($tags === TRUE)
 		{
-			// Remove opening tag and save for later
-			$pos = strpos($output, '>') + 1;
-			$open_tag = substr($output, 0, $pos);
-			$output = substr_replace($output, '', 0, $pos);
+			$tags = array('close' => strrchr($output, '<'));
 
-			// Remove closing tag and save it for later
-			$pos = strpos($output, '</');
-			$closing_tag = substr($output, $pos, strlen($output));
-			$output = substr_replace($output, '', $pos);
+			$open_length = strpos($output, '>') + 1;
+			$tags['open'] = substr($output, 0, $open_length);
+
+			$output = substr($output, $open_length, -strlen($tags['close']));
+
+			// Strip spaces from the tags
+			$tags = preg_replace('#\s{2,}#', ' ', $tags);
 		}
 
-		// Remove CSS comments
-		$output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!i', '', $output);
+		$output = trim($output);
 
-		// Remove spaces around curly brackets, colons,
-		// semi-colons, parenthesis, commas
-		$chunks = preg_split('/([\'|"]).+(?![^\\\]\\1)\\1/iU', $output, -1, PREG_SPLIT_OFFSET_CAPTURE);
-		for ($i = count($chunks) - 1; $i >= 0; $i--)
+		if ($type === 'js')
 		{
-			$output = substr_replace(
-				$output,
-				preg_replace('/\s*(:|;|,|}|{|\(|\))\s*/i', '$1', $chunks[$i][0]),
-				$chunks[$i][1],
-				strlen($chunks[$i][0])
+			// Catch all string literals and comment blocks
+			if (preg_match_all('#((?:((?<!\\\)\'|")|(/\*)|(//)).*(?(2)(?<!\\\)\2|(?(3)\*/|\n)))#msuUS', $output, $match, PREG_OFFSET_CAPTURE))
+			{
+				$js_literals = $js_code = array();
+				for ($match = $match[0], $c = count($match), $i = $pos = $offset = 0; $i < $c; $i++)
+				{
+					$js_code[$pos++] = trim(substr($output, $offset, $match[$i][1] - $offset));
+					$offset = $match[$i][1] + strlen($match[$i][0]);
+
+					// Save only if we haven't matched a comment block
+					if ($match[$i][0][0] !== '/')
+					{
+						$js_literals[$pos++] = array_shift($match[$i]);
+					}
+				}
+				$js_code[$pos] = substr($output, $offset);
+
+				// $match might be quite large, so free it up together with other vars that we no longer need
+				unset($match, $offset, $pos);
+			}
+			else
+			{
+				$js_code = array($output);
+				$js_literals = array();
+			}
+
+			$varname = 'js_code';
+		}
+		else
+		{
+			$varname = 'output';
+		}
+
+		// Standartize new lines
+		$$varname = str_replace(array("\r\n", "\r"), "\n", $$varname);
+
+		if ($type === 'js')
+		{
+			$patterns = array(
+				'#\s*([!\#%&()*+,\-./:;<=>?@\[\]^`{|}~])\s*#'	=> '$1',	// Remove spaces following and preceeding JS-wise non-special & non-word characters
+				'#\s{2,}#'					=> ' '		// Reduce the remaining multiple whitespace characters to a single space
+			);
+		}
+		else
+		{
+			$patterns = array(
+				'#/\*.*(?=\*/)\*/#s'	=> '',		// Remove /* block comments */
+				'#\n?//[^\n]*#'		=> '',		// Remove // line comments
+				'#\s*([^\w.\#%])\s*#U'	=> '$1',	// Remove spaces following and preceeding non-word characters, excluding dots, hashes and the percent sign
+				'#\s{2,}#'		=> ' '		// Reduce the remaining multiple space characters to a single space
 			);
 		}
 
-		// Replace tabs with spaces
-		// Replace carriage returns & multiple new lines with single new line
-		// and trim any leading or trailing whitespace
-		$output = trim(preg_replace(array('/\t+/', '/\r/', '/\n+/'), array(' ', "\n", "\n"), $output));
+		$$varname = preg_replace(array_keys($patterns), array_values($patterns), $$varname);
 
-		// Remove spaces when safe to do so.
-		$in_string = $in_dstring = $prev = FALSE;
-		$array_output = str_split($output);
-		foreach ($array_output as $key => $value)
+		// Glue back JS quoted strings
+		if ($type === 'js')
 		{
-			if ($in_string === FALSE && $in_dstring === FALSE)
-			{
-				if ($value === ' ')
-				{
-					// Get the next element in the array for comparisons
-					$next = $array_output[$key + 1];
-
-					// Strip spaces preceded/followed by a non-ASCII character
-					// or not preceded/followed by an alphanumeric
-					// or not preceded/followed \ $ and _
-					if ((preg_match('/^[\x20-\x7f]*$/D', $next) OR preg_match('/^[\x20-\x7f]*$/D', $prev))
-						&& ( ! ctype_alnum($next) OR ! ctype_alnum($prev))
-						&& ! in_array($next, array('\\', '_', '$'), TRUE)
-						&& ! in_array($prev, array('\\', '_', '$'), TRUE)
-					)
-					{
-						unset($array_output[$key]);
-					}
-				}
-				else
-				{
-					// Save this value as previous for the next iteration
-					// if it is not a blank space
-					$prev = $value;
-				}
-			}
-
-			if ($value === "'")
-			{
-				$in_string = ! $in_string;
-			}
-			elseif ($value === '"')
-			{
-				$in_dstring = ! $in_dstring;
-			}
+			$js_code += $js_literals;
+			ksort($js_code);
+			$output = implode($js_code);
+			unset($js_code, $js_literals, $varname, $patterns);
 		}
 
-		// Put the string back together after spaces have been stripped
-		$output = implode($array_output);
-
-		// Remove new line characters unless previous or next character is
-		// printable or Non-ASCII
-		preg_match_all('/[\n]/', $output, $lf, PREG_OFFSET_CAPTURE);
-		$removed_lf = 0;
-		foreach ($lf as $feed_position)
-		{
-			foreach ($feed_position as $position)
-			{
-				$position = $position[1] - $removed_lf;
-				$next = $output[$position + 1];
-				$prev = $output[$position - 1];
-				if ( ! ctype_print($next) && ! ctype_print($prev)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $next)
-					&& ! preg_match('/^[\x20-\x7f]*$/D', $prev)
-				)
-				{
-					$output = substr_replace($output, '', $position, 1);
-					$removed_lf++;
-				}
-			}
-		}
-
-		// Put the opening and closing tags back if applicable
-		return isset($open_tag)
-			? $open_tag.$output.$closing_tag
+		return is_array($tags)
+			? $tags['open'].$output.$tags['close']
 			: $output;
 	}
 
diff --git a/system/core/Router.php b/system/core/Router.php
index 989ae54..d467d60 100644
--- a/system/core/Router.php
+++ b/system/core/Router.php
@@ -345,16 +345,41 @@
 		// Turn the segment array into a URI string
 		$uri = implode('/', $this->uri->segments);
 
+		// Get HTTP verb
+		$http_verb = isset($_SERVER['REQUEST_METHOD']) ? strtolower($_SERVER['REQUEST_METHOD']) : 'cli';
+
 		// Is there a literal match?  If so we're done
-		if (isset($this->routes[$uri]) && is_string($this->routes[$uri]))
+		if (isset($this->routes[$uri]))
 		{
-			return $this->_set_request(explode('/', $this->routes[$uri]));
+			// Check default routes format
+			if (is_string($this->routes[$uri]))
+			{
+				return $this->_set_request(explode('/', $this->routes[$uri]));
+			}
+			// Is there a matching http verb?
+			elseif (is_array($this->routes[$uri]) && isset($this->routes[$uri][$http_verb]))
+			{
+				return $this->_set_request(explode('/', $this->routes[$uri][$http_verb]));
+			}
 		}
 
-		// Loop through the route array looking for wild-cards
+		// Loop through the route array looking for wildcards
 		foreach ($this->routes as $key => $val)
 		{
-			// Convert wild-cards to RegEx
+			// Check if route format is using http verb
+			if (is_array($val))
+			{
+				if (isset($val[$http_verb]))
+				{
+					$val = $val[$http_verb];
+				}
+				else
+				{
+					continue;
+				}
+			}
+
+			// Convert wildcards to RegEx
 			$key = str_replace(array(':any', ':num'), array('[^/]+', '[0-9]+'), $key);
 
 			// Does the RegEx match?
diff --git a/system/core/Security.php b/system/core/Security.php
index 196d611..9423f82 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -38,6 +38,30 @@
 class CI_Security {
 
 	/**
+	 * List of sanitize filename strings
+	 *
+	 * @var	array
+	 */
+	public $filename_bad_chars =	array(
+		'../', '<!--', '-->', '<', '>',
+		"'", '"', '&', '$', '#',
+		'{', '}', '[', ']', '=',
+		';', '?', '%20', '%22',
+		'%3c',		// <
+		'%253c',	// <
+		'%3e',		// >
+		'%0e',		// >
+		'%28',		// (
+		'%29',		// )
+		'%2528',	// (
+		'%26',		// &
+		'%24',		// $
+		'%3f',		// ?
+		'%3b',		// ;
+		'%3d'		// =
+	);
+
+	/**
 	 * XSS Hash
 	 *
 	 * Random Hash for protecting URLs.
@@ -529,9 +553,9 @@
 		{
 			$matches = $matches1 = 0;
 
+			$str = preg_replace('~(&#x0*[0-9a-f]{2,5});?~iS', '$1;', $str, -1, $matches);
+			$str = preg_replace('~(&#\d{2,4});?~S', '$1;', $str, -1, $matches1);
 			$str = html_entity_decode($str, ENT_COMPAT, $charset);
-			$str = preg_replace('~&#x(0*[0-9a-f]{2,5})~ei', 'chr(hexdec("\\1"))', $str, -1, $matches);
-			$str = preg_replace('~&#([0-9]{2,4})~e', 'chr(\\1)', $str, -1, $matches1);
 		}
 		while ($matches OR $matches1);
 
@@ -549,24 +573,7 @@
 	 */
 	public function sanitize_filename($str, $relative_path = FALSE)
 	{
-		$bad = array(
-			'../', '<!--', '-->', '<', '>',
-			"'", '"', '&', '$', '#',
-			'{', '}', '[', ']', '=',
-			';', '?', '%20', '%22',
-			'%3c',		// <
-			'%253c',	// <
-			'%3e',		// >
-			'%0e',		// >
-			'%28',		// (
-			'%29',		// )
-			'%2528',	// (
-			'%26',		// &
-			'%24',		// $
-			'%3f',		// ?
-			'%3b',		// ;
-			'%3d'		// =
-		);
+		$bad = $this->filename_bad_chars;
 
 		if ( ! $relative_path)
 		{
@@ -596,7 +603,7 @@
 	 */
 	public function strip_image_tags($str)
 	{
-		return preg_replace(array('#<img\s+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img\s+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
+		return preg_replace(array('#<img[\s/]+.*?src\s*=\s*["\'](.+?)["\'].*?\>#', '#<img[\s/]+.*?src\s*=\s*(.+?).*?\>#'), '\\1', $str);
 	}
 
 	// ----------------------------------------------------------------
@@ -877,7 +884,7 @@
 	{
 		if ($this->_csrf_hash === '')
 		{
-			// If the cookie exists we will use it's value.
+			// If the cookie exists we will use its value.
 			// We don't necessarily want to regenerate it with
 			// each page load since a page could contain embedded
 			// sub-pages causing this feature to fail
@@ -887,7 +894,7 @@
 				return $this->_csrf_hash = $_COOKIE[$this->_csrf_cookie_name];
 			}
 
-			$this->_csrf_hash = md5(uniqid(rand(), TRUE));
+			$this->_csrf_hash = md5(uniqid(mt_rand(), TRUE));
 			$this->csrf_set_cookie();
 		}
 
diff --git a/system/core/URI.php b/system/core/URI.php
index bc086d2..bad9985 100644
--- a/system/core/URI.php
+++ b/system/core/URI.php
@@ -99,7 +99,7 @@
 		if ($protocol === 'AUTO')
 		{
 			// Is the request coming from the command line?
-			if ($this->_is_cli_request())
+			if (is_cli())
 			{
 				$this->_set_uri_string($this->_parse_argv());
 				return;
@@ -280,23 +280,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Is CLI Request?
-	 *
-	 * Duplicate of method from the Input class to test to see if
-	 * a request was made from the command line.
-	 *
-	 * @see		CI_Input::is_cli_request()
-	 * @used-by	CI_URI::_fetch_uri_string()
-	 * @return 	bool
-	 */
-	protected function _is_cli_request()
-	{
-		return (PHP_SAPI === 'cli') OR defined('STDIN');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Parse CLI arguments
 	 *
 	 * Take each command line argument and assume it is a URI segment.
diff --git a/system/database/DB.php b/system/database/DB.php
index 8742800..96da87c 100644
--- a/system/database/DB.php
+++ b/system/database/DB.php
@@ -206,11 +206,6 @@
 		$DB->initialize();
 	}
 
-	if ( ! empty($params['stricton']))
-	{
-		$DB->query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
-	}
-
 	return $DB;
 }
 
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 425657e..9aa6c5d 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -624,7 +624,14 @@
 				// if transactions are enabled. If we don't call this here
 				// the error message will trigger an exit, causing the
 				// transactions to remain in limbo.
-				$this->_trans_depth > 0 && $this->trans_complete();
+				if ($this->_trans_depth !== 0)
+				{
+					do
+					{
+						$this->trans_complete();
+					}
+					while ($this->_trans_depth !== 0);
+				}
 
 				// Display errors
 				return $this->display_error(array('Error Number: '.$error['code'], $error['message'], $sql));
@@ -1135,7 +1142,7 @@
 				else
 				{
 					/* We have no other choice but to just get the first element's key.
-					 * Due to array_shift() accepting it's argument by reference, if
+					 * Due to array_shift() accepting its argument by reference, if
 					 * E_STRICT is on, this would trigger a warning. So we'll have to
 					 * assign it first.
 					 */
@@ -1375,7 +1382,9 @@
 			$fields[$this->protect_identifiers($key)] = $this->escape($val);
 		}
 
-		return $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
+		$sql = $this->_update($this->protect_identifiers($table, TRUE, NULL, FALSE), $fields);
+		$this->_reset_write();
+		return $sql;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php
index d52029e..92806d3 100644
--- a/system/database/DB_forge.php
+++ b/system/database/DB_forge.php
@@ -740,6 +740,18 @@
 					'_literal'		=> FALSE
 			);
 
+			if ($create_table === FALSE)
+			{
+				if (isset($attributes['AFTER']))
+				{
+					$field['after'] = $attributes['AFTER'];
+				}
+				elseif (isset($attributes['FIRST']))
+				{
+					$field['first'] = (bool) $attributes['FIRST'];
+				}
+			}
+
 			$this->_attr_default($attributes, $field);
 
 			if (isset($attributes['NULL']))
@@ -748,11 +760,15 @@
 				{
 					$field['null'] = empty($this->_null) ? '' : ' '.$this->_null;
 				}
-				elseif ($create_table === TRUE)
+				else
 				{
 					$field['null'] = ' NOT NULL';
 				}
 			}
+			elseif ($create_table === TRUE)
+			{
+				$field['null'] = ' NOT NULL';
+			}
 
 			$this->_attr_auto_increment($attributes, $field);
 			$this->_attr_unique($attributes, $field);
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 292621b..1d41a19 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -385,7 +385,7 @@
 			$alias = $this->_create_alias_from_table(trim($select));
 		}
 
-		$sql = $this->protect_identifiers($type.'('.trim($select).')').' AS '.$this->escape_identifiers(trim($alias));
+		$sql = $type.'('.$this->protect_identifiers(trim($select)).') AS '.$this->escape_identifiers(trim($alias));
 
 		$this->qb_select[] = $sql;
 		$this->qb_no_escape[] = NULL;
@@ -1138,7 +1138,7 @@
 	 * ORDER BY
 	 *
 	 * @param	string	$orderby
-	 * @param	string	$direction	ASC or DESC
+	 * @param	string	$direction	ASC, DESC or RANDOM
 	 * @param	bool	$escape
 	 * @return	CI_DB_query_builder
 	 */
@@ -1152,7 +1152,7 @@
 
 			// Do we have a seed value?
 			$orderby = ctype_digit((string) $orderby)
-				? $orderby = sprintf($this->_random_keyword[1], $orderby)
+				? sprintf($this->_random_keyword[1], $orderby)
 				: $this->_random_keyword[0];
 		}
 		elseif (empty($orderby))
@@ -1338,7 +1338,7 @@
 	 * returned by an Query Builder query.
 	 *
 	 * @param	string
-	 * @return	string
+	 * @return	int
 	 */
 	public function count_all_results($table = '')
 	{
@@ -1846,6 +1846,7 @@
 		{
 			$this->query($this->_update_batch($this->protect_identifiers($table, TRUE, NULL, FALSE), array_slice($this->qb_set, $i, 100), $this->protect_identifiers($index)));
 			$affected_rows += $this->affected_rows();
+			$this->qb_where = array();
 		}
 
 		$this->_reset_write();
@@ -2290,7 +2291,12 @@
 		{
 			for ($i = 0, $c = count($this->$qb_key); $i < $c; $i++)
 			{
-				if ($this->{$qb_key}[$i]['escape'] === FALSE)
+				// Is this condition already compiled?
+				if (is_string($this->{$qb_key}[$i]))
+				{
+					continue;
+				}
+				elseif ($this->{$qb_key}[$i]['escape'] === FALSE)
 				{
 					$this->{$qb_key}[$i] = $this->{$qb_key}[$i]['condition'];
 					continue;
@@ -2360,6 +2366,12 @@
 		{
 			for ($i = 0, $c = count($this->qb_groupby); $i < $c; $i++)
 			{
+				// Is it already compiled?
+				if (is_string($this->qb_groupby))
+				{
+					continue;
+				}
+
 				$this->qb_groupby[$i] = ($this->qb_groupby[$i]['escape'] === FALSE OR $this->_is_literal($this->qb_groupby[$i]['field']))
 					? $this->qb_groupby[$i]['field']
 					: $this->protect_identifiers($this->qb_groupby[$i]['field']);
@@ -2545,16 +2557,18 @@
 			return;
 		}
 
-		foreach ($this->qb_cache_exists as $val)
+		foreach (array_unique($this->qb_cache_exists) as $val) // select, from, etc.
 		{
 			$qb_variable	= 'qb_'.$val;
 			$qb_cache_var	= 'qb_cache_'.$val;
+			$qb_new 	= $this->$qb_cache_var;
 
-			if (count($this->$qb_cache_var) === 0)
+			foreach ($this->$qb_variable as &$qb_var)
 			{
-				continue;
+			 	in_array($qb_var, $qb_new, TRUE) OR $qb_new[] = $qb_var;
 			}
-			$this->$qb_variable = array_merge($this->$qb_variable, array_diff($this->$qb_cache_var, $this->$qb_variable));
+
+			$this->$qb_variable = $qb_new;
 		}
 
 		// If we are "protecting identifiers" we need to examine the "from"
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index b94642b..16b2f6f 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -66,6 +66,15 @@
 	 */
 	public $delete_hack = TRUE;
 
+	/**
+	 * Strict ON flag
+	 *
+	 * Whether we're running in strict SQL mode.
+	 *
+	 * @var	bool
+	 */
+	public $stricton = FALSE;
+
 	// --------------------------------------------------------------------
 
 	/**
@@ -126,6 +135,11 @@
 				: FALSE;
 		}
 
+		if ($this->stricton && is_resource($this->conn_id))
+		{
+			$this->simple_query('SET SESSION sql_mode="STRICT_ALL_TABLES"');
+		}
+
 		return $this->conn_id;
 	}
 
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index ef2cb8a..62ba2c5 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -66,6 +66,15 @@
 	 */
 	public $delete_hack = TRUE;
 
+	/**
+	 * Strict ON flag
+	 *
+	 * Whether we're running in strict SQL mode.
+	 *
+	 * @var	bool
+	 */
+	public $stricton = FALSE;
+
 	// --------------------------------------------------------------------
 
 	/**
@@ -93,6 +102,11 @@
 		$client_flags = ($this->compress === TRUE) ? MYSQLI_CLIENT_COMPRESS : 0;
 		$mysqli = mysqli_init();
 
+		if ($this->stricton)
+		{
+			$mysqli->options(MYSQLI_INIT_COMMAND, 'SET SESSION sql_mode="STRICT_ALL_TABLES"');
+		}
+
 		return @$mysqli->real_connect($hostname, $this->username, $this->password, $this->database, $port, NULL, $client_flags)
 			? $mysqli : FALSE;
 	}
@@ -241,9 +255,10 @@
 		// even if the queries produce a successful result.
 		$this->_trans_failure = ($test_mode === TRUE);
 
-		$this->simple_query('SET AUTOCOMMIT=0');
-		$this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
-		return TRUE;
+		$this->conn_id->autocommit(FALSE);
+		return is_php('5.5')
+			? $this->conn_id->begin_transaction()
+			: $this->simple_query('START TRANSACTION'); // can also be BEGIN or BEGIN WORK
 	}
 
 	// --------------------------------------------------------------------
@@ -261,9 +276,13 @@
 			return TRUE;
 		}
 
-		$this->simple_query('COMMIT');
-		$this->simple_query('SET AUTOCOMMIT=1');
-		return TRUE;
+		if ($this->conn_id->commit())
+		{
+			$this->conn_id->autocommit(TRUE);
+			return TRUE;
+		}
+
+		return FALSE;
 	}
 
 	// --------------------------------------------------------------------
@@ -281,9 +300,13 @@
 			return TRUE;
 		}
 
-		$this->simple_query('ROLLBACK');
-		$this->simple_query('SET AUTOCOMMIT=1');
-		return TRUE;
+		if ($this->conn_id->rollback())
+		{
+			$this->conn_id->autocommit(TRUE);
+			return TRUE;
+		}
+
+		return FALSE;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 93e62b4..d75ed28 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -18,7 +18,7 @@
  *
  * @package		CodeIgniter
  * @author		EllisLab Dev Team
- * @copyright   Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
  * @license		http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  * @link		http://codeigniter.com
  * @since		Version 1.0
@@ -344,7 +344,7 @@
 				$have_cursor = TRUE;
 			}
 		}
-		$sql = trim($sql, ',') . '); END;';
+		$sql = trim($sql, ',').'); END;';
 
 		$this->stmt_id = FALSE;
 		$this->_set_stmt_id($sql);
diff --git a/system/database/drivers/oci8/oci8_result.php b/system/database/drivers/oci8/oci8_result.php
index fd1d287..ce09b62 100644
--- a/system/database/drivers/oci8/oci8_result.php
+++ b/system/database/drivers/oci8/oci8_result.php
@@ -18,7 +18,7 @@
  *
  * @package		CodeIgniter
  * @author		EllisLab Dev Team
- * @copyright   Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
+ * @copyright	Copyright (c) 2008 - 2013, EllisLab, Inc. (http://ellislab.com/)
  * @license		http://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0)
  * @link		http://codeigniter.com
  * @since		Version 1.0
diff --git a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
index ff486fc..bc92cab 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_mysql_driver.php
@@ -55,6 +55,15 @@
 	 */
 	public $compress = FALSE;
 
+	/**
+	 * Strict ON flag
+	 *
+	 * Whether we're running in strict SQL mode.
+	 *
+	 * @var	bool
+	 */
+	public $stricton = FALSE;
+
 	// --------------------------------------------------------------------
 
 	/**
@@ -114,6 +123,18 @@
 				.(empty($this->dbcollat) ? '' : ' COLLATE '.$this->dbcollat);
 		}
 
+		if ($this->stricton)
+		{
+			if (empty($this->options[PDO::MYSQL_ATTR_INIT_COMMAND]))
+			{
+				$this->options[PDO::MYSQL_ATTR_INIT_COMMAND] = 'SET SESSION sql_mode="STRICT_ALL_TABLES"';
+			}
+			else
+			{
+				$this->options[PDO::MYSQL_ATTR_INIT_COMMAND] .= ', @@session.sql_mode = "STRICT_ALL_TABLES"';
+			}
+		}
+
 		if ($this->compress === TRUE)
 		{
 			$this->options[PDO::MYSQL_ATTR_COMPRESS] = TRUE;
diff --git a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
index d0cdde2..fda3f23 100644
--- a/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
+++ b/system/database/drivers/pdo/subdrivers/pdo_pgsql_driver.php
@@ -137,7 +137,7 @@
 	 */
 	public function is_write_type($sql)
 	{
-		return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+		return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE(?!.*\sRETURNING)|DELETE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', str_replace(array("\r\n", "\r", "\n"), ' ', $sql));
 	}
 
 	// --------------------------------------------------------------------
@@ -166,7 +166,7 @@
 	 * ORDER BY
 	 *
 	 * @param	string	$orderby
-	 * @param	string	$direction	ASC or DESC
+	 * @param	string	$direction	ASC, DESC or RANDOM
 	 * @param	bool	$escape
 	 * @return	object
 	 */
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index ac7345a..b72fb87 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -318,7 +318,7 @@
 	 */
 	public function is_write_type($sql)
 	{
-		return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE|DELETE|REPLACE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', $sql);
+		return (bool) preg_match('/^\s*"?(SET|INSERT(?![^\)]+\)\s+RETURNING)|UPDATE(?!.*\sRETURNING)|DELETE|CREATE|DROP|TRUNCATE|LOAD|COPY|ALTER|RENAME|GRANT|REVOKE|LOCK|UNLOCK|REINDEX)\s+/i', str_replace(array("\r\n", "\r", "\n"), ' ', $sql));
 	}
 
 	// --------------------------------------------------------------------
@@ -331,7 +331,7 @@
 	 */
 	protected function _escape_str($str)
 	{
-		return pg_escape_string($str);
+		return pg_escape_string($this->conn_id, $str);
 	}
 
 	// --------------------------------------------------------------------
@@ -346,7 +346,11 @@
 	 */
 	public function escape($str)
 	{
-		if (is_bool($str))
+		if (is_php('5.4.4') && (is_string($str) OR (is_object($str) && method_exists($str, '__toString'))))
+		{
+			return pg_escape_literal($this->conn_id, $str);
+		}
+		elseif (is_bool($str))
 		{
 			return ($str) ? 'TRUE' : 'FALSE';
 		}
@@ -512,7 +516,7 @@
 	 * ORDER BY
 	 *
 	 * @param	string	$orderby
-	 * @param	string	$direction	ASC or DESC
+	 * @param	string	$direction	ASC, DESC or RANDOM
 	 * @param	bool	$escape
 	 * @return	object
 	 */
diff --git a/system/helpers/captcha_helper.php b/system/helpers/captcha_helper.php
index 29911dc..24cd535 100644
--- a/system/helpers/captcha_helper.php
+++ b/system/helpers/captcha_helper.php
@@ -126,9 +126,9 @@
 		// Determine angle and position
 		// -----------------------------------
 		$length	= strlen($word);
-		$angle	= ($length >= 6) ? rand(-($length-6), ($length-6)) : 0;
-		$x_axis	= rand(6, (360/$length)-16);
-		$y_axis = ($angle >= 0) ? rand($img_height, $img_width) : rand(6, $img_height);
+		$angle	= ($length >= 6) ? mt_rand(-($length-6), ($length-6)) : 0;
+		$x_axis	= mt_rand(6, (360/$length)-16);
+		$y_axis = ($angle >= 0) ? mt_rand($img_height, $img_width) : mt_rand(6, $img_height);
 
 		// Create image
 		// PHP.net recommends imagecreatetruecolor(), but it isn't always available
@@ -183,13 +183,13 @@
 		if ($use_font === FALSE)
 		{
 			$font_size = 5;
-			$x = rand(0, $img_width / ($length / 3));
+			$x = mt_rand(0, $img_width / ($length / 3));
 			$y = 0;
 		}
 		else
 		{
 			$font_size = 16;
-			$x = rand(0, $img_width / ($length / 1.5));
+			$x = mt_rand(0, $img_width / ($length / 1.5));
 			$y = $font_size + 2;
 		}
 
@@ -197,13 +197,13 @@
 		{
 			if ($use_font === FALSE)
 			{
-				$y = rand(0 , $img_height / 2);
+				$y = mt_rand(0 , $img_height / 2);
 				imagestring($im, $font_size, $x, $y, $word[$i], $colors['text']);
 				$x += ($font_size * 2);
 			}
 			else
 			{
-				$y = rand($img_height / 2, $img_height - 3);
+				$y = mt_rand($img_height / 2, $img_height - 3);
 				imagettftext($im, $font_size, $angle, $x, $y, $colors['text'], $font_path, $word[$i]);
 				$x += $font_size;
 			}
@@ -215,12 +215,12 @@
 		// -----------------------------------
 		//  Generate the image
 		// -----------------------------------
-		$img_name = $now.'.jpg';
-		ImageJPEG($im, $img_path.$img_name);
-		$img = '<img src="'.$img_url.$img_name.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
+		$img_filename = $now.'.jpg';
+		ImageJPEG($im, $img_path.$img_filename);
+		$img = '<img src="'.$img_url.$img_filename.'" style="width: '.$img_width.'; height: '.$img_height .'; border: 0;" alt=" " />';
 		ImageDestroy($im);
 
-		return array('word' => $word, 'time' => $now, 'image' => $img);
+		return array('word' => $word, 'time' => $now, 'image' => $img, 'filename' => $img_filename);
 	}
 }
 
diff --git a/system/helpers/form_helper.php b/system/helpers/form_helper.php
index 146c0f5..a3d299b 100644
--- a/system/helpers/form_helper.php
+++ b/system/helpers/form_helper.php
@@ -316,7 +316,7 @@
 		{
 			isset($name['options']) OR $name['options'] = array();
 			isset($name['selected']) OR $name['selected'] = array();
-			isset($name['extra']) OR $name['extra'] = array();
+			isset($name['extra']) OR $name['extra'] = '';
 
 			return form_dropdown($name['name'], $name['options'], $name['selected'], $name['extra']);
 		}
@@ -329,10 +329,7 @@
 			$selected = array($_POST[$name]);
 		}
 
-		if ($extra != '')
-		{
-			$extra = ' '.$extra;
-		}
+		$extra = _attributes_to_string($extra);
 
 		$multiple = (count($selected) > 1 && strpos($extra, 'multiple') === FALSE) ? ' multiple="multiple"' : '';
 
@@ -675,37 +672,33 @@
 	 */
 	function set_select($field = '', $value = '', $default = FALSE)
 	{
-		$OBJ =& _get_validation_object();
+		$CI =& get_instance();
 
-		if ($OBJ === FALSE)
+		if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
 		{
-			if ( ! isset($_POST[$field]))
+			return $CI->form_validation->set_select($field, $value, $default);
+		}
+		elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+		{
+			return ($default === TRUE) ? ' selected="selected"' : '';
+		}
+
+		$value = (string) $value;
+		if (is_array($input))
+		{
+			// Note: in_array('', array(0)) returns TRUE, do not use it
+			foreach ($input as &$v)
 			{
-				if (count($_POST) === 0 && $default === TRUE)
+				if ($value === $v)
 				{
 					return ' selected="selected"';
 				}
-				return '';
 			}
 
-			$field = $_POST[$field];
-
-			if (is_array($field))
-			{
-				if ( ! in_array($value, $field))
-				{
-					return '';
-				}
-			}
-			elseif (($field == '' OR $value == '') OR $field !== $value)
-			{
-				return '';
-			}
-
-			return ' selected="selected"';
+			return '';
 		}
 
-		return $OBJ->set_select($field, $value, $default);
+		return ($input === $value) ? ' selected="selected"' : '';
 	}
 }
 
@@ -726,37 +719,33 @@
 	 */
 	function set_checkbox($field = '', $value = '', $default = FALSE)
 	{
-		$OBJ =& _get_validation_object();
+		$CI =& get_instance();
 
-		if ($OBJ === FALSE)
+		if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
 		{
-			if ( ! isset($_POST[$field]))
+			return $CI->form_validation->set_checkbox($field, $value, $default);
+		}
+		elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+		{
+			return ($default === TRUE) ? ' checked="checked"' : '';
+		}
+
+		$value = (string) $value;
+		if (is_array($input))
+		{
+			// Note: in_array('', array(0)) returns TRUE, do not use it
+			foreach ($input as &$v)
 			{
-				if (count($_POST) === 0 && $default === TRUE)
+				if ($value === $v)
 				{
 					return ' checked="checked"';
 				}
-				return '';
 			}
 
-			$field = $_POST[$field];
-
-			if (is_array($field))
-			{
-				if ( ! in_array($value, $field))
-				{
-					return '';
-				}
-			}
-			elseif (($field == '' OR $value == '') OR $field !== $value)
-			{
-				return '';
-			}
-
-			return ' checked="checked"';
+			return '';
 		}
 
-		return $OBJ->set_checkbox($field, $value, $default);
+		return ($input === $value) ? ' checked="checked"' : '';
 	}
 }
 
@@ -770,47 +759,25 @@
 	 * Let's you set the selected value of a radio field via info in the POST array.
 	 * If Form Validation is active it retrieves the info from the validation class
 	 *
-	 * @param	string
-	 * @param	string
-	 * @param	bool
+	 * @param	string	$field
+	 * @param	string	$value
+	 * @param	bool	$default
 	 * @return	string
 	 */
 	function set_radio($field = '', $value = '', $default = FALSE)
 	{
-		$OBJ =& _get_validation_object();
+		$CI =& get_instance();
 
-		if ($OBJ === FALSE)
+		if (isset($CI->form_validation) && is_object($CI->form_validation) && $CI->form_validation->has_rule($field))
 		{
-			if ( ! isset($_POST[$field]))
-			{
-				if (count($_POST) === 0 && $default === TRUE)
-				{
-					return ' checked="checked"';
-				}
-				return '';
-			}
-
-			$field = $_POST[$field];
-
-			if (is_array($field))
-			{
-				if ( ! in_array($value, $field))
-				{
-					return '';
-				}
-			}
-			else
-			{
-				if (($field == '' OR $value == '') OR $field !== $value)
-				{
-					return '';
-				}
-			}
-
-			return ' checked="checked"';
+			return $CI->form_validation->set_radio($field, $value, $default);
+		}
+		elseif (($input = $CI->input->post($field, FALSE)) === NULL)
+		{
+			return ($default === TRUE) ? ' checked="checked"' : '';
 		}
 
-		return $OBJ->set_radio($field, $value, $default);
+		return ($input === (string) $value) ? ' checked="checked"' : '';
 	}
 }
 
diff --git a/system/helpers/url_helper.php b/system/helpers/url_helper.php
index fbb4a1b..b0f4368 100644
--- a/system/helpers/url_helper.php
+++ b/system/helpers/url_helper.php
@@ -52,14 +52,7 @@
 	 */
 	function site_url($uri = '', $protocol = NULL)
 	{
-		$uri = get_instance()->config->site_url($uri);
-
-		if (isset($protocol))
-		{
-			return $protocol.substr($uri, strpos($uri, '://'));
-		}
-
-		return $uri;
+		return get_instance()->config->site_url($uri, $protocol);
 	}
 }
 
@@ -80,14 +73,7 @@
 	 */
 	function base_url($uri = '', $protocol = NULL)
 	{
-		$uri = get_instance()->config->base_url($uri);
-
-		if (isset($protocol))
-		{
-			return $protocol.substr($uri, strpos($uri, '://'));
-		}
-
-		return $uri;
+		return get_instance()->config->base_url($uri, $protocol);
 	}
 }
 
diff --git a/system/libraries/Cache/drivers/Cache_redis.php b/system/libraries/Cache/drivers/Cache_redis.php
index 40823fc..f13e447 100644
--- a/system/libraries/Cache/drivers/Cache_redis.php
+++ b/system/libraries/Cache/drivers/Cache_redis.php
@@ -44,6 +44,7 @@
 	 * @var	array
 	 */
 	protected static $_default_config = array(
+		'socket_type' => 'tcp',
 		'host' => '127.0.0.1',
 		'password' => NULL,
 		'port' => 6379,
@@ -163,8 +164,7 @@
 	{
 		if (extension_loaded('redis'))
 		{
-			$this->_setup_redis();
-			return TRUE;
+			return $this->_setup_redis();
 		}
 		else
 		{
@@ -200,17 +200,33 @@
 
 		try
 		{
-			$this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+			if ($config['socket_type'] === 'unix')
+			{
+				$success = $this->_redis->connect($config['socket']);
+			}
+			else // tcp socket
+			{
+				$success = $this->_redis->connect($config['host'], $config['port'], $config['timeout']);
+			}
+			
+			if ( ! $success)
+			{
+				log_message('debug', 'Cache: Redis connection refused. Check the config.');
+				return FALSE;
+			}
 		}
 		catch (RedisException $e)
 		{
-			show_error('Redis connection refused. ' . $e->getMessage());
+			log_message('debug', 'Cache: Redis connection refused ('.$e->getMessage().')');
+			return FALSE;
 		}
 
 		if (isset($config['password']))
 		{
 			$this->_redis->auth($config['password']);
 		}
+		
+		return TRUE;
 	}
 
 	// ------------------------------------------------------------------------
diff --git a/system/libraries/Email.php b/system/libraries/Email.php
index 46ffaa1..efdbfd7 100644
--- a/system/libraries/Email.php
+++ b/system/libraries/Email.php
@@ -399,9 +399,9 @@
 		else
 		{
 			$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
-			$this->_safe_mode = (bool) @ini_get('safe_mode');
 		}
 
+		$this->_safe_mode = ( ! is_php('5.4') && (bool) @ini_get('safe_mode'));
 		$this->charset = strtoupper($this->charset);
 
 		log_message('debug', 'Email Class Initialized');
@@ -451,7 +451,6 @@
 		$this->clear();
 
 		$this->_smtp_auth = ! ($this->smtp_user === '' && $this->smtp_pass === '');
-		$this->_safe_mode = (bool) @ini_get('safe_mode');
 
 		return $this;
 	}
@@ -1265,7 +1264,7 @@
 				}
 				else
 				{
-					$this->_finalbody = $hdr . $this->newline . $this->newline . $this->_body;
+					$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_body;
 				}
 
 				return;
@@ -1275,11 +1274,11 @@
 				if ($this->send_multipart === FALSE)
 				{
 					$hdr .= 'Content-Type: text/html; charset='.$this->charset.$this->newline
-						.'Content-Transfer-Encoding: quoted-printable'.$this->newline.$this->newline;
+						.'Content-Transfer-Encoding: quoted-printable';
 				}
 				else
 				{
-					$hdr .= 'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"'.$this->newline.$this->newline;
+					$hdr .= 'Content-Type: multipart/alternative; boundary="'.$this->_alt_boundary.'"';
 
 					$body .= $this->_get_mime_message().$this->newline.$this->newline
 						.'--'.$this->_alt_boundary.$this->newline
@@ -1300,7 +1299,7 @@
 				}
 				else
 				{
-					$this->_finalbody = $hdr.$this->_finalbody;
+					$this->_finalbody = $hdr.$this->newline.$this->newline.$this->_finalbody;
 				}
 
 				if ($this->send_multipart !== FALSE)
@@ -1312,25 +1311,25 @@
 
 			case 'plain-attach' :
 
-				$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
+				$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"';
 
 				if ($this->_get_protocol() === 'mail')
 				{
 					$this->_header_str .= $hdr;
 				}
 
-				$body .= $this->_get_mime_message().$this->newline.$this->newline
+				$body .= $this->_get_mime_message().$this->newline
+					.$this->newline
 					.'--'.$this->_atc_boundary.$this->newline
-
 					.'Content-Type: text/plain; charset='.$this->charset.$this->newline
-					.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline.$this->newline
-
+					.'Content-Transfer-Encoding: '.$this->_get_encoding().$this->newline
+					.$this->newline
 					.$this->_body.$this->newline.$this->newline;
 
 			break;
 			case 'html-attach' :
 
-				$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"'.$this->newline.$this->newline;
+				$hdr .= 'Content-Type: multipart/'.$this->multipart.'; boundary="'.$this->_atc_boundary.'"';
 
 				if ($this->_get_protocol() === 'mail')
 				{
@@ -1400,7 +1399,9 @@
 		}
 
 		$body .= implode($this->newline, $attachment).$this->newline.'--'.$this->_atc_boundary.'--';
-		$this->_finalbody = ($this->_get_protocol() === 'mail') ? $body : $hdr.$body;
+		$this->_finalbody = ($this->_get_protocol() === 'mail')
+			? $body
+			: $hdr.$this->newline.$this->newline.$body;
 		return TRUE;
 	}
 
diff --git a/system/libraries/Form_validation.php b/system/libraries/Form_validation.php
index 8b9bfa8..5ea2f81 100644
--- a/system/libraries/Form_validation.php
+++ b/system/libraries/Form_validation.php
@@ -898,12 +898,19 @@
 		}
 
 		$field = $this->_field_data[$field]['postdata'];
+		$value = (string) $value;
 		if (is_array($field))
 		{
-			if ( ! in_array($value, $field))
+			// Note: in_array('', array(0)) returns TRUE, do not use it
+			foreach ($field as &$v)
 			{
-				return '';
+				if ($value === $v)
+				{
+					return ' selected="selected"';
+				}
 			}
+
+			return '';
 		}
 		elseif (($field === '' OR $value === '') OR ($field !== $value))
 		{
@@ -934,12 +941,19 @@
 		}
 
 		$field = $this->_field_data[$field]['postdata'];
+		$value = (string) $value;
 		if (is_array($field))
 		{
-			if ( ! in_array($value, $field))
+			// Note: in_array('', array(0)) returns TRUE, do not use it
+			foreach ($field as &$v)
 			{
-				return '';
+				if ($value === $v)
+				{
+					return ' checked="checked"';
+				}
 			}
+
+			return '';
 		}
 		elseif (($field === '' OR $value === '') OR ($field !== $value))
 		{
diff --git a/system/libraries/Ftp.php b/system/libraries/Ftp.php
index dc6bbd2..2489f49 100644
--- a/system/libraries/Ftp.php
+++ b/system/libraries/Ftp.php
@@ -392,7 +392,7 @@
 		{
 			if ($this->debug === TRUE)
 			{
-				$this->_error('ftp_unable_to_' . ($move === FALSE ? 'rename' : 'move'));
+				$this->_error('ftp_unable_to_'.($move === FALSE ? 'rename' : 'move'));
 			}
 			return FALSE;
 		}
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 10fb29d..c6ffd03 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -354,7 +354,8 @@
 	public function create_links()
 	{
 		// If our item count or per-page total is zero there is no need to continue.
-		if ($this->total_rows === 0 OR $this->per_page === 0)
+		// Note: DO NOT change the operator to === here!
+		if ($this->total_rows == 0 OR $this->per_page == 0)
 		{
 			return '';
 		}
diff --git a/system/libraries/Profiler.php b/system/libraries/Profiler.php
index 9e9e7d0..50ba167 100644
--- a/system/libraries/Profiler.php
+++ b/system/libraries/Profiler.php
@@ -307,10 +307,7 @@
 
 			foreach ($_GET as $key => $val)
 			{
-				if ( ! is_numeric($key))
-				{
-					$key = "'".$key."'";
-				}
+				is_int($key) OR $key = "'".$key."'";
 
 				$output .= '<tr><td style="width:50%;color:#000;background-color:#ddd;padding:5px;">&#36;_GET['
 					.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#cd6e00;font-weight:normal;background-color:#ddd;">'
@@ -338,7 +335,7 @@
 			."\n"
 			.'<legend style="color:#009900;">&nbsp;&nbsp;'.$this->CI->lang->line('profiler_post_data')."&nbsp;&nbsp;</legend>\n";
 
-		if (count($_POST) === 0)
+		if (count($_POST) === 0 && count($_FILES) === 0)
 		{
 			$output .= '<div style="color:#009900;font-weight:normal;padding:4px 0 4px 0;">'.$this->CI->lang->line('profiler_no_post').'</div>';
 		}
@@ -348,10 +345,7 @@
 
 			foreach ($_POST as $key => $val)
 			{
-				if ( ! is_numeric($key))
-				{
-					$key = "'".$key."'";
-				}
+				is_int($key) OR $key = "'".$key."'";
 
 				$output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">&#36;_POST['
 					.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">';
@@ -368,6 +362,21 @@
 				$output .= "</td></tr>\n";
 			}
 
+			foreach ($_FILES as $key => $val)
+			{
+				is_int($key) OR $key = "'".$key."'";
+
+				$output .= '<tr><td style="width:50%;padding:5px;color:#000;background-color:#ddd;">&#36;_FILES['
+					.$key.']&nbsp;&nbsp; </td><td style="width:50%;padding:5px;color:#009900;font-weight:normal;background-color:#ddd;">';
+
+				if (is_array($val) OR is_object($val))
+				{
+					$output .= '<pre>'.htmlspecialchars(stripslashes(print_r($val, TRUE))).'</pre>';
+				}
+
+				$output .= "</td></tr>\n";
+			}
+
 			$output .= "</table>\n";
 		}
 
diff --git a/system/libraries/Session/Session.php b/system/libraries/Session/Session.php
index c7f6f82..19de979 100644
--- a/system/libraries/Session/Session.php
+++ b/system/libraries/Session/Session.php
@@ -60,11 +60,18 @@
 	public $params = array();
 
 	/**
+	 * Valid drivers list
+	 *
+	 * @var	array
+	 */
+	public $valid_drivers = array('native',	'cookie');
+
+	/**
 	 * Current driver in use
 	 *
 	 * @var	string
 	 */
-	protected $current = NULL;
+	public $current = NULL;
 
 	/**
 	 * User data
@@ -95,46 +102,36 @@
 	 */
 	public function __construct(array $params = array())
 	{
-		$CI =& get_instance();
+		$_config =& get_instance()->config;
 
 		// No sessions under CLI
-		if ($CI->input->is_cli_request())
+		if (is_cli())
 		{
 			return;
 		}
 
 		log_message('debug', 'CI_Session Class Initialized');
 
-		// Get valid drivers list
-		$this->valid_drivers = array(
-			'native',
-			'cookie'
-		);
-		$key = 'sess_valid_drivers';
-		$drivers = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
-		if ($drivers)
+		// Add possible extra entries to our valid drivers list
+		$drivers = isset($params['sess_valid_drivers']) ? $params['sess_valid_drivers'] : $_config->item('sess_valid_drivers');
+		if ( ! empty($drivers))
 		{
-			// Add driver names to valid list
-			foreach ((array) $drivers as $driver)
-			{
-				if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
-				{
-					$this->valid_drivers[] = $driver;
-				}
-			}
+			$drivers = array_map('strtolower', (array) $drivers);
+			$this->valid_drivers = array_merge($this->valid_drivers, array_diff($drivers, $this->valid_drivers));
 		}
 
 		// Get driver to load
-		$key = 'sess_driver';
-		$driver = isset($params[$key]) ? $params[$key] : $CI->config->item($key);
+		$driver = isset($params['sess_driver']) ? $params['sess_driver'] : $_config->item('sess_driver');
 		if ( ! $driver)
 		{
+			log_message('debug', "Session: No driver name is configured, defaulting to 'cookie'.");
 			$driver = 'cookie';
 		}
 
-		if ( ! in_array(strtolower($driver), array_map('strtolower', $this->valid_drivers)))
+		if ( ! in_array($driver, $this->valid_drivers))
 		{
-			$this->valid_drivers[] = $driver;
+			log_message('error', 'Session: Configured driver name is not valid, aborting.');
+			return;
 		}
 
 		// Save a copy of parameters in case drivers need access
diff --git a/system/libraries/Upload.php b/system/libraries/Upload.php
index 8542804..7989d11 100644
--- a/system/libraries/Upload.php
+++ b/system/libraries/Upload.php
@@ -234,6 +234,13 @@
 	public $xss_clean		= FALSE;
 
 	/**
+	 * Apache mod_mime fix flag
+	 *
+	 * @var	bool
+	 */
+	public $mod_mime_fix		= TRUE;
+
+	/**
 	 * Temporary filename prefix
 	 *
 	 * @var	string
@@ -314,6 +321,7 @@
 					'remove_spaces'			=> TRUE,
 					'detect_mime'			=> TRUE,
 					'xss_clean'			=> FALSE,
+					'mod_mime_fix'			=> TRUE,
 					'temp_prefix'			=> 'temp_file_',
 					'client_name'			=> ''
 				);
@@ -463,7 +471,7 @@
 		}
 
 		// Are the image dimensions within the allowed size?
-		// Note: This can fail if the server has an open_basdir restriction.
+		// Note: This can fail if the server has an open_basedir restriction.
 		if ( ! $this->is_allowed_dimensions())
 		{
 			$this->set_error('upload_invalid_dimensions');
@@ -1148,7 +1156,7 @@
 	 */
 	protected function _prep_filename($filename)
 	{
-		if (strpos($filename, '.') === FALSE OR $this->allowed_types === '*')
+		if ($this->mod_mime_fix === FALSE OR $this->allowed_types === '*' OR strpos($filename, '.') === FALSE)
 		{
 			return $filename;
 		}
@@ -1245,7 +1253,7 @@
 				}
 			}
 
-			if ( (bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec'))
+			if ((bool) @ini_get('safe_mode') === FALSE && function_usable('shell_exec'))
 			{
 				$mime = @shell_exec($cmd);
 				if (strlen($mime) > 0)
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index 16c5b0e..fe9781b 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -1684,7 +1684,7 @@
 	{
 		if ($this->mytype !== 0)
 		{
-			echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
 			return 0;
 		}
 
@@ -1705,7 +1705,7 @@
 	{
 		if ($this->mytype !== 0)
 		{
-			echo '<strong>XML_RPC_Values</strong>: already initialized as a [' . $this->kindOf() . ']<br />';
+			echo '<strong>XML_RPC_Values</strong>: already initialized as a ['.$this->kindOf().']<br />';
 			return 0;
 		}
 		$this->mytype = $this->xmlrpcTypes['struct'];
diff --git a/system/libraries/Zip.php b/system/libraries/Zip.php
index 6608f05..2ce4578 100644
--- a/system/libraries/Zip.php
+++ b/system/libraries/Zip.php
@@ -103,12 +103,12 @@
 	 *
 	 * Lets you add a virtual directory into which you can place files.
 	 *
-	 * @param	mixed	the directory name. Can be string or array
+	 * @param	mixed	$directory	the directory name. Can be string or array
 	 * @return	void
 	 */
 	public function add_dir($directory)
 	{
-		foreach ( (array) $directory as $dir)
+		foreach ((array) $directory as $dir)
 		{
 			if ( ! preg_match('|.+/$|', $dir))
 			{
@@ -127,7 +127,7 @@
 	 *
 	 * If this is a newly created file/dir, we will set the time to 'now'
 	 *
-	 * @param	string	path to file
+	 * @param	string	$dir	path to file
 	 * @return	array	filemtime/filemdate
 	 */
 	protected function _get_mod_time($dir)
@@ -146,9 +146,9 @@
 	/**
 	 * Add Directory
 	 *
-	 * @param	string	the directory name
-	 * @param	int
-	 * @param	int
+	 * @param	string	$dir	the directory name
+	 * @param	int	$file_mtime
+	 * @param	int	$file_mdate
 	 * @return	void
 	 */
 	protected function _add_dir($dir, $file_mtime, $file_mdate)
@@ -199,8 +199,8 @@
 	 * in the filename it will be placed within a directory. Make
 	 * sure you use add_dir() first to create the folder.
 	 *
-	 * @param	mixed
-	 * @param	string
+	 * @param	mixed	$filepath	A single filepath or an array of file => data pairs
+	 * @param	string	$data		Single file contents
 	 * @return	void
 	 */
 	public function add_data($filepath, $data = NULL)
@@ -225,10 +225,10 @@
 	/**
 	 * Add Data to Zip
 	 *
-	 * @param	string	the file name/path
-	 * @param	string	the data to be encoded
-	 * @param	int
-	 * @param	int
+	 * @param	string	$filepath	the file name/path
+	 * @param	string	$data	the data to be encoded
+	 * @param	int	$file_mtime
+	 * @param	int	$file_mdate
 	 * @return	void
 	 */
 	protected function _add_data($filepath, $data, $file_mtime, $file_mdate)
@@ -278,8 +278,8 @@
 	/**
 	 * Read the contents of a file and add it to the zip
 	 *
-	 * @param	string
-	 * @param	bool
+	 * @param	string	$path
+	 * @param	bool	$preserve_filepath
 	 * @return	bool
 	 */
 	public function read_file($path, $preserve_filepath = FALSE)
@@ -313,9 +313,9 @@
 	 * sub-folders) and creates a zip based on it. Whatever directory structure
 	 * is in the original file path will be recreated in the zip file.
 	 *
-	 * @param	string	path to source
-	 * @param	bool
-	 * @param	bool
+	 * @param	string	$path	path to source directory
+	 * @param	bool	$preserve_filepath
+	 * @param	string	$root_path
 	 * @return	bool
 	 */
 	public function read_dir($path, $preserve_filepath = TRUE, $root_path = NULL)
@@ -389,7 +389,7 @@
 	 *
 	 * Lets you write a file
 	 *
-	 * @param	string	the file name
+	 * @param	string	$filepath	the file name
 	 * @return	bool
 	 */
 	public function archive($filepath)
@@ -412,7 +412,7 @@
 	/**
 	 * Download
 	 *
-	 * @param	string	the file name
+	 * @param	string	$filename	the file name
 	 * @return	void
 	 */
 	public function download($filename = 'backup.zip')
diff --git a/tests/codeigniter/core/Benchmark_test.php b/tests/codeigniter/core/Benchmark_test.php
index a239ba5..aff736a 100644
--- a/tests/codeigniter/core/Benchmark_test.php
+++ b/tests/codeigniter/core/Benchmark_test.php
@@ -30,7 +30,7 @@
 		sleep(1);
 		$this->benchmark->mark('code_end');
 
-		$this->assertEquals('1.0', $this->benchmark->elapsed_time('code_start', 'code_end', 1));
+		$this->assertEquals('1', $this->benchmark->elapsed_time('code_start', 'code_end', 0));
 	}
 
 	// --------------------------------------------------------------------
diff --git a/tests/codeigniter/core/Input_test.php b/tests/codeigniter/core/Input_test.php
index 5cf25fe..0a98e55 100644
--- a/tests/codeigniter/core/Input_test.php
+++ b/tests/codeigniter/core/Input_test.php
@@ -82,11 +82,21 @@
 
 	// --------------------------------------------------------------------
 
-	public function test_get_post()
+	public function test_post_get()
 	{
 		$_SERVER['REQUEST_METHOD'] = 'POST';
 		$_POST['foo'] = 'bar';
 
+		$this->assertEquals('bar', $this->input->post_get('foo'));
+	}
+
+	// --------------------------------------------------------------------
+
+	public function test_get_post()
+	{
+		$_SERVER['REQUEST_METHOD'] = 'GET';
+		$_GET['foo'] = 'bar';
+
 		$this->assertEquals('bar', $this->input->get_post('foo'));
 	}
 
diff --git a/tests/codeigniter/core/Security_test.php b/tests/codeigniter/core/Security_test.php
index 3f6e3b0..433ad31 100644
--- a/tests/codeigniter/core/Security_test.php
+++ b/tests/codeigniter/core/Security_test.php
@@ -5,7 +5,7 @@
 	public function set_up()
 	{
 		// Set cookie for security test
-		$_COOKIE['ci_csrf_cookie'] = md5(uniqid(rand(), TRUE));
+		$_COOKIE['ci_csrf_cookie'] = md5(uniqid(mt_rand(), TRUE));
 
 		// Set config for Security class
 		$this->ci_set_config('csrf_protection', TRUE);
diff --git a/tests/mocks/core/common.php b/tests/mocks/core/common.php
index 0ccfe1e..b073f23 100644
--- a/tests/mocks/core/common.php
+++ b/tests/mocks/core/common.php
@@ -178,7 +178,7 @@
 
 if ( ! function_exists('log_message'))
 {
-	function log_message($level, $message, $php_error = FALSE)
+	function log_message($level, $message)
 	{
 		return TRUE;
 	}
@@ -190,4 +190,13 @@
 	{
 		return TRUE;
 	}
+}
+
+if ( ! function_exists('is_cli'))
+{
+	// In order to test HTTP functionality, we need to lie about this
+	function is_cli()
+	{
+		return FALSE;
+	}
 }
\ No newline at end of file
diff --git a/tests/mocks/core/uri.php b/tests/mocks/core/uri.php
index 94f75df..1107858 100644
--- a/tests/mocks/core/uri.php
+++ b/tests/mocks/core/uri.php
@@ -18,9 +18,4 @@
 
 	}
 
-	protected function _is_cli_request()
-	{
-		return FALSE;
-	}
-
 }
\ No newline at end of file
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index 4cef0e6..b7fa9bb 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -55,6 +55,7 @@
    -  Changed environment defaults to report all errors in *development* and only fatal ones in *testing*, *production* but only display them in *development*.
    -  Updated *ip_address* database field lengths from 16 to 45 for supporting IPv6 address on :doc:`Trackback Library <libraries/trackback>` and :doc:`Captcha Helper <helpers/captcha_helper>`.
    -  Removed *cheatsheets* and *quick_reference* PDFs from the documentation.
+   -  Added support non-HTML error templates for CLI applications.
    -  Added availability checks where usage of dangerous functions like ``eval()`` and ``exec()`` is required.
    -  Added support for changing the file extension of log files using ``$config['log_file_extension']``.
 
@@ -75,9 +76,8 @@
       - :php:func:`anchor_popup()` will now fill the *href* attribute with the URL and its JS code will return FALSE instead.
       - Added JS window name support to the :php:func:`anchor_popup()` function.
       - Added support (auto-detection) for HTTP/1.1 response code 303 in :php:func:`redirect()`.
-      - Changed :php:func:`redirect()` to only choose the **refresh** method only on IIS servers, instead of all servers on Windows (when **auto** is used).
+      - Changed :php:func:`redirect()` to choose the **refresh** method only on IIS servers, instead of all servers on Windows (when **auto** is used).
       - Changed :php:func:`anchor()`, :php:func:`anchor_popup()`, and :php:func:`redirect()` to support protocol-relative URLs (e.g. *//ellislab.com/codeigniter*).
-      - Added an optional second parameter to both :php:func:`base_url()` and :php:func:`site_url()` that allows enforcing of a protocol different than the one in the *base_url* configuration setting.
 
    -  :doc:`HTML Helper <helpers/html_helper>` changes include:
 
@@ -128,6 +128,7 @@
 
       - Added *word_length* and *pool* options to allow customization of the generated word.
       - Added *colors* configuration to allow customization for the *background*, *border*, *text* and *grid* colors.
+      - Added *filename* to the returned array elements.
 
    -  :doc:`Directory Helper <helpers/directory_helper>` :php:func:`directory_map()` will now append ``DIRECTORY_SEPARATOR`` to directory names in the returned array.
    -  :doc:`Array Helper <helpers/array_helper>` :php:func:`element()` and :php:func:`elements()` now return NULL instead of FALSE when the required elements don't exist.
@@ -181,6 +182,7 @@
       - Server version checking is now done via ``mysqli::$server_info`` instead of running an SQL query.
       - Added persistent connections support for PHP >= 5.3.
       - Added support for ``backup()`` in :doc:`Database Utilities <database/utilities>`.
+      - Changed methods ``trans_begin()``, ``trans_commit()`` and ``trans_rollback()`` to use the PHP API instead of sending queries.	
 
    -  Improved support of the PDO driver, including:
 
@@ -198,6 +200,7 @@
       - Removed ``limit()`` and ``order_by()`` support for *UPDATE* and *DELETE* queries as PostgreSQL does not support those features.
       - Added a work-around for dead persistent connections to be re-created after a database restart.
       - Changed ``db_connect()`` to include the (new) **schema** value into Postgre's **search_path** session variable.
+      - ``pg_escape_literal()`` is now used for escaping strings, if available.
 
    -  Improved support of the CUBRID driver, including:
 
@@ -271,6 +274,7 @@
       -  Added the **min_width** and **min_height** options for images.
       -  Removed method ``clean_file_name()`` and its usage in favor of :doc:`Security Library <libraries/security>`'s ``sanitize_filename()``.
       -  Added **file_ext_tolower** config setting.
+      -  Added **mod_mime_fix** option to disable suffixing multiple file extensions with an underscore.
 
    -  :doc:`Cart library <libraries/cart>` changes include:
 
@@ -349,6 +353,7 @@
       -  Database object names are now being displayed.
       -  The sum of all queries running times in seconds is now being displayed.
       -  Added support for displaying the HTTP DNT ("Do Not Track") header.
+      -  Added support for displaying $_FILES.
 
    -  :doc:`Migration Library <libraries/migration>` changes include:
 
@@ -379,6 +384,7 @@
       -  Added support for model aliasing on autoload.
       -  Changed method ``is_loaded()`` to ask for the (case sensitive) library name instead of its instance name.
       -  Removed ``$_base_classes`` property and unified all class data in ``$_ci_classes`` instead.
+      -  Added method ``clear_vars()`` to allow clearing the cached variables for views.
 
    -  :doc:`Input Library <libraries/input>` changes include:
 
@@ -388,7 +394,10 @@
       -  Changed method ``valid_ip()`` to use PHP's native ``filter_var()`` function.
       -  Changed internal method ``_sanitize_globals()`` to skip enforcing reversal of *register_globals* in PHP 5.4+, where this functionality no longer exists.
       -  Changed methods ``get()``, ``post()``, ``get_post()``, ``cookie()``, ``server()``, ``user_agent()`` to return NULL instead of FALSE when no value is found.
+      -  Added method ``post_get()`` and changed ``get_post()`` to search in GET data first. Both methods' names now properly match their GET/POST data search priorities.
       -  Changed method ``_fetch_from_array()`` to parse array notation in field name.
+      -  Added an option for ``_clean_input_keys()`` to return FALSE instead of terminating the whole script.
+      -  Deprecated the ``is_cli_request()`` method, it is now an alias for the new :php:func:`is_cli()` common function.
 
    -  :doc:`Common functions <general/common_functions>` changes include:
 
@@ -397,7 +406,9 @@
       -  Removed redundant conditional to determine HTTP server protocol in :php:func:`set_status_header()`.
       -  Changed ``_exception_handler()`` to respect php.ini *display_errors* setting.
       -  Added function :php:func:`is_https()` to check if a secure connection is used.
+      -  Added function :php:func:`is_cli()` to replace the ``CI_Input::is_cli_request()`` method.
       -  Added function :php:func:`function_usable()` to check if a function exists and is not disabled by `Suhosin <http://www.hardened-php.net/suhosin/>`.
+      -  Removed the third (`$php_error`) from function :php:func:`log_message()`.
 
    -  :doc:`Output Library <libraries/output>` changes include:
 
@@ -410,15 +421,18 @@
       -  Changed ``site_url()`` method  to accept an array as well.
       -  Removed internal method ``_assign_to_config()`` and moved its implementation to *CodeIgniter.php* instead.
       -  ``item()`` now returns NULL instead of FALSE when the required config item doesn't exist.
+      -  Added an optional second parameter to both ``base_url()`` and ``site_url()`` that allows enforcing of a protocol different than the one in the *base_url* configuration setting.
 
    -  :doc:`Security Library <libraries/security>` changes include:
 
       -  Added method ``strip_image_tags()``.
       -  Added ``$config['csrf_regeneration']``, which makes token regeneration optional.
       -  Added ``$config['csrf_exclude_uris']``, which allows you list URIs which will not have the CSRF validation methods run.
+      -  Modified method ``sanitize_filename()`` to read a public ``$filename_bad_chars`` property for getting the invalid characters list.
 
    -  :doc:`URI Routing <general/routing>` changes include:
 
+      -  Added possibility to route requests using HTTP verbs.
       -  Added possibility to route requests using callbacks.
       -  Added a new reserved route (*translate_uri_dashes*) to allow usage of dashes in the controller and method URI segments.
       -  Deprecated methods ``fetch_directory()``, ``fetch_class()`` and ``fetch_method()`` in favor of their respective public properties.
@@ -434,6 +448,7 @@
    -  Added support for HTTP-Only cookies with new config option *cookie_httponly* (default FALSE).
    -  Renamed method ``_call_hook()`` to ``call_hook()`` in the :doc:`Hooks Library <general/hooks>`.
    -  ``$config['time_reference']`` now supports all timezone strings supported by PHP.
+   -  Fatal PHP errors are now also passed to ``_exception_handler()``, so they can be logged.
 
 
 Bug fixes for 3.0
@@ -462,7 +477,7 @@
 -  Fixed a possible bug in ``CI_Input::is_ajax_request()`` where some clients might not send the X-Requested-With HTTP header value exactly as 'XmlHttpRequest'.
 -  Fixed a bug (#1039) - MySQL's _backup() method failed due to a table name not being escaped.
 -  Fixed a bug (#1070) - CI_DB_driver::initialize() didn't set a character set if a database is not selected.
--  Fixed a bug (#177) - CI_Form_validation::set_value() didn't set the default value if POST data is NULL.
+-  Fixed a bug (#177) - ``CI_Form_validation::set_value()`` didn't set the default value if POST data is NULL.
 -  Fixed a bug (#68, #414) - Oracle's escape_str() didn't properly escape LIKE wild characters.
 -  Fixed a bug (#81) - ODBC's list_fields() and field_data() methods skipped the first column due to odbc_field_*() functions' index starting at 1 instead of 0.
 -  Fixed a bug (#129) - ODBC's num_rows() returned -1 in some cases, due to not all subdrivers supporting the odbc_num_rows() function.
@@ -514,7 +529,7 @@
 -  Fixed a bug (#784, #861) - :doc:`Database Forge <database/forge>` method ``create_table()`` used to accept constraints for MSSQL/SQLSRV integer-type columns.
 -  Fixed a bug (#706) - SQLSRV/MSSSQL didn't escape field names.
 -  Fixed a bug (#1452) - ``protect_identifiers()`` didn't properly detect identifiers with spaces in their names.
--  Fixed a bug where ``protect_identifiers()`` ignored it's extra arguments when the value passed to it is an array.
+-  Fixed a bug where ``protect_identifiers()`` ignored its extra arguments when the value passed to it is an array.
 -  Fixed a bug where ``_has_operator()`` didn't detect BETWEEN.
 -  Fixed a bug in :doc:`Query Builder <database/query_builder>`'s ``join()`` method where it failed with identifiers containing dashes.
 -  Fixed a bug (#1264) - :doc:`Database Forge <database/forge>` and :doc:`Database Utilities <database/utilities>` didn't update/reset the databases and tables list cache when a table or a database is created, dropped or renamed.
@@ -554,7 +569,7 @@
 -  Fixed a bug where the :doc:`Session Library <libraries/sessions>` accepted cookies with *last_activity* values being in the future.
 -  Fixed a bug (#1897) - :doc:`Email Library <libraries/email>` triggered PHP E_WARNING errors when *mail* protocol used and ``to()`` is never called.
 -  Fixed a bug (#1409) - :doc:`Email Library <libraries/email>` didn't properly handle multibyte characters when applying Q-encoding to headers.
--  Fixed a bug where :doc:`Email Library <libraries/email>` didn't honor it's *wordwrap* setting while handling alternative messages.
+-  Fixed a bug where :doc:`Email Library <libraries/email>` didn't honor its *wordwrap* setting while handling alternative messages.
 -  Fixed a bug (#1476, #1909) - :doc:`Pagination Library <libraries/pagination>` didn't take into account actual routing when determining the current page.
 -  Fixed a bug (#1766) - :doc:`Query Builder <database/query_builder>` didn't always take into account the *dbprefix* setting.
 -  Fixed a bug (#779) - :doc:`URI Class <libraries/uri>` didn't always trim slashes from the *uri_string* as shown in the documentation.
@@ -590,7 +605,7 @@
 -  Fixed a bug (#2239) - :doc:`Email Library <libraries/email>` improperly handled the Subject when used with ``bcc_batch_mode`` resulting in E_WARNING messages and an empty Subject.
 -  Fixed a bug (#2234) - :doc:`Query Builder <database/query_builder>` didn't reset JOIN cache for write-type queries.
 -  Fixed a bug (#2298) - :doc:`Database Results <database/results>` method ``next_row()`` kept returning the last row, allowing for infinite loops.
--  Fixed a bug (#2236) - :doc:`Form Helper <helpers/form_helper>` function ``set_value()`` didn't parse array notation for keys if the rule was not present in the :doc:`Form Validation Library <libraries/form_validation>`.
+-  Fixed a bug (#2236, #2639) - :doc:`Form Helper <helpers/form_helper>` functions :func:`set_value()`, :func:`set_select()`, :func:`set_radio()`, :func:`set_checkbox()` didn't parse array notation for keys if the rule was not present in the :doc:`Form Validation Library <libraries/form_validation>`.
 -  Fixed a bug (#2353) - :doc:`Query Builder <database/query_builder>` erroneously prefixed literal strings with **dbprefix**.
 -  Fixed a bug (#78) - :doc:`Cart Library <libraries/cart>` didn't allow non-English letters in product names.
 -  Fixed a bug (#77) - :doc:`Database Class <database/index>` didn't properly handle the transaction "test mode" flag.
@@ -598,11 +613,22 @@
 -  Fixed a bug (#2388) - :doc:`Email Library <libraries/email>` used to ignore attachment errors, resulting in broken emails being sent.
 -  Fixed a bug (#2498) - :doc:`Form Validation Library <libraries/form_validation>` rule **valid_base64** only checked characters instead of actual validity.
 -  Fixed a bug (#2425) - OCI8 :doc:`database <database>` driver's method ``stored_procedure()`` didn't log an error unless **db_debug** was set to TRUE.
--  Fixed a bug (#2490) - :doc:`Database Class <database/queries>` method ``query()`` returning boolean instead of a result object for PostgreSQL-specific *INSERT INTO ... RETURNING* statements.
+-  Fixed a bug (#2490) - :doc:`Database Class <database/queries>` method ``query()`` returning boolean instead of a result object when the PostgreSQL-specific *RETURNING* clause is used.
 -  Fixed a bug (#249) - :doc:`Cache Library <libraries/caching>` didn't properly handle Memcache(d) configurations with missing options.
 -  Fixed a bug (#180) - :php:func:`config_item()` didn't take into account run-time configuration changes.
--  Fixed a bug (#2551) - :doc:`Loader Library <libraries/loader>` method ``library()`` didn't properly check if a class that is being loaded already exits.
+-  Fixed a bug (#2551) - :doc:`Loader Library <libraries/loader>` method ``library()`` didn't properly check if a class that is being loaded already exists.
 -  Fixed a bug (#2560) - :doc:`Form Helper <helpers/form_helper>` function :php:func:`form_open()` set the 'method="post"' attribute only if the passed attributes equaled an empty string.
+-  Fixed a bug (#2585) - :doc:`Query Builder <database/query_builder>` methods ``min()``, ``max()``, ``avg()``, ``sum()`` didn't escape field names.
+-  Fixed an edge case (#2583) in the :doc:`Email Library <libraries/email>` where `Suhosin <http://www.hardened-php.net/suhosin/>` blocked messages sent via ``mail()`` due to trailing newspaces in headers.
+-  Fixed a bug (#2590) - :php:func:`log_message()` didn't actually cache the ``CI_Log`` class instance.
+-  Fixed a bug (#2609) - :php:func:`get_config()` optional argument was only effective on first function call. Also, it can now add items, in addition to updating existing items.
+-  Fixed a bug in the 'postgre' :doc:`database <database/index>` driver where the connection ID wasn't passed to ``pg_escape_string()``.
+-  Fixed a bug (#33) - Script execution was terminated when an invalid cookie key was encountered.
+-  Fixed a bug (#2681) - ``CI_Security::entity_decode()`` used the `PREG_REPLACE_EVAL` flag, which is deprecated since PHP 5.5.
+-  Fixed a bug (#2691) - nested transactions could end in a deadlock when an error is encountered with *db_debug* set to TRUE.
+-  Fixed a bug (#2515) - ``_exception_handler()`` used to send the 200 "OK" HTTP status code and didn't stop script exection even on fatal errors.
+-  Fixed a bug - Redis :doc:`Caching <libraries/caching>` driver didn't handle connection failures properly.
+-  Fixed a bug (#2756) - :doc:`Database Class <database/index>` executed the MySQL-specific `SET SESSION sql_mode` query for all drivers when the 'stricton' option is set.
 
 Version 2.1.4
 =============
@@ -682,7 +708,7 @@
 -  Fixed a bug (#538) - Windows paths were ignored when using the :doc:`Image Manipulation Library <libraries/image_lib>` to create a new file.
 -  Fixed a bug - When database caching was enabled, $this->db->query() checked the cache before binding variables which resulted in cached queries never being found.
 -  Fixed a bug - CSRF cookie value was allowed to be any (non-empty) string before being written to the output, making code injection a risk.
--  Fixed a bug (#726) - PDO put a 'dbname' argument in it's connection string regardless of the database platform in use, which made it impossible to use SQLite.
+-  Fixed a bug (#726) - PDO put a 'dbname' argument in its connection string regardless of the database platform in use, which made it impossible to use SQLite.
 -  Fixed a bug - ``CI_DB_pdo_driver::num_rows()`` was not returning properly value with SELECT queries, cause it was relying on ``PDOStatement::rowCount()``.
 -  Fixed a bug (#1059) - ``CI_Image_lib::clear()`` was not correctly clearing all necessary object properties, namely width and height.
 
@@ -759,7 +785,6 @@
    but the requested method did not.
 -  Fixed a bug (Reactor #89) where MySQL export would fail if the table
    had hyphens or other non alphanumeric/underscore characters.
--  Fixed a bug (#200) where MySQL queries would be malformed after calling $this->db->count_all() then $this->db->get()
 -  Fixed a bug (#105) that stopped query errors from being logged unless database debugging was enabled
 -  Fixed a bug (#160) - Removed unneeded array copy in the file cache
    driver.
@@ -780,7 +805,7 @@
 -  Fixed a bug (#537) - Support for all wav type in browser.
 -  Fixed a bug (#576) - Using ini_get() function to detect if apc is enabled or not.
 -  Fixed invalid date time format in :doc:`Date helper <helpers/date_helper>` and :doc:`XMLRPC library <libraries/xmlrpc>`.
--  Fixed a bug (#200) - MySQL queries would be malformed after calling count_all() then db->get().
+-  Fixed a bug (#200) - MySQL queries would be malformed after calling db->count_all() then db->get().
 
 Version 2.0.3
 =============
diff --git a/user_guide_src/source/database/query_builder.rst b/user_guide_src/source/database/query_builder.rst
index 65609c1..4800674 100644
--- a/user_guide_src/source/database/query_builder.rst
+++ b/user_guide_src/source/database/query_builder.rst
@@ -68,7 +68,7 @@
 	// Produces string: SELECT * FROM mytable
 
 The second parameter enables you to set whether or not the query builder query
-will be reset (by default it will be&mdash;just like `$this->db->get()`)::
+will be reset (by default it will be reset, just like when using `$this->db->get()`)::
 
 	echo $this->db->limit(10,20)->get_compiled_select('mytable', FALSE);
 	// Produces string: SELECT * FROM mytable LIMIT 20, 10
@@ -76,7 +76,7 @@
 
 	echo $this->db->select('title, content, date')->get_compiled_select();
 
-	// Produces string: SELECT title, content, date FROM mytable
+	// Produces string: SELECT title, content, date FROM mytable LIMIT 20, 10
 
 The key thing to notice in the above example is that the second query did not
 utilize `$this->db->from()`_ and did not pass a table name into the first
diff --git a/user_guide_src/source/general/cli.rst b/user_guide_src/source/general/cli.rst
index 4145d5c..4f3b07d 100644
--- a/user_guide_src/source/general/cli.rst
+++ b/user_guide_src/source/general/cli.rst
@@ -23,7 +23,7 @@
 
 -  Run your cron-jobs without needing to use *wget* or *curl*
 -  Make your cron-jobs inaccessible from being loaded in the URL by
-   checking for ``$this->input->is_cli_request()``
+   checking the return value of :func:`is_cli()`.
 -  Make interactive "tasks" that can do things like set permissions,
    prune cache folders, run backups, etc.
 -  Integrate with other applications in other languages. For example, a
diff --git a/user_guide_src/source/general/common_functions.rst b/user_guide_src/source/general/common_functions.rst
index 32e8a8b..2dfec9c 100644
--- a/user_guide_src/source/general/common_functions.rst
+++ b/user_guide_src/source/general/common_functions.rst
@@ -96,11 +96,10 @@
 log_message()
 =============
 
-.. php:function:: log_message($level, $message, $php_error = FALSE)
+.. php:function:: log_message($level, $message)
 
 	:param	string	$level: Log level: 'error', 'debug' or 'info'
 	:param	string	$message: Message to log
-	:param	bool	$php_error: Whether we're logging a native PHP error message
 	:returns:	void
 
 This function is an alias for ``CI_Log::write_log()``. For more info,
@@ -174,6 +173,19 @@
 Returns TRUE if a secure (HTTPS) connection is used and FALSE
 in any other case (including non-HTTP requests).
 
+is_cli()
+========
+
+.. php:function:: is_cli()
+
+	:returns:	bool
+
+Returns TRUE if the application is run through the command line
+and FALSE if not.
+
+.. note:: This function checks both if the ``PHP_SAPI`` value is 'cli'
+	or if the ``STDIN`` constant is defined.
+
 function_usable()
 =================
 
diff --git a/user_guide_src/source/general/routing.rst b/user_guide_src/source/general/routing.rst
index 5520f59..0b91d3f 100644
--- a/user_guide_src/source/general/routing.rst
+++ b/user_guide_src/source/general/routing.rst
@@ -142,6 +142,29 @@
 		return 'catalog/product_edit/' . strtolower($product_type) . '/' . $id;
 	};
 
+Using HTTP verbs in routes
+==========================
+
+It is possible to use HTTP verbs (request method) to define your routing rules.
+This is particularly useful when building RESTful applications. You can use standard HTTP
+verbs (GET, PUT, POST, DELETE, PATCH) or a custom one such (e.g. PURGE). HTTP verb rules
+are case-insensitive. All you need to do is to add the verb as an array key to your route.
+Example::
+
+	$route['products']['put'] = 'product/insert';
+
+In the above example, a PUT request to URI "products" would call the ``Product::insert()``
+controller method.
+
+::
+
+	$route['products/(:num)']['DELETE'] = 'product/delete/$1';
+
+A DELETE request to URL with "products" as first the segment and a number in the second will be
+mapped to the ``Product::delete()`` method, passing the numeric value as the first parameter.
+
+Using HTTP verbs is of course, optional.
+
 Reserved Routes
 ===============
 
diff --git a/user_guide_src/source/helpers/captcha_helper.rst b/user_guide_src/source/helpers/captcha_helper.rst
index 3c56add..f471734 100644
--- a/user_guide_src/source/helpers/captcha_helper.rst
+++ b/user_guide_src/source/helpers/captcha_helper.rst
@@ -26,7 +26,7 @@
 	:param	string	$img_path: Path to create the image in
 	:param	string	$img_url: URL to the CAPTCHA image folder
 	:param	string	$font_path: Server path to font
-	:returns:	array('word' => $word, 'time' => $now, 'image' => $img)
+	:returns:	array
 
 Takes an array of information to generate the CAPTCHA as input and
 creates the image to your specifications, returning an array of
@@ -35,9 +35,10 @@
 ::
 
 	array(
-		'image'	=> IMAGE TAG
-		'time'	=> TIMESTAMP (in microtime)
-		'word'	=> CAPTCHA WORD
+		'word'     => CAPTCHA WORD,
+		'time'     => TIMESTAMP (in microtime),
+		'image'    => IMAGE TAG,
+		'filename' => IMAGE FILE NAME
 	)
 
 The **image** is the actual image tag::
diff --git a/user_guide_src/source/helpers/date_helper.rst b/user_guide_src/source/helpers/date_helper.rst
index 5dfee8b..8126eba 100644
--- a/user_guide_src/source/helpers/date_helper.rst
+++ b/user_guide_src/source/helpers/date_helper.rst
@@ -80,7 +80,7 @@
 	$time = time();
 	echo standard_date($format, $time);
 
-.. note:: This function is DEPRECATED.Use the native ``date()`` combined with
+.. note:: This function is DEPRECATED. Use the native ``date()`` combined with
 	`DateTime's format constants
 	<http://www.php.net/manual/en/class.datetime.php#datetime.constants.types>`_
 	instead:
diff --git a/user_guide_src/source/helpers/smiley_helper.rst b/user_guide_src/source/helpers/smiley_helper.rst
index 3925f8b..cfd52ff 100644
--- a/user_guide_src/source/helpers/smiley_helper.rst
+++ b/user_guide_src/source/helpers/smiley_helper.rst
@@ -17,7 +17,7 @@
 Overview
 ========
 
-The Smiley helper has a renderer that takes plain text simileys, like
+The Smiley helper has a renderer that takes plain text smileys, like
 :-) and turns them into a image representation, like |smile!|
 
 It also lets you display a set of smiley images that when clicked will
@@ -44,7 +44,7 @@
 --------------
 
 In your **application/controllers/** directory, create a file called
-smileys.php and place the code below in it.
+Smileys.php and place the code below in it.
 
 .. important:: Change the URL in the :php:func:`get_clickable_smileys()`
 	function below so that it points to your smiley folder.
@@ -156,7 +156,7 @@
 
 Example::
 
-	$str = 'Here are some simileys: :-)  ;-)';
+	$str = 'Here are some smileys: :-)  ;-)';
 	$str = parse_smileys($str, "http://example.com/images/smileys/");
 	echo $str;
 
diff --git a/user_guide_src/source/installation/downloads.rst b/user_guide_src/source/installation/downloads.rst
index 8d47ba3..93c5cc2 100644
--- a/user_guide_src/source/installation/downloads.rst
+++ b/user_guide_src/source/installation/downloads.rst
@@ -3,35 +3,37 @@
 #######################
 
 -  `CodeIgniter v3.0.0 (Current version) <http://ellislab.com/codeigniter/download>`_
--  `CodeIgniter v2.1.4 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.4.zip>`_
--  `CodeIgniter v2.1.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.3.zip>`_
--  `CodeIgniter v2.1.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.2.zip>`_
--  `CodeIgniter v2.1.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.1.zip>`_
--  `CodeIgniter v2.1.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.0.zip>`_
--  `CodeIgniter v2.0.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.3.zip>`_
--  `CodeIgniter v2.0.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.2.zip>`_
--  `CodeIgniter v2.0.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.1.zip>`_
--  `CodeIgniter v2.0.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.0.zip>`_
--  `CodeIgniter v1.7.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.3.zip>`_
--  `CodeIgniter v1.7.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.2.zip>`_
--  `CodeIgniter v1.7.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.1.zip>`_
--  `CodeIgniter v1.7.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.0.zip>`_
--  `CodeIgniter v1.6.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.3.zip>`_
--  `CodeIgniter v1.6.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.2.zip>`_
--  `CodeIgniter v1.6.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.1.zip>`_
--  `CodeIgniter v1.6.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.0.zip>`_
--  `CodeIgniter v1.5.4 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.4.zip>`_
--  `CodeIgniter v1.5.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.3.zip>`_
--  `CodeIgniter v1.5.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.2.zip>`_
--  `CodeIgniter v1.5.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.1.zip>`_
--  `CodeIgniter v1.4.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.4.1.zip>`_
--  `CodeIgniter v1.3.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.3.zip>`_
--  `CodeIgniter v1.3.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.2.zip>`_
--  `CodeIgniter v1.3.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.1.zip>`_
--  `CodeIgniter v1.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.zip>`_
--  `CodeIgniter v1.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.2.zip>`_
--  `CodeIgniter v1.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.1b.zip>`_
--  `CodeIgniter v1.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.0b.zip>`_
+-  `CodeIgniter v2.1.4 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.4.zip>`_ (MD5 Checksum: e74a296c1d412a855c025b9cd468a513)
+-  `CodeIgniter v2.1.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.3.zip>`_ (MD5 Checksum: 781d06be06eaa36f10759ef82c8594d5)
+-  `CodeIgniter v2.1.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.2.zip>`_ (MD5 Checksum: c7a2980dff2774c97bd38bfbf450d8d5)
+-  `CodeIgniter v2.1.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.1.zip>`_ (MD5 Checksum: c4aa5f188f4ff16f919607b46a16c76c)
+-  `CodeIgniter v2.1.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.1.0.zip>`_ (MD5 Checksum: 8cb676b0f831114935d7dd1ae2e0d490)
+-  `CodeIgniter v2.0.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.3.zip>`_ (MD5 Checksum: 910475d50daf088bdd949c3d35b444d9)
+-  `CodeIgniter v2.0.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.2.zip>`_ (MD5 Checksum: e75bab8cf27d2fb2483c5bb61b85a524)
+-  `CodeIgniter v2.0.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.1.zip>`_ (MD5 Checksum: 675aa95896bfb16467436c0484f15f1f)
+-  `CodeIgniter v2.0.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_2.0.0.zip>`_ (MD5 Checksum: bd657863de45dbb397f3b3dbc4f13abb)
+-  `CodeIgniter v1.7.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.3.zip>`_ (MD5 Checksum: 16f50e7df4f44c1defe18355131049e9)
+-  `CodeIgniter v1.7.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.2.zip>`_ (MD5 Checksum: ff2f4d1b3ab921f91e006f38b3ae6540)
+-  `CodeIgniter v1.7.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.1.zip>`_ (MD5 Checksum: deca9709cf21b26dc0e4ec040b37e866)
+-  `CodeIgniter v1.7.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.7.0.zip>`_ (MD5 Checksum: 28037f2071f940d8756864460d949045)
+-  `CodeIgniter v1.6.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.3.zip>`_ (MD5 Checksum: 5ffab52b39b235ed6bd08ee5dd64d2f6)
+-  `CodeIgniter v1.6.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.2.zip>`_ (MD5 Checksum: 0922830f96dfd40874b39ad018a49206)
+-  `CodeIgniter v1.6.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.1.zip>`_ (MD5 Checksum: cc3f0b566e3654d351fa067aeee9bced)
+-  `CodeIgniter v1.6.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.6.0.zip>`_ (MD5 Checksum: 89efabb8c1d57bb51071e6a20bb5590d)
+-  `CodeIgniter v1.5.4 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.4.zip>`_ (MD5 Checksum: 0d6cc66b01d5ddecde483b3d5f51e4f8)
+-  `CodeIgniter v1.5.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.3.zip>`_ (MD5 Checksum: f44dd21d34a2842bd052879ca5de6630)
+-  `CodeIgniter v1.5.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.2.zip>`_ (MD5 Checksum: 78e7106b271f75af48e626f6e923c1aa)
+-  `CodeIgniter v1.5.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.1.zip>`_ (MD5 Checksum: 9dfd0dbed4f283a42a817e1e88f97481)
+-  `CodeIgniter v1.5.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.5.0.zip>`_ (MD5 Checksum: 116b805eae4b7e78ddd43a8aee733632)
+-  `CodeIgniter v1.4.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.4.1.zip>`_ (MD5 Checksum: 470005a83772e9d2e99dec2b4058e584)
+-  `CodeIgniter v1.4.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.4.0.zip>`_ (MD5 Checksum: 43ca6ff3447d6b5681f98a328b386338)
+-  `CodeIgniter v1.3.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.3.zip>`_ (MD5 Checksum: 55692ba4b55b53b58e4514e310288981)
+-  `CodeIgniter v1.3.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.2.zip>`_ (MD5 Checksum: 7dace6e1d6245b569943e8df952c7637)
+-  `CodeIgniter v1.3.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.1.zip>`_ (MD5 Checksum: f6c6f00830c60d7f98b948269ee81069)
+-  `CodeIgniter v1.3 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.3.zip>`_ (MD5 Checksum: 03b2f796df6af808ecff3a18b6000477)
+-  `CodeIgniter v1.2 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.2.zip>`_ (MD5 Checksum: f9289814fabe102bc35beb791d0c0f62)
+-  `CodeIgniter v1.1 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.1b.zip>`_ (MD5 Checksum: bf4cabb6a3ea3122a974270b8044befb)
+-  `CodeIgniter v1.0 <http://ellislab.com/asset/ci_download_files/CodeIgniter_1.0b.zip>`_ (MD5 Checksum: 427ca4255e2bdaacee976de1aa143ea0)
 
 
 ******
diff --git a/user_guide_src/source/installation/upgrade_300.rst b/user_guide_src/source/installation/upgrade_300.rst
index 0eafaf9..ec80e80 100644
--- a/user_guide_src/source/installation/upgrade_300.rst
+++ b/user_guide_src/source/installation/upgrade_300.rst
@@ -119,11 +119,18 @@
 	// $active_record = TRUE;
 	$query_builder = TRUE;
 
-*******************************************
-Step 8: Move your error templates directory
-*******************************************
+************************************
+Step 8: Replace your error templates
+************************************
 
-In version 3.0.0, the errors folder has been moved from _application/errors* to _application/views/errors*.
+In CodeIgniter 3.0, the error templates are now considered as views and have been moved to the
+_application/views/errors* directory.
+
+Furthermore, we've added support for CLI error templates in plain-text format that unlike HTML,
+is suitable for the command line. This of course requires another level of separation.
+
+It is safe to move your old templates from _application/errors* to _application/views/errors/html*,
+but you'll have to copy the new _application/views/errors/cli* directory from the CodeIgniter archive.
 
 *******************************************************
 Step 9: Update your config/routes.php containing (:any)
@@ -145,22 +152,55 @@
 	(.+)	// matches ANYTHING
 	(:any)	// matches any character, except for '/'
 
-*************************************************
-Step 10: Check the calls to config->item() method
-*************************************************
+*************************************************************************
+Step 10: Many functions now return NULL instead of FALSE on missing items
+*************************************************************************
 
-This method now returns NULL instead of FALSE when the required config
-item doesn't exist.
+Many methods and functions now return NULL instead of FALSE when the required items don't exist:
 
-*****************************************************************************
-Step 11: Check the calls to Array Helper's element() and elements() functions
-*****************************************************************************
+ - :doc:`Config Class <../libraries/config>`
 
-The default return value of these functions, when the required elements
-don't exist, has been changed from FALSE to NULL.
+   - config->item()
+   - config->slash_item()
+
+ - :doc:`Input Class <../libraries/input>`
+
+   - input->get()
+   - input->post()
+   - input->get_post()
+   - input->cookie()
+   - input->server()
+   - input->input_stream()
+   - input->get_request_header()
+
+ - :doc:`Session Class <../libraries/sessions>`
+
+   - session->userdata()
+   - session->flashdata()
+
+ - :doc:`URI Class <../libraries/uri>`
+
+   - uri->segment()
+   - uri->rsegment()
+
+ - :doc:`Array Helper <../helpers/array_helper>`
+
+   - element()
+   - elements()
+
+********************************************************
+Step 11: Update usage of Input Class's get_post() method
+********************************************************
+
+Previously, the :doc:`Input Class <../libraries/input>` method ``get_post()``
+was searching first in POST data, then in GET data. This method has been
+modified so that it searches in GET then in POST, as its name suggests.
+
+A method has been added, ``post_get()``, which searches in POST then in GET, as
+``get_post()`` was doing before.
 
 ***********************************************************************
-Step 12: Check the calls to Directory Helper's directory_map() function
+Step 12: Update usage of Directory Helper's directory_map() function
 ***********************************************************************
 
 In the resulting array, directories now end with a trailing directory
@@ -185,7 +225,7 @@
 	// Produces DROP TABLE IF EXISTS `table_name`
 	$this->dbforge->drop_table('table_name', TRUE);
 
-.. note:: The given example users MySQL-specific syntax, but it should work across
+.. note:: The given example uses MySQL-specific syntax, but it should work across
 	all drivers with the exception of ODBC.
 
 ***********************************************************
@@ -424,4 +464,28 @@
 	$this->router->method;
 
 .. note:: Those methods are still available, but you're strongly encouraged to remove their usage
+	sooner rather than later.
+
+Input library method is_cli_request()
+=====================================
+
+Calls to the ``CI_Input::is_cli_request()`` method are necessary at many places
+in the CodeIgniter internals and this is often before the :doc:`Input Library
+<../libraries/input>` is loaded. Because of that, it is being replaced by a common
+function named :php:func:`is_cli()` and this method is now just an alias.
+
+The new function is both available at all times for you to use and shorter to type.
+
+::
+
+	// Old
+	$this->input->is_cli_request();
+
+	// New
+	is_cli();
+
+``CI_Input::is_cli_request()`` is now now deprecated and scheduled for removal in
+CodeIgniter 3.1+.
+
+.. note:: This method is still available, but you're strongly encouraged to remove its usage
 	sooner rather than later.
\ No newline at end of file
diff --git a/user_guide_src/source/libraries/caching.rst b/user_guide_src/source/libraries/caching.rst
index 8d7b4c4..3f7dc2d 100644
--- a/user_guide_src/source/libraries/caching.rst
+++ b/user_guide_src/source/libraries/caching.rst
@@ -239,17 +239,28 @@
 Redis Caching
 =============
 
+Redis is an in-memory key-value store which can operate in LRU cache mode. 
+To use it, you need Redis server and phpredis PHP extension 
+`https://github.com/nicolasff/phpredis <https://github.com/nicolasff/phpredis>`_.
+
+Config options to connect to redis server must be stored in the application/config/redis.php file.
+Available options are::
+	
+	$config['socket_type'] = 'tcp'; //`tcp` or `unix`
+	$config['socket'] = '/var/run/redis.sock'; // in case of `unix` socket type
+	$config['host'] = '127.0.0.1';
+	$config['password'] = NULL;
+	$config['port'] = 6379;
+	$config['timeout'] = 0;
+
 All of the methods listed above can be accessed without passing a
 specific adapter to the driver loader as follows::
 
 	$this->load->driver('cache');
 	$this->cache->redis->save('foo', 'bar', 10);
 
-.. important:: Redis may require one or more of the following options:
-	**host**, **post**, **timeout**, **password**.
-
-The Redis PHP extension repository is located at
-`https://github.com/nicolasff/phpredis <https://github.com/nicolasff/phpredis>`_.
+For more information on Redis, please see
+`http://redis.io <http://redis.io>`_.
 
 Dummy Cache
 ===========
diff --git a/user_guide_src/source/libraries/file_uploading.rst b/user_guide_src/source/libraries/file_uploading.rst
index a295d74..ac56fab 100644
--- a/user_guide_src/source/libraries/file_uploading.rst
+++ b/user_guide_src/source/libraries/file_uploading.rst
@@ -224,6 +224,11 @@
 **detect_mime**              TRUE              TRUE/FALSE (boolean)    If set to TRUE, a server side detection of the file type will be
                                                                        performed to avoid code injection attacks. DO NOT disable this option
                                                                        unless you have no other option as that would cause a security risk.
+**mod_mime_fix**             TRUE              TRUE/FALSE (boolean)    If set to TRUE, multiple filename extensions will be suffixed with an
+                                                                       underscore in order to avoid triggering `Apache mod_mime
+                                                                       <http://httpd.apache.org/docs/2.0/mod/mod_mime.html#multipleext>`_.
+                                                                       DO NOT turn off this option if your upload directory is public, as this
+                                                                       is a security risk.
 ============================ ================= ======================= ======================================================================
 
 Setting preferences in a config file
diff --git a/user_guide_src/source/libraries/form_validation.rst b/user_guide_src/source/libraries/form_validation.rst
index 8b35fdc..8534175 100644
--- a/user_guide_src/source/libraries/form_validation.rst
+++ b/user_guide_src/source/libraries/form_validation.rst
@@ -431,7 +431,7 @@
 			}
 		}
 
-		protected function username_check($str)
+		public function username_check($str)
 		{
 			if ($str == 'test')
 			{
@@ -866,6 +866,7 @@
 **is_unique**             Yes        Returns FALSE if the form element is not unique to the table and field name in the            is_unique[table.field] 
                                      parameter. Note: This rule requires :doc:`Query Builder <../database/query_builder>` to be                             
                                      enabled in order to work.
+**min_length**            Yes        Returns FALSE if the form element is shorter then the parameter value.                        min_length[3]         
 **max_length**            Yes        Returns FALSE if the form element is longer then the parameter value.                         max_length[12]         
 **exact_length**          Yes        Returns FALSE if the form element is not exactly the parameter value.                         exact_length[8]        
 **greater_than**          Yes        Returns FALSE if the form element is less than or equal to the parameter value or not         greater_than[8]
diff --git a/user_guide_src/source/libraries/input.rst b/user_guide_src/source/libraries/input.rst
index 177f5cb..b58ed2f 100644
--- a/user_guide_src/source/libraries/input.rst
+++ b/user_guide_src/source/libraries/input.rst
@@ -98,7 +98,7 @@
 $this->input->get()
 ===================
 
-This method is identical to the post method, only it fetches get data
+This method is identical to the POST method, only it fetches GET data
 ::
 
 	$this->input->get('some_data', TRUE);
@@ -116,18 +116,26 @@
 	$this->input->get(); // returns all GET items without XSS filtering
 
 
+$this->input->post_get()
+========================
+
+This method will search through both the POST and GET streams for
+data, looking first in POST, and then in GET::
+
+	$this->input->post_get('some_data', TRUE);
+
 $this->input->get_post()
 ========================
 
-This method will search through both the post and get streams for
-data, looking first in post, and then in get::
+This method will search through both the POST and GET streams for
+data, looking first in GET, and then in POST::
 
 	$this->input->get_post('some_data', TRUE);
 
 $this->input->cookie()
 ======================
 
-This method is identical to the post method, only it fetches cookie data
+This method is identical to the POST method, only it fetches cookie data
 ::
 
 	$this->input->cookie('some_cookie');
@@ -307,6 +315,9 @@
 
 	$this->input->is_cli_request()
 
+.. note:: This method is DEPRECATED and is now just an alias for the
+	:php:func:`is_cli()` function.
+
 $this->input->method()
 ======================
 
diff --git a/user_guide_src/source/libraries/loader.rst b/user_guide_src/source/libraries/loader.rst
index 19446a9..91db5af 100644
--- a/user_guide_src/source/libraries/loader.rst
+++ b/user_guide_src/source/libraries/loader.rst
@@ -234,6 +234,11 @@
 
 This method retrieves all variables available to your views.
 
+$this->load->clear_vars()
+=========================
+
+Clears cached view variables.
+
 $this->load->helper('file_name')
 ================================
 
diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst
index 36c7c1d..2f8bea0 100644
--- a/user_guide_src/source/libraries/sessions.rst
+++ b/user_guide_src/source/libraries/sessions.rst
@@ -252,7 +252,7 @@
 ===================
 
 You'll find the following Session related preferences in your
-application/config/config.php file:
+*application/config/config.php* file:
 
 =========================== =============== =========================== ==========================================================================
 Preference                  Default         Options                     Description
@@ -271,7 +271,8 @@
                                                                         table before enabling this option (Cookie driver only).
 **sess_table_name**         ci_sessions     Any valid SQL table name    The name of the session database table (Cookie driver only).
 **sess_time_to_update**     300             Time in seconds             This options controls how often the session class will regenerate itself
-                                                                        and create a new session id.
+                                                                        and create a new session ID. Setting it to 0 will disable session
+                                                                        ID regeneartion.
 **sess_match_ip**           FALSE           TRUE/FALSE (boolean)        Whether to match the user's IP address when reading the session data.
                                                                         Note that some ISPs dynamically changes the IP, so if you want a
                                                                         non-expiring session you will likely set this to FALSE.
diff --git a/user_guide_src/source/tutorial/news_section.rst b/user_guide_src/source/tutorial/news_section.rst
index c21f4e6..ad9ed41 100644
--- a/user_guide_src/source/tutorial/news_section.rst
+++ b/user_guide_src/source/tutorial/news_section.rst
@@ -127,7 +127,7 @@
 
 	public function index()
 	{
-		data['news'] = $this->news_model->get_news();
+		$data['news'] = $this->news_model->get_news();
 		$data['title'] = 'News archive';
 
 		$this->load->view('templates/header', $data);