summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDerek Jones <derek.jones@ellislab.com>2009-02-20 22:44:59 +0100
committerDerek Jones <derek.jones@ellislab.com>2009-02-20 22:44:59 +0100
commite4ed583067095144eb20aefc61d4499d8386532a (patch)
treeb156a0305e5c1e84466bcb0ca84787b234be3cfd
parent436e6e2583c574a4628984c4a95c5d3da5fcce1f (diff)
added LIKE condition escaping to all drivers and Active Record
updated all DB drivers to accept arrays in escape_str()
-rw-r--r--system/database/DB_active_rec.php8
-rw-r--r--system/database/DB_driver.php19
-rw-r--r--system/database/drivers/mssql/mssql_driver.php30
-rw-r--r--system/database/drivers/mysql/mysql_driver.php25
-rw-r--r--system/database/drivers/mysqli/mysqli_driver.php31
-rw-r--r--system/database/drivers/oci8/oci8_driver.php31
-rw-r--r--system/database/drivers/odbc/odbc_driver.php33
-rw-r--r--system/database/drivers/postgre/postgre_driver.php31
-rw-r--r--system/database/drivers/sqlite/sqlite_driver.php29
-rw-r--r--user_guide/changelog.html5
-rw-r--r--user_guide/database/queries.html9
11 files changed, 223 insertions, 28 deletions
diff --git a/system/database/DB_active_rec.php b/system/database/DB_active_rec.php
index c757e6ae6..d48f43e51 100644
--- a/system/database/DB_active_rec.php
+++ b/system/database/DB_active_rec.php
@@ -707,7 +707,7 @@ class CI_DB_active_record extends CI_DB_driver {
$prefix = (count($this->ar_like) == 0) ? '' : $type;
- $v = $this->escape_str($v);
+ $v = $this->escape_like_str($v);
if ($side == 'before')
{
@@ -722,6 +722,12 @@ class CI_DB_active_record extends CI_DB_driver {
$like_statement = $prefix." $k $not LIKE '%{$v}%'";
}
+ // some platforms require an escape sequence definition for LIKE wildcards
+ if ($this->_like_escape_str != '')
+ {
+ $like_statement = $like_statement.sprintf($this->_like_escape_str, $this->_like_escape_char);
+ }
+
$this->ar_like[] = $like_statement;
if ($this->ar_caching === TRUE)
{
diff --git a/system/database/DB_driver.php b/system/database/DB_driver.php
index 9385870e9..729af5bf6 100644
--- a/system/database/DB_driver.php
+++ b/system/database/DB_driver.php
@@ -670,7 +670,7 @@ class CI_DB_driver {
*
* @access public
* @param string
- * @return integer
+ * @return mixed
*/
function escape($str)
{
@@ -691,7 +691,24 @@ class CI_DB_driver {
}
// --------------------------------------------------------------------
+
+ /**
+ * Smart Escape LIKE String
+ *
+ * Calls the individual driver for platform
+ * specific escaping for LIKE conditions
+ *
+ * @access public
+ * @param string
+ * @return mixed
+ */
+ function escape_like_str($str)
+ {
+ return $this->escape_str($str, TRUE);
+ }
+ // --------------------------------------------------------------------
+
/**
* Primary
*
diff --git a/system/database/drivers/mssql/mssql_driver.php b/system/database/drivers/mssql/mssql_driver.php
index addbd6b92..c89e2549e 100644
--- a/system/database/drivers/mssql/mssql_driver.php
+++ b/system/database/drivers/mssql/mssql_driver.php
@@ -34,6 +34,11 @@ class CI_DB_mssql_driver extends CI_DB {
// The character used for escaping
var $_escape_char = '';
+
+ // clause and character used for LIKE escape sequences
+ var $_like_escape_str = " ESCAPE '%s' ";
+ var $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -225,15 +230,36 @@ class CI_DB_mssql_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
// Access the CI object
$CI =& get_instance();
// Escape single quotes
- return str_replace("'", "''", $CI->input->_remove_invisible_characters($str));
+ $str = str_replace("'", "''", $CI->input->_remove_invisible_characters($str));
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace( array('%', '_', $this->_like_escape_chr),
+ array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysql/mysql_driver.php b/system/database/drivers/mysql/mysql_driver.php
index a0cdb58af..5b2ba62b8 100644
--- a/system/database/drivers/mysql/mysql_driver.php
+++ b/system/database/drivers/mysql/mysql_driver.php
@@ -34,7 +34,11 @@ class CI_DB_mysql_driver extends CI_DB {
// The character used for escaping
var $_escape_char = '`';
-
+
+ // clause and character used for LIKE escape sequences - not used in MySQL
+ var $_like_escape_str = '';
+ var $_like_escape_chr = '';
+
/**
* Whether to use the MySQL "delete hack" which allows the number
* of affected rows to be shown. Uses a preg_replace when enabled,
@@ -256,15 +260,16 @@ class CI_DB_mysql_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
if (is_array($str))
{
foreach($str as $key => $val)
{
- $str[$key] = $this->escape_str($val);
+ $str[$key] = $this->escape_str($val, $like);
}
return $str;
@@ -272,16 +277,24 @@ class CI_DB_mysql_driver extends CI_DB {
if (function_exists('mysql_real_escape_string') AND is_resource($this->conn_id))
{
- return mysql_real_escape_string($str, $this->conn_id);
+ $str = mysql_real_escape_string($str, $this->conn_id);
}
elseif (function_exists('mysql_escape_string'))
{
- return mysql_escape_string($str);
+ $str = mysql_escape_string($str);
}
else
{
- return addslashes($str);
+ $str = addslashes($str);
}
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/mysqli/mysqli_driver.php b/system/database/drivers/mysqli/mysqli_driver.php
index 9ef18e025..92d871111 100644
--- a/system/database/drivers/mysqli/mysqli_driver.php
+++ b/system/database/drivers/mysqli/mysqli_driver.php
@@ -35,6 +35,10 @@ class CI_DB_mysqli_driver extends CI_DB {
// The character used for escaping
var $_escape_char = '`';
+ // clause and character used for LIKE escape sequences - not used in MySQL
+ var $_like_escape_str = '';
+ var $_like_escape_chr = '';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -257,22 +261,41 @@ class CI_DB_mysqli_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
if (function_exists('mysqli_real_escape_string') AND is_object($this->conn_id))
{
- return mysqli_real_escape_string($this->conn_id, $str);
+ $str = mysqli_real_escape_string($this->conn_id, $str);
}
elseif (function_exists('mysql_escape_string'))
{
- return mysql_escape_string($str);
+ $str = mysql_escape_string($str);
}
else
{
- return addslashes($str);
+ $str = addslashes($str);
}
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace(array('%', '_'), array('\\%', '\\_'), $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/oci8/oci8_driver.php b/system/database/drivers/oci8/oci8_driver.php
index 42dd51769..1fdb1bc45 100644
--- a/system/database/drivers/oci8/oci8_driver.php
+++ b/system/database/drivers/oci8/oci8_driver.php
@@ -47,7 +47,11 @@ class CI_DB_oci8_driver extends CI_DB {
// The character used for excaping
var $_escape_char = '"';
-
+
+ // clause and character used for LIKE escape sequences
+ var $_like_escape_str = " escape '%s' ";
+ var $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -368,14 +372,35 @@ class CI_DB_oci8_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
// Access the CI object
$CI =& get_instance();
- return $CI->input->_remove_invisible_characters($str);
+ $str = $CI->input->_remove_invisible_characters($str);
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace( array('%', '_', $this->_like_escape_chr),
+ array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/odbc/odbc_driver.php b/system/database/drivers/odbc/odbc_driver.php
index 0f8b42007..a14aaa1f3 100644
--- a/system/database/drivers/odbc/odbc_driver.php
+++ b/system/database/drivers/odbc/odbc_driver.php
@@ -34,7 +34,11 @@ class CI_DB_odbc_driver extends CI_DB {
// the character used to excape - not necessary for ODBC
var $_escape_char = '';
-
+
+ // clause and character used for LIKE escape sequences
+ var $_like_escape_str = " {escape '%s'} ";
+ var $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -237,15 +241,36 @@ class CI_DB_odbc_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
// Access the CI object
$CI =& get_instance();
-
+
// ODBC doesn't require escaping
- return $CI->_remove_invisible_characters($str);
+ $str = $CI->input->_remove_invisible_characters($str);
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace( array('%', '_', $this->_like_escape_chr),
+ array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/postgre/postgre_driver.php b/system/database/drivers/postgre/postgre_driver.php
index 9d53b1ef8..8d0d8901c 100644
--- a/system/database/drivers/postgre/postgre_driver.php
+++ b/system/database/drivers/postgre/postgre_driver.php
@@ -34,6 +34,10 @@ class CI_DB_postgre_driver extends CI_DB {
var $_escape_char = '"';
+ // clause and character used for LIKE escape sequences
+ var $_like_escape_str = " ESCAPE '%s' ";
+ var $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -253,11 +257,32 @@ class CI_DB_postgre_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
- {
- return pg_escape_string($str);
+ function escape_str($str, $like = FALSE)
+ {
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
+ $str = pg_escape_string($str);
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace( array('%', '_', $this->_like_escape_chr),
+ array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/system/database/drivers/sqlite/sqlite_driver.php b/system/database/drivers/sqlite/sqlite_driver.php
index 3ef88dbba..104a3bc36 100644
--- a/system/database/drivers/sqlite/sqlite_driver.php
+++ b/system/database/drivers/sqlite/sqlite_driver.php
@@ -37,6 +37,10 @@ class CI_DB_sqlite_driver extends CI_DB {
// The character used to escape with - not needed for SQLite
var $_escape_char = '';
+ // clause and character used for LIKE escape sequences
+ var $_like_escape_str = " ESCAPE '%s' ";
+ var $_like_escape_chr = '!';
+
/**
* The syntax to count rows is slightly different across different
* database engines, so this string appears in each driver and is
@@ -253,11 +257,32 @@ class CI_DB_sqlite_driver extends CI_DB {
*
* @access public
* @param string
+ * @param bool whether or not the string will be used in a LIKE condition
* @return string
*/
- function escape_str($str)
+ function escape_str($str, $like = FALSE)
{
- return sqlite_escape_string($str);
+ if (is_array($str))
+ {
+ foreach($str as $key => $val)
+ {
+ $str[$key] = $this->escape_str($val, $like);
+ }
+
+ return $str;
+ }
+
+ $str = sqlite_escape_string($str);
+
+ // escape LIKE condition wildcards
+ if ($like === TRUE)
+ {
+ $str = str_replace( array('%', '_', $this->_like_escape_chr),
+ array($this->_like_escape_chr.'%', $this->_like_escape_chr.'_', $this->_like_escape_chr.$this->_like_escape_chr),
+ $str);
+ }
+
+ return $str;
}
// --------------------------------------------------------------------
diff --git a/user_guide/changelog.html b/user_guide/changelog.html
index 06375d6f4..cdbfbbd04 100644
--- a/user_guide/changelog.html
+++ b/user_guide/changelog.html
@@ -71,6 +71,9 @@ SVN Revision: </p>
<li>Database
<ul>
<li>Switched from using gettype() in escape() to is_* methods, since future PHP versions might change its output.</li>
+ <li>Updated all database drivers to handle arrays in escape_str()</li>
+ <li>Added escape_like_str() method for escaping strings to be used in LIKE conditions</li>
+ <li>Updated Active Record to utilize the new LIKE escaping mechanism.</li>
</ul>
</li>
@@ -80,6 +83,7 @@ SVN Revision: </p>
<ul>
<li>Fixed assorted user guide typos or examples (#6743).</li>
<li>Fixed a bug with ORIG_PATH_INFO that was allowing URIs of just a slash through.</li>
+ <li>Fixed a fatal error in the Oracle and ODBC drivers (#6752)</li>
</ul>
<h2>Version 1.7.1</h2>
@@ -136,7 +140,6 @@ SVN Revision: 1640</p>
<li>Fixed a bug where TRUNCATE was not considered a "write" query (#6619).</li>
<li>Fixed a bug where csv_from_result() was checking for a nonexistent method.</li>
<li>Fixed a bug _protect_identifiers() where it was improperly removing all pipe symbols from items</li>
- <li>Fixed a fatal error in the Oracle driver (#6752)</li>
</ul>
</li>
<li>Fixed assorted user guide typos or examples (#5998, #6093, #6259, #6339, #6432, #6521).</li>
diff --git a/user_guide/database/queries.html b/user_guide/database/queries.html
index f42e179ab..9665af231 100644
--- a/user_guide/database/queries.html
+++ b/user_guide/database/queries.html
@@ -96,7 +96,7 @@ It simply lets you submit a query. Most users will rarely use this function.</p>
<h1>Escaping Queries</h1>
<p>It's a very good security practice to escape your data before submitting it into your database.
-CodeIgniter has two functions that help you do this:</p>
+CodeIgniter has three methods that help you do this:</p>
<ol>
<li><strong>$this->db->escape()</strong> This function determines the data type so that it
@@ -108,6 +108,13 @@ can escape only string data. It also automatically adds single quotes around th
Most of the time you'll use the above function rather than this one. Use the function like this:
<code>$sql = "INSERT INTO table (title) VALUES('".$this->db->escape_str($title)."')";</code></li>
+
+<li><strong>$this->db->escape_like_str()</strong> This method should be used when strings are to be used in LIKE
+conditions so that LIKE wildcards ('%', '_') in the string are also properly escaped.
+
+<code>$search = '20% raise';<br />
+$sql = "SELECT id FROM table WHERE column LIKE '%".$this->db->escape_like_str($search)."%'";</code>
+
</ol>