Merge pull request #1550 from krynble/develop

Fixing imagemagick maintain ratio not implemented
diff --git a/system/core/Security.php b/system/core/Security.php
index 227217e..b22d2cf 100644
--- a/system/core/Security.php
+++ b/system/core/Security.php
@@ -395,20 +395,20 @@
 
 			if (preg_match('/<a/i', $str))
 			{
-				$str = preg_replace_callback('#<a\s+([^>]*?)(>|$)#si', array($this, '_js_link_removal'), $str);
+				$str = preg_replace_callback('#<a\s+([^>]*?)(?:>|$)#si', array($this, '_js_link_removal'), $str);
 			}
 
 			if (preg_match('/<img/i', $str))
 			{
-				$str = preg_replace_callback('#<img\s+([^>]*?)(\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
+				$str = preg_replace_callback('#<img\s+([^>]*?)(?:\s?/?>|$)#si', array($this, '_js_img_removal'), $str);
 			}
 
-			if (preg_match('/(script|xss)/i', $str))
+			if (preg_match('/script|xss/i', $str))
 			{
-				$str = preg_replace('#<(/*)(script|xss)(.*?)\>#si', '[removed]', $str);
+				$str = preg_replace('#</*(?:script|xss).*?>#si', '[removed]', $str);
 			}
 		}
-		while($original !== $str);
+		while ($original !== $str);
 
 		unset($original);
 
@@ -683,7 +683,7 @@
 	protected function _js_link_removal($match)
 	{
 		return str_replace($match[1],
-					preg_replace('#href=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
+					preg_replace('#href=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|data\s*:)#si',
 							'',
 							$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
 					),
@@ -706,7 +706,7 @@
 	protected function _js_img_removal($match)
 	{
 		return str_replace($match[1],
-					preg_replace('#src=.*?(alert\(|alert&\#40;|javascript\:|livescript\:|mocha\:|charset\=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
+					preg_replace('#src=.*?(?:alert\(|alert&\#40;|javascript:|livescript:|mocha:|charset=|window\.|document\.|\.cookie|<script|<xss|base64\s*,)#si',
 							'',
 							$this->_filter_attributes(str_replace(array('<', '>'), '', $match[1]))
 					),
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 380bbc3..334bdbd 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -982,11 +982,15 @@
 		{
 			if (is_array($this->_escape_char))
 			{
-				$preg_ec = array(preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1]));
+				$preg_ec = array(
+						preg_quote($this->_escape_char[0]), preg_quote($this->_escape_char[1]),
+						$this->_escape_char[0], $this->_escape_char[1]
+						);
 			}
 			else
 			{
 				$preg_ec[0] = $preg_ec[1] = preg_quote($this->_escape_char);
+				$preg_ec[2] = $preg_ec[3] = $this->_escape_char;
 			}
 		}
 
@@ -994,11 +998,11 @@
 		{
 			if (strpos($item, '.'.$id) !== FALSE)
 			{
-				return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[0].'$1'.$preg_ec[1].'.', $item);
+				return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?\./i', $preg_ec[2].'$1'.$preg_ec[3].'.', $item);
 			}
 		}
 
-		return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[0].'$1'.$preg_ec[1].'$2', $item);
+		return preg_replace('/'.$preg_ec[0].'?([^'.$preg_ec[1].'\.]+)'.$preg_ec[1].'?(\.)?/i', $preg_ec[2].'$1'.$preg_ec[3].'$2', $item);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index 7634be2..3026b36 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -83,11 +83,27 @@
 	/**
 	 * Non-persistent database connection
 	 *
+	 * @param	bool
 	 * @return	resource
 	 */
-	public function db_connect()
+	public function db_connect($persistent = FALSE)
 	{
-		return $this->_mssql_connect();
+		$this->conn_id = ($persistent)
+				? @mssql_pconnect($this->hostname, $this->username, $this->password)
+				: @mssql_connect($this->hostname, $this->username, $this->password);
+
+		if ( ! $this->conn_id)
+		{
+			return FALSE;
+		}
+
+		// Determine how identifiers are escaped
+		$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
+		$query = $query->row_array();
+		$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
+		$this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
+
+		return $this->conn_id;
 	}
 
 	// --------------------------------------------------------------------
@@ -99,35 +115,7 @@
 	 */
 	public function db_pconnect()
 	{
-		return $this->_mssql_connect(TRUE);
-	}
-
-	// --------------------------------------------------------------------
-
-	/*
-	 * MSSQL Connect
-	 *
-	 * @param	bool
-	 * @return	resource
-	 */
-	protected function _mssql_connect($persistent = FALSE)
-	{
-		$conn_id = ($persistent)
-				? @mssql_pconnect($this->hostname, $this->username, $this->password)
-				: @mssql_connect($this->hostname, $this->username, $this->password);
-
-		if ( ! $conn_id)
-		{
-			return FALSE;
-		}
-
-		// Determine how identifiers are escaped
-		$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
-		$query = $query->row_array();
-		$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
-		$this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
-
-		return $conn_id;
+		return $this->db_connect(TRUE);
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlsrv/sqlsrv_driver.php b/system/database/drivers/sqlsrv/sqlsrv_driver.php
index 4fdc4aa..12482de 100644
--- a/system/database/drivers/sqlsrv/sqlsrv_driver.php
+++ b/system/database/drivers/sqlsrv/sqlsrv_driver.php
@@ -86,7 +86,7 @@
 			unset($connection['UID'], $connection['PWD']);
 		}
 
-		$conn_id = sqlsrv_connect($this->hostname, $connection);
+		$this->conn_id = sqlsrv_connect($this->hostname, $connection);
 
 		// Determine how identifiers are escaped
 		$query = $this->query('SELECT CASE WHEN (@@OPTIONS | 256) = @@OPTIONS THEN 1 ELSE 0 END AS qi');
@@ -94,7 +94,7 @@
 		$this->_quoted_identifier = empty($query) ? FALSE : (bool) $query['qi'];
 		$this->_escape_char = ($this->_quoted_identifier) ? '"' : array('[', ']');
 
-		return $conn_id;
+		return $this->conn_id;
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/helpers/array_helper.php b/system/helpers/array_helper.php
index 6a7c8e3..5d02439 100644
--- a/system/helpers/array_helper.php
+++ b/system/helpers/array_helper.php
@@ -43,14 +43,14 @@
 	 * Element
 	 *
 	 * Lets you determine whether an array index is set and whether it has a value.
-	 * If the element is empty it returns FALSE (or whatever you specify as the default value.)
+	 * If the element is empty it returns NULL (or whatever you specify as the default value.)
 	 *
 	 * @param	string
 	 * @param	array
 	 * @param	mixed
 	 * @return	mixed	depends on what the array contains
 	 */
-	function element($item, $array, $default = FALSE)
+	function element($item, $array, $default = NULL)
 	{
 		return empty($array[$item]) ? $default : $array[$item];
 	}
@@ -87,7 +87,7 @@
 	 * @param	mixed
 	 * @return	mixed	depends on what the array contains
 	 */
-	function elements($items, $array, $default = FALSE)
+	function elements($items, $array, $default = NULL)
 	{
 		$return = array();
 
diff --git a/system/helpers/date_helper.php b/system/helpers/date_helper.php
index fc790c5..9637e26 100644
--- a/system/helpers/date_helper.php
+++ b/system/helpers/date_helper.php
@@ -124,16 +124,16 @@
 	function standard_date($fmt = 'DATE_RFC822', $time = '')
 	{
 		$formats = array(
-				'DATE_ATOM'		=>	'%Y-%m-%dT%H:%i:%s%O',
+				'DATE_ATOM'		=>	'%Y-%m-%dT%H:%i:%s%P',
 				'DATE_COOKIE'	=>	'%l, %d-%M-%y %H:%i:%s UTC',
-				'DATE_ISO8601'	=>	'%Y-%m-%dT%H:%i:%s%O',
+				'DATE_ISO8601'	=>	'%Y-%m-%dT%H:%i:%s%P',
 				'DATE_RFC822'	=>	'%D, %d %M %y %H:%i:%s %O',
 				'DATE_RFC850'	=>	'%l, %d-%M-%y %H:%i:%s UTC',
 				'DATE_RFC1036'	=>	'%D, %d %M %y %H:%i:%s %O',
 				'DATE_RFC1123'	=>	'%D, %d %M %Y %H:%i:%s %O',
-				'DATE_RFC2822'	=>	'%D, %d %M %Y %H:%i:%s %O',
+				'DATE_RFC2822'	=>	'%r',
 				'DATE_RSS'		=>	'%D, %d %M %Y %H:%i:%s %O',
-				'DATE_W3C'		=>	'%Y-%m-%dT%H:%i:%s%O'
+				'DATE_W3C'		=>	'%Y-%m-%dT%H:%i:%s%P'
 				);
 
 		return isset($formats[$fmt]) ? mdate($formats[$fmt], $time) : FALSE;
diff --git a/system/libraries/Session.php b/system/libraries/Session.php
index 72a942b..af38dc3 100644
--- a/system/libraries/Session.php
+++ b/system/libraries/Session.php
@@ -155,12 +155,6 @@
 	 */
 	public $time_reference			= 'local';
 
-	/**
-	 * Probablity level of garbage collection of old sessions
-	 *
-	 * @var int
-	 */
-	public $gc_probability			= 5;
 
 	/**
 	 * Session data
@@ -940,8 +934,11 @@
 			return;
 		}
 
+		$probability = ini_get('session.gc_probability');
+		$divisor = ini_get('session.gc_divisor');
+
 		srand(time());
-		if ((rand() % 100) < $this->gc_probability)
+		if ((mt_rand(0, $divisor) / $divisor) < $probability)
 		{
 			$expire = $this->now - $this->sess_expiration;
 
diff --git a/system/libraries/Xmlrpc.php b/system/libraries/Xmlrpc.php
index eac4ac1..cbb91c4 100644
--- a/system/libraries/Xmlrpc.php
+++ b/system/libraries/Xmlrpc.php
@@ -174,7 +174,7 @@
 	 * @param	int	port
 	 * @return	void
 	 */
-	public function server($url, $port = 80)
+	public function server($url, $port = 80, $proxy = FALSE, $proxy_port = 8080)
 	{
 		if (strpos($url, 'http') !== 0)
 		{
@@ -190,7 +190,7 @@
 			$path .= '?'.$parts['query'];
 		}
 
-		$this->client = new XML_RPC_Client($path, $parts['host'], $port);
+		$this->client = new XML_RPC_Client($path, $parts['host'], $port, $proxy, $proxy_port);
 	}
 
 	// --------------------------------------------------------------------
@@ -385,6 +385,8 @@
 	public $path			= '';
 	public $server			= '';
 	public $port			= 80;
+	public $proxy			= FALSE;
+	public $proxy_port		= 8080;
 	public $errno			= '';
 	public $errstring		= '';
 	public $timeout		= 5;
@@ -398,13 +400,15 @@
 	 * @param	int
 	 * @return	void
 	 */
-	public function __construct($path, $server, $port = 80)
+	public function __construct($path, $server, $port = 80, $proxy = FALSE, $proxy_port = 8080)
 	{
 		parent::__construct();
 
 		$this->port = $port;
 		$this->server = $server;
 		$this->path = $path;
+		$this->proxy = $proxy;
+		$this->proxy_port = $proxy_port;
 	}
 
 	// --------------------------------------------------------------------
@@ -436,7 +440,18 @@
 	 */
 	public function sendPayload($msg)
 	{
-		$fp = @fsockopen($this->server, $this->port,$this->errno, $this->errstring, $this->timeout);
+		if ($this->proxy === FALSE)
+		{
+			$server = $this->server;
+			$port = $this->port;
+		}
+		else
+		{
+			$server = $this->proxy;
+			$port = $this->proxy_port;
+		}
+
+		$fp = @fsockopen($server, $port, $this->errno, $this->errstring, $this->timeout);
 
 		if ( ! is_resource($fp))
 		{
diff --git a/tests/codeigniter/helpers/date_helper_test.php b/tests/codeigniter/helpers/date_helper_test.php
index 4e01b1a..eaf4cf8 100644
--- a/tests/codeigniter/helpers/date_helper_test.php
+++ b/tests/codeigniter/helpers/date_helper_test.php
@@ -79,7 +79,7 @@
 	public function test_standard_date_atom()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date('Y-m-d\TH:i:sP', $this->time),
 			standard_date('DATE_ATOM', $this->time)
 		);
 	}
@@ -99,7 +99,7 @@
 	public function test_standard_date_iso8601()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date('Y-m-d\TH:i:sP', $this->time),
 			standard_date('DATE_ISO8601', $this->time)
 		);
 	}
@@ -139,7 +139,7 @@
 	public function test_standard_date_rfc2822()
 	{
 		$this->assertEquals(
-			date('D, d M Y H:i:s O', $this->time),
+			date('r', $this->time),
 			standard_date('DATE_RFC2822', $this->time)
 		);
 	}
@@ -159,7 +159,7 @@
 	public function test_standard_date_w3c()
 	{
 		$this->assertEquals(
-			date("Y-m-d\TH:i:sO", $this->time),
+			date('Y-m-d\TH:i:sP', $this->time),
 			standard_date('DATE_W3C', $this->time)
 		);
 	}
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index a244625..efe49cf 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -136,7 +136,7 @@
    -  Added unbuffered_row() method for getting a row without prefetching whole result (consume less memory).
 
 -  Libraries
-
+   -  CI_Session now respects php.ini's session.gc_probability and session.gc_divisor
    -  Added max_filename_increment config setting for Upload library.
    -  CI_Loader::_ci_autoloader() is now a protected method.
    -  Added custom filename to Email::attach() as $this->email->attach($filename, $disposition, $newname).
@@ -176,6 +176,7 @@
 	 -  Added support for setting custom attributes.
 	 -  Deprecated usage of the "anchor_class" setting (use the new "attributes" setting instead).
 	 -  Added $config['reuse_query_string'] to allow automatic repopulation of query string arguments, combined with normal URI segments.
+   -  Added the ability to use a proxy with the :doc:`XML-RPC Library <libraries/xmlrpc.rst>`.
 
 -  Core
 
@@ -301,11 +302,20 @@
 -  Fixed a bug (#79) - :doc:`Form Validation Library <libraries/form_validation>` didn't properly validate array fields that use associative keys or have custom indexes.
 -  Fixed a bug (#427) - :doc:`Form Validation Library <libraries/form_validation>` method ``strip_image_tags()`` was an alias to a non-existent method.
 -  Fixed a bug (#1545) - :doc:`Query Builder <database/query_builder>` method ``limit()`` wasn't executed properly under Oracle.
+-  Fixed a bug (#1551) - :doc:`Date Helper <helpers/date_helper>` function ``standard_date()`` didn't properly format *W3C* and *ATOM* standard dates.
+
+Version 2.1.2
+=============
+
+Release Date: June 29, 2012
+
+-  General Changes
+   -  Improved security in ``xss_clean()``.
 
 Version 2.1.1
 =============
 
-Release Date: June 13, 2012
+Release Date: June 12, 2012
 
 -  General Changes
    -  Fixed support for docx, xlsx files in mimes.php.
@@ -316,20 +326,20 @@
    -  Added support for the IP format parameter to the :doc:`Form Validation Library <libraries/form_validation>`.
 
 -  Helpers
-   -  url_title() performance and output improved. You can now use any string as the word delimiter, but 'dash' and 'underscore' are still supported.
+   -  ``url_title()`` performance and output improved. You can now use any string as the word delimiter, but 'dash' and 'underscore' are still supported.
 
 Bug fixes for 2.1.1
 -------------------
 
--  Fixed a bug (#697) - A wrong array key was used in the Upload library to check for mime-types.
--  Fixed a bug - form_open() compared $action against site_url() instead of base_url().
--  Fixed a bug - CI_Upload::_file_mime_type() could've failed if mime_content_type() is used for the detection and returns FALSE.
+-  Fixed a bug (#697) - A wrong array key was used in the :doc:`File Uploading Library <libraries/file_uploading>` to check for mime-types.
+-  Fixed a bug - ``form_open()`` compared $action against ``site_url()`` instead of ``base_url()``.
+-  Fixed a bug - ``CI_Upload::_file_mime_type()`` could've failed if ``mime_content_type()`` is used for the detection and returns FALSE.
 -  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 - 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.
+-  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.
 
 Version 2.1.0
 =============
diff --git a/user_guide_src/source/helpers/array_helper.rst b/user_guide_src/source/helpers/array_helper.rst
index 4308753..15b5e17 100644
--- a/user_guide_src/source/helpers/array_helper.rst
+++ b/user_guide_src/source/helpers/array_helper.rst
@@ -21,17 +21,17 @@
 element()
 =========
 
-.. php:method:: element($item, $array, $default = FALSE)
+.. php:method:: element($item, $array, $default = NULL)
 
 	:param string 	$item: Item to fetch from the array
 	:param array 	$array: Input array
 	:param boolean	$default: What to return if the array isn't valid
-	:returns: FALSE on failure or the array item.
+	:returns: NULL on failure or the array item.
 
 
 Lets you fetch an item from an array. The function tests whether the
 array index is set and whether it has a value. If a value exists it is
-returned. If a value does not exist it returns FALSE, or whatever you've
+returned. If a value does not exist it returns NULL, or whatever you've
 specified as the default value via the third parameter. Example
 
 ::
@@ -43,31 +43,31 @@
 	);
 
 	echo element('color', $array); // returns "red" 
-	echo element('size', $array, NULL); // returns NULL 
+	echo element('size', $array, 'foobar'); // returns "foobar" 
 
 elements()
 ==========
 
 Lets you fetch a number of items from an array. The function tests
 whether each of the array indices is set. If an index does not exist it
-is set to FALSE, or whatever you've specified as the default value via
+is set to NULL, or whatever you've specified as the default value via
 the third parameter. 
 
-.. php:method:: elements($items, $array, $default = FALSE)
+.. php:method:: elements($items, $array, $default = NULL)
 
 	:param string 	$item: Item to fetch from the array
 	:param array 	$array: Input array
 	:param boolean	$default: What to return if the array isn't valid
-	:returns: FALSE on failure or the array item.
+	:returns: NULL on failure or the array item.
 
 Example
 
 ::
 
 	$array = array(
-		'color' => 'red',  
-		'shape' => 'round',     
-		'radius' => '10',     
+		'color' => 'red',
+		'shape' => 'round',
+		'radius' => '10',
 		'diameter' => '20'
 	);
 
@@ -78,25 +78,25 @@
 ::
 
 	array(
-		'color' => 'red',     
-		'shape' => 'round',     
-		'height' => FALSE
+		'color' => 'red',
+		'shape' => 'round',
+		'height' => NULL
 	);
 
 You can set the third parameter to any default value you like
 
 ::
 
-	 $my_shape = elements(array('color', 'shape', 'height'), $array, NULL);
+	 $my_shape = elements(array('color', 'shape', 'height'), $array, 'foobar');
 
 The above will return the following array
 
 ::
 
 	array(     
-		'color' 	=> 'red',     
-		'shape' 	=> 'round',     
-		'height'	=> NULL
+		'color' 	=> 'red',
+		'shape' 	=> 'round',
+		'height'	=> 'foobar'
 	);
 
 This is useful when sending the $_POST array to one of your Models.