Merge pull request #1519 from mwhitneysdsu/develop

Added optional fourth parameter to timezone_menu
diff --git a/system/core/Output.php b/system/core/Output.php
index 4fdf18f..5ec8c4b 100644
--- a/system/core/Output.php
+++ b/system/core/Output.php
@@ -625,6 +625,11 @@
 
 				$size_before = strlen($output);
 
+				if ($size_before === 0)
+				{
+					return '';
+				}
+
 				// Find all the <pre>,<code>,<textarea>, and <javascript> tags
 				// We'll want to return them to this unprocessed state later.
 				preg_match_all('{<pre.+</pre>}msU', $output, $pres_clean);
diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php
index 62e0212..dad1df1 100644
--- a/system/database/DB_query_builder.php
+++ b/system/database/DB_query_builder.php
@@ -463,7 +463,9 @@
 
 		foreach ($key as $k => $v)
 		{
-			$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? $this->_group_get_type('') : $this->_group_get_type($type);
+			$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+				? $this->_group_get_type('')
+				: $this->_group_get_type($type);
 
 			$k = (($op = $this->_get_operator($k)) !== FALSE)
 				? $this->protect_identifiers(substr($k, 0, strpos($k, $op)), FALSE, $escape).strstr($k, $op)
@@ -1059,6 +1061,23 @@
 	// --------------------------------------------------------------------
 
 	/**
+	 * Limit string
+	 *
+	 * Generates a platform-specific LIMIT clause
+	 *
+	 * @param	string	the sql query string
+	 * @param	int	the number of rows to limit the query to
+	 * @param	int	the offset value
+	 * @return	string
+	 */
+	protected function _limit($sql, $limit, $offset)
+	{
+		return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit;
+	}
+
+	// --------------------------------------------------------------------
+
+	/**
 	 * The "set" function.
 	 *
 	 * Allows key/value pairs to be set for inserting or updating
@@ -2387,4 +2406,4 @@
 }
 
 /* End of file DB_query_builder.php */
-/* Location: ./system/database/DB_query_builder.php */
+/* Location: ./system/database/DB_query_builder.php */
\ No newline at end of file
diff --git a/system/database/drivers/cubrid/cubrid_driver.php b/system/database/drivers/cubrid/cubrid_driver.php
index 6b67b75..7496ee4 100644
--- a/system/database/drivers/cubrid/cubrid_driver.php
+++ b/system/database/drivers/cubrid/cubrid_driver.php
@@ -437,23 +437,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/database/drivers/interbase/interbase_driver.php b/system/database/drivers/interbase/interbase_driver.php
index 5a03607..512ee62 100644
--- a/system/database/drivers/interbase/interbase_driver.php
+++ b/system/database/drivers/interbase/interbase_driver.php
@@ -421,12 +421,12 @@
 		if (stripos($this->version(), 'firebird') !== FALSE)
 		{
 			$select = 'FIRST '. (int) $limit
-				.($offset > 0 ? ' SKIP '. (int) $offset : '');
+				.($offset ? ' SKIP '. (int) $offset : '');
 		}
 		else
 		{
 			$select = 'ROWS '
-				.($offset > 0 ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
+				.($offset ? (int) $offset.' TO '.($limit + $offset) : (int) $limit);
 		}
 
 		return preg_replace('`SELECT`i', 'SELECT '.$select, $sql);
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index 8938d22..d11f015 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -64,6 +64,12 @@
 	 */
 	public $delete_hack = TRUE;
 
+	/**
+	 * Constructor
+	 *
+	 * @param	array
+	 * @return	void
+	 */
 	public function __construct($params)
 	{
 		parent::__construct($params);
@@ -74,6 +80,8 @@
 		}
 	}
 
+	// --------------------------------------------------------------------
+
 	/**
 	 * Non-persistent database connection
 	 *
@@ -335,7 +343,7 @@
 	 */
 	protected function _list_tables($prefix_limit = FALSE)
 	{
-		$sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+		$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
 
 		if ($prefix_limit !== FALSE && $this->dbprefix !== '')
 		{
@@ -355,7 +363,7 @@
 	 * @param	string	the table name
 	 * @return	string
 	 */
-	public function _list_columns($table = '')
+	protected function _list_columns($table = '')
 	{
 		return 'SHOW COLUMNS FROM '.$this->protect_identifiers($table, TRUE, NULL, FALSE);
 	}
@@ -453,23 +461,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.' LIMIT '.($offset == 0 ? '' : $offset.', ').$limit;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index d3fb77a..d1581bf 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -335,7 +335,7 @@
 	 */
 	protected function _list_tables($prefix_limit = FALSE)
 	{
-		$sql = 'SHOW TABLES FROM '.$this->_escape_char.$this->database.$this->_escape_char;
+		$sql = 'SHOW TABLES FROM '.$this->escape_identifiers($this->database);
 
 		if ($prefix_limit !== FALSE && $this->dbprefix !== '')
 		{
@@ -455,24 +455,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.' LIMIT '.$limit
-			.($offset > 0 ? ' OFFSET '.$offset : '');
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index e780916..1f571e5 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -634,7 +634,7 @@
 	{
 		$this->limit_used = TRUE;
 		return 'SELECT * FROM (SELECT inner_query.*, rownum rnum FROM ('.$sql.') inner_query WHERE rownum < '.($offset + $limit).')'
-			.($offset !== 0 ? ' WHERE rnum >= '.$offset : '');
+			.($offset ? ' WHERE rnum >= '.$offset : '');
 	}
 
 	// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 5ebba7a..bd57592 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -331,23 +331,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.' LIMIT '.($offset == 0 ? '' : $offset.', ').$limit;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/database/drivers/pdo/pdo_driver.php b/system/database/drivers/pdo/pdo_driver.php
index e25013a..a3ad469 100644
--- a/system/database/drivers/pdo/pdo_driver.php
+++ b/system/database/drivers/pdo/pdo_driver.php
@@ -599,19 +599,12 @@
 	 */
 	protected function _limit($sql, $limit, $offset)
 	{
-		if ($this->pdodriver === 'cubrid' OR $this->pdodriver === 'sqlite')
+		if ($this->pdodriver === 'pgsql')
 		{
-			$offset = ($offset == 0) ? '' : $offset.', ';
-
-			return $sql.'LIMIT '.$offset.$limit;
+			return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
 		}
-		else
-		{
-			$sql .= 'LIMIT '.$limit;
-			$sql .= ($offset > 0) ? ' OFFSET '.$offset : '';
 
-			return $sql;
-		}
+		return $sql.' LIMIT '.($offset ? $offset.', ' : '').$limit;
 	}
 
 }
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 23826a0..fd25303 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -399,11 +399,13 @@
 	 */
 	protected function _list_tables($prefix_limit = FALSE)
 	{
-		$sql = "SELECT table_name FROM information_schema.tables WHERE table_schema = 'public'";
+		$sql = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\'';
 
 		if ($prefix_limit !== FALSE && $this->dbprefix !== '')
 		{
-			return $sql." AND table_name LIKE '".$this->escape_like_str($this->dbprefix)."%' ".sprintf($this->_like_escape_str, $this->_like_escape_chr);
+			return $sql.' AND "table_name" LIKE \''
+				.$this->escape_like_str($this->dbprefix)."%' "
+				.sprintf($this->_like_escape_str, $this->_like_escape_chr);
 		}
 
 		return $sql;
@@ -421,7 +423,7 @@
 	 */
 	protected function _list_columns($table = '')
 	{
-		return "SELECT column_name FROM information_schema.columns WHERE table_name = '".$table."'";
+		return 'SELECT "column_name" FROM "information_schema"."columns" WHERE "table_name" = '.$this->escape($table);
 	}
 
 	// --------------------------------------------------------------------
@@ -580,7 +582,7 @@
 	 */
 	protected function _limit($sql, $limit, $offset)
 	{
-		return $sql.' LIMIT '.$limit.($offset == 0 ? '' : ' OFFSET '.$offset);
+		return $sql.' LIMIT '.$limit.($offset ? ' OFFSET '.$offset : '');
 	}
 
 	// --------------------------------------------------------------------
@@ -593,13 +595,11 @@
 	 * @param	mixed
 	 * @param	mixed
 	 * @param	string
+	 * @param	mixed
 	 * @return	object
-	 *
 	 */
 	protected function _where($key, $value = NULL, $type = 'AND ', $escape = NULL)
 	{
-		$type = $this->_group_get_type($type);
-
 		if ( ! is_array($key))
 		{
 			$key = array($key => $value);
@@ -610,7 +610,9 @@
 
 		foreach ($key as $k => $v)
 		{
-			$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0) ? '' : $type;
+			$prefix = (count($this->qb_where) === 0 && count($this->qb_cache_where) === 0)
+				? $this->_group_get_type('')
+				: $this->_group_get_type($type);
 
 			$k = (($op = $this->_get_operator($k)) !== FALSE)
 				? $this->protect_identifiers(substr($k, 0, strpos($k, $op)), FALSE, $escape).strstr($k, $op)
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 3305f60..87be7a5 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -360,23 +360,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.'LIMIT '.($offset == 0 ? '' : $offset.', ').$limit;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/database/drivers/sqlite3/sqlite3_driver.php b/system/database/drivers/sqlite3/sqlite3_driver.php
index bed6189..1c6533f 100644
--- a/system/database/drivers/sqlite3/sqlite3_driver.php
+++ b/system/database/drivers/sqlite3/sqlite3_driver.php
@@ -353,23 +353,6 @@
 	// --------------------------------------------------------------------
 
 	/**
-	 * Limit string
-	 *
-	 * Generates a platform-specific LIMIT clause
-	 *
-	 * @param	string	the sql query string
-	 * @param	int	the number of rows to limit the query to
-	 * @param	int	the offset value
-	 * @return	string
-	 */
-	protected function _limit($sql, $limit, $offset)
-	{
-		return $sql.' LIMIT '.($offset ? $offset.',' : '').$limit;
-	}
-
-	// --------------------------------------------------------------------
-
-	/**
 	 * Close DB Connection
 	 *
 	 * @return	void
diff --git a/system/libraries/Pagination.php b/system/libraries/Pagination.php
index 5a4ca8f..75745dd 100644
--- a/system/libraries/Pagination.php
+++ b/system/libraries/Pagination.php
@@ -36,39 +36,40 @@
  */
 class CI_Pagination {
 
-	public $base_url		= ''; // The page we are linking to
-	public $prefix			= ''; // A custom prefix added to the path.
-	public $suffix			= ''; // A custom suffix added to the path.
-	public $total_rows		= 0; // Total number of items (database results)
-	public $per_page		= 10; // Max number of items you want shown per page
-	public $num_links		= 2; // Number of "digit" links to show before/after the currently viewed page
-	public $cur_page		= 0; // The current page being viewed
-	public $use_page_numbers	= FALSE; // Use page number for segment instead of offset
-	public $first_link		= '&lsaquo; First';
-	public $next_link		= '&gt;';
-	public $prev_link		= '&lt;';
-	public $last_link		= 'Last &rsaquo;';
-	public $uri_segment		= 3;
-	public $full_tag_open		= '';
-	public $full_tag_close		= '';
-	public $first_tag_open		= '';
-	public $first_tag_close		= '&nbsp;';
-	public $last_tag_open		= '&nbsp;';
-	public $last_tag_close		= '';
-	public $first_url		= ''; // Alternative URL for the First Page.
-	public $cur_tag_open		= '&nbsp;<strong>';
-	public $cur_tag_close		= '</strong>';
-	public $next_tag_open		= '&nbsp;';
-	public $next_tag_close		= '&nbsp;';
-	public $prev_tag_open		= '&nbsp;';
-	public $prev_tag_close		= '';
-	public $num_tag_open		= '&nbsp;';
-	public $num_tag_close		= '';
-	public $page_query_string	= FALSE;
-	public $query_string_segment 	= 'per_page';
-	public $display_pages		= TRUE;
-	protected $_attributes		= '';
-	protected $_link_types		= array();
+	protected $base_url				= ''; // The page we are linking to
+	protected $prefix				= ''; // A custom prefix added to the path.
+	protected $suffix				= ''; // A custom suffix added to the path.
+	protected $total_rows			= 0; // Total number of items (database results)
+	protected $per_page				= 10; // Max number of items you want shown per page
+	protected $num_links			= 2; // Number of "digit" links to show before/after the currently viewed page
+	protected $cur_page				= 0; // The current page being viewed
+	protected $use_page_numbers		= FALSE; // Use page number for segment instead of offset
+	protected $first_link			= '&lsaquo; First';
+	protected $next_link			= '&gt;';
+	protected $prev_link			= '&lt;';
+	protected $last_link			= 'Last &rsaquo;';
+	protected $uri_segment			= 3;
+	protected $full_tag_open		= '';
+	protected $full_tag_close		= '';
+	protected $first_tag_open		= '';
+	protected $first_tag_close		= '&nbsp;';
+	protected $last_tag_open		= '&nbsp;';
+	protected $last_tag_close		= '';
+	protected $first_url			= ''; // Alternative URL for the First Page.
+	protected $cur_tag_open			= '&nbsp;<strong>';
+	protected $cur_tag_close		= '</strong>';
+	protected $next_tag_open		= '&nbsp;';
+	protected $next_tag_close		= '&nbsp;';
+	protected $prev_tag_open		= '&nbsp;';
+	protected $prev_tag_close		= '';
+	protected $num_tag_open			= '&nbsp;';
+	protected $num_tag_close		= '';
+	protected $page_query_string	= FALSE;
+	protected $query_string_segment 	= 'per_page';
+	protected $display_pages		= TRUE;
+	protected $_attributes			= '';
+	protected $_link_types			= array();
+	protected $reuse_query_string   = FALSE;
 
 	/**
 	 * Constructor
@@ -222,6 +223,23 @@
 
 		// And here we go...
 		$output = '';
+		$query_string = '';
+
+		// Add anything in the query string back to the links
+		// Note: Nothing to do with query_string_segment or any other query string options
+		if ($this->reuse_query_string === TRUE)
+		{
+			$get = $CI->input->get();
+			
+			// Unset the controll, method, old-school routing options
+			unset($get['c'], $get['m'], $get[$this->query_string_segment]);
+
+			// Put everything else onto the end
+			$query_string = (strpos($this->base_url, '&amp;') !== FALSE ? '&amp;' : '?') . http_build_query($get, '', '&amp;');
+
+			// Add this after the suffix to put it into more links easily
+			$this->suffix .= $query_string;
+		}
 
 		// Render the "First" link
 		if ($this->first_link !== FALSE && $this->cur_page > ($this->num_links + 1))
@@ -232,19 +250,19 @@
 		}
 
 		// Render the "previous" link
-		if  ($this->prev_link !== FALSE && $this->cur_page !== 1)
+		if ($this->prev_link !== FALSE && $this->cur_page !== 1)
 		{
 			$i = ($this->use_page_numbers) ? $uri_page_number - 1 : $uri_page_number - $this->per_page;
 
 			if ($i === $base_page && $this->first_url !== '')
 			{
-				$output .= $this->prev_tag_open.'<a href="'.$this->first_url.'"'.$this->_attributes.$this->_attr_rel('prev').'>'
+				$output .= $this->prev_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$this->_attributes.$this->_attr_rel('prev').'>'
 					.$this->prev_link.'</a>'.$this->prev_tag_close;
 			}
 			else
 			{
-				$i = ($i === $base_page) ? '' : $this->prefix.$i.$this->suffix;
-				$output .= $this->prev_tag_open.'<a href="'.$this->base_url.$i.'"'.$this->_attributes.$this->_attr_rel('prev').'>'
+				$append = ($i === $base_page) ? $query_string : $this->prefix.$i.$this->suffix;
+				$output .= $this->prev_tag_open.'<a href="'.$this->base_url.$append.'"'.$this->_attributes.$this->_attr_rel('prev').'>'
 					.$this->prev_link.'</a>'.$this->prev_tag_close;
 			}
 
@@ -268,13 +286,13 @@
 						$n = ($i === $base_page) ? '' : $i;
 						if ($n === '' && ! empty($this->first_url))
 						{
-							$output .= $this->num_tag_open.'<a href="'.$this->first_url.'"'.$this->_attributes.$this->_attr_rel('start').'>'
+							$output .= $this->num_tag_open.'<a href="'.$this->first_url.$query_string.'"'.$this->_attributes.$this->_attr_rel('start').'>'
 								.$loop.'</a>'.$this->num_tag_close;
 						}
 						else
 						{
-							$n = ($n === '') ? '' : $this->prefix.$n.$this->suffix;
-							$output .= $this->num_tag_open.'<a href="'.$this->base_url.$n.'"'.$this->_attributes.$this->_attr_rel('start').'>'
+							$append = ($n === '') ? $query_string : $this->prefix.$n.$this->suffix;
+							$output .= $this->num_tag_open.'<a href="'.$this->base_url.$append.'"'.$this->_attributes.$this->_attr_rel('start').'>'
 								.$loop.'</a>'.$this->num_tag_close;
 						}
 					}
diff --git a/user_guide_src/source/changelog.rst b/user_guide_src/source/changelog.rst
index c861a1e..28e2f94 100644
--- a/user_guide_src/source/changelog.rst
+++ b/user_guide_src/source/changelog.rst
@@ -149,6 +149,7 @@
 	 -  If property maintain_ratio is set to TRUE, image_reproportion() now doesn't need both width and height to be specified.
    -  Removed SHA1 function in the :doc:`Encryption Library <libraries/encryption>`.
    -  Added $config['csrf_regeneration'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which makes token regeneration optional.
+   -  Added $config['csrf_exclude_uris'] to the CSRF protection in the :doc:`Security library <libraries/security>`, which allows you list URIs which will not have the CSRF validation functions run.
    -  :doc:`Form Validation library <libraries/form_validation>` changes include:
 	 -  Added method error_array() to return all error messages as an array.
 	 -  Added method set_data() to set an alternative data array to be validated instead of the default $_POST.
@@ -170,6 +171,7 @@
 	 -  Added support for the anchor "rel" attribute.
 	 -  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.
 
 -  Core
 
@@ -454,7 +456,6 @@
    -  Added insert_batch() function to the PostgreSQL database driver.
       Thanks to epallerols for the patch.
    -  Added "application/x-csv" to mimes.php.
-   -  Added CSRF protection URI whitelisting.
    -  Fixed a bug where :doc:`Email library <libraries/email>`
       attachments with a "." in the name would using invalid MIME-types.
 
diff --git a/user_guide_src/source/libraries/pagination.rst b/user_guide_src/source/libraries/pagination.rst
index c4398d7..15b3675 100644
--- a/user_guide_src/source/libraries/pagination.rst
+++ b/user_guide_src/source/libraries/pagination.rst
@@ -112,6 +112,21 @@
 Note that "per_page" is the default query string passed, however can be
 configured using $config['query_string_segment'] = 'your_string'
 
+$config['reuse_query_string'] = FALSE;
+====================================
+
+By default your Query String arguments (nothing to do with other 
+query string options) will be ignored. Setting this config to 
+TRUE will add existing query string arguments back into the 
+URL after the URI segment and before the suffix
+
+::
+
+	http://example.com/index.php/test/page/20?query=search%term
+
+This helps you mix together normal :doc:`URI Segments <../general/urls>`
+as well as query string arguments, which until 3.0 was not possible.
+
 ***********************
 Adding Enclosing Markup
 ***********************