tweak the sql_like_expression feature a little bit to allow correct escaping

git-svn-id: file:///svn/phpbb/trunk@7789 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
Meik Sievertsen 2007-06-24 12:49:13 +00:00
parent 318418b0f2
commit 5aa220bcd2
22 changed files with 96 additions and 53 deletions

View file

@ -239,7 +239,7 @@ class acp_permission_roles
{
$sql = 'SELECT auth_option_id, auth_option
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression($permission_type . '%') . "
WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . "
AND auth_option <> '{$permission_type}'
ORDER BY auth_option_id";
$result = $db->sql_query($sql);
@ -305,7 +305,7 @@ class acp_permission_roles
// We need to fill the auth options array with ACL_NO options ;)
$sql = 'SELECT auth_option_id, auth_option
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression($permission_type . '%') . "
WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char) . "
AND auth_option <> '{$permission_type}'
ORDER BY auth_option_id";
$result = $db->sql_query($sql);
@ -490,7 +490,7 @@ class acp_permission_roles
// Get complete auth array
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression($permission_type . '%');
WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char);
$result = $db->sql_query($sql);
$auth_settings = array();

View file

@ -1069,7 +1069,7 @@ class acp_permissions
global $db, $user;
$sql_forum_id = ($permission_scope == 'global') ? 'AND a.forum_id = 0' : ((sizeof($forum_id)) ? 'AND ' . $db->sql_in_set('a.forum_id', $forum_id) : 'AND a.forum_id <> 0');
$sql_permission_option = ' AND o.auth_option ' . $db->sql_like_expression($permission_type . '%');
$sql_permission_option = ' AND o.auth_option ' . $db->sql_like_expression($permission_type . $db->any_char);
$sql = $db->sql_build_query('SELECT_DISTINCT', array(
'SELECT' => 'u.username, u.username_clean, u.user_regdate, u.user_id',

View file

@ -393,8 +393,8 @@ class acp_prune
$sort_by_types = array('username', 'user_email', 'user_posts', 'user_regdate', 'user_lastvisit');
$where_sql = '';
$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', '%', utf8_clean_string($username))) : '';
$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', '%', $email)) . ' ' : '';
$where_sql .= ($username) ? ' AND username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($username))) : '';
$where_sql .= ($email) ? ' AND user_email ' . $db->sql_like_expression(str_replace('*', $db->any_char, $email)) . ' ' : '';
$where_sql .= (sizeof($joined)) ? " AND user_regdate " . $key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, (int) $joined[1], (int) $joined[2], (int) $joined[0]) : '';
$where_sql .= ($count !== '') ? " AND user_posts " . $key_match[$count_select] . ' ' . (int) $count . ' ' : '';
$where_sql .= (sizeof($active)) ? " AND user_lastvisit " . $key_match[$active_select] . " " . gmmktime(0, 0, 0, (int) $active[1], (int) $active[2], (int) $active[0]) : '';

View file

@ -1831,7 +1831,7 @@ class acp_users
// Select auth options
$sql = 'SELECT auth_option, is_local, is_global
FROM ' . ACL_OPTIONS_TABLE . '
WHERE auth_option ' . $db->sql_like_expression('%_') . '
WHERE auth_option ' . $db->sql_like_expression($db->any_char . '_') . '
AND is_global = 1
ORDER BY auth_option';
$result = $db->sql_query($sql);
@ -1851,7 +1851,7 @@ class acp_users
{
$sql = 'SELECT auth_option, is_local, is_global
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression('%_') . "
WHERE auth_option " . $db->sql_like_expression($db->any_char . '_') . "
AND is_local = 1
ORDER BY is_global DESC, auth_option";
$result = $db->sql_query($sql);

View file

@ -968,7 +968,7 @@ class auth_admin extends auth
// Get permission type
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression($permission_type . '%');
WHERE auth_option " . $db->sql_like_expression($permission_type . $db->any_char);
$result = $db->sql_query($sql);
$auth_id_ary = array();

View file

@ -842,7 +842,7 @@ class auth
{
if (strpos($auth_options, '%') !== false)
{
$sql_opts = "AND $key " . $db->sql_like_expression($auth_options);
$sql_opts = "AND $key " . $db->sql_like_expression(str_replace('%', $db->any_char, $auth_options));
}
else
{
@ -873,7 +873,7 @@ class auth
{
if (strpos($option, '%') !== false)
{
$sql[] = $key . ' ' . $db->sql_like_expression($option);
$sql[] = $key . ' ' . $db->sql_like_expression(str_replace('%', $db->any_char, $option));
}
else
{

View file

@ -49,6 +49,12 @@ class dbal
*/
var $sql_layer = '';
/**
* Wildcards for matching any (%) or exactly one (_) character within LIKE expressions
*/
var $any_char;
var $one_char;
/**
* Constructor
*/
@ -63,6 +69,10 @@ class dbal
// Fill default sql layer based on the class being called.
// This can be changed by the specified layer itself later if needed.
$this->sql_layer = substr(get_class($this), 5);
// Do not change this please! This variable is used to easy the use of it - and is hardcoded.
$this->any_char = chr(0) . '%';
$this->one_char = chr(0) . '_';
}
/**
@ -193,17 +203,17 @@ class dbal
/**
* Correctly adjust LIKE expression for special characters
* Some DBMS are handling them in a different way we need to take into account
* Some DBMS are handling them in a different way
*
* @param string $expression The expression to use. Every wildcard is escaped, except $this->any_char and $this->one_char
* @return string LIKE expression including the keyword!
*/
function sql_like_expression($expression)
{
// Standard for most DBMS
if (strpos($expression, '_') === false)
{
return 'LIKE \'' . $this->sql_escape($expression) . '\'';
}
$expression = str_replace(array('_', '%'), array("\_", "\%"), $expression);
$expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression);
return 'LIKE \'' . $this->sql_escape(str_replace('_', "\_", $expression)) . '\'';
return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\'');
}
/**

View file

@ -408,6 +408,15 @@ class dbal_firebird extends dbal
return str_replace("'", "''", $msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private

View file

@ -309,19 +309,12 @@ class dbal_mssql extends dbal
}
/**
* Correctly adjust LIKE expression for special characters
* MSSQL needs an escape character being defined
* Build LIKE expression
* @access private
*/
function sql_like_expression($expression)
function _sql_like_expression($expression)
{
// Standard for most DBMS
if (strpos($expression, '_') === false)
{
return 'LIKE \'' . $this->sql_escape($expression) . '\'';
}
// sql_like_expression is only allowed directly within single quotes (to ease the use of it), therefore the special writing of ESCAPE below
return 'LIKE \'' . $this->sql_escape(str_replace('_', "\_", $expression)) . "' ESCAPE '\\'";
return $expression . " ESCAPE '\\'";
}
/**

View file

@ -320,19 +320,12 @@ class dbal_mssql_odbc extends dbal
}
/**
* Correctly adjust LIKE expression for special characters
* MSSQL needs an escape character being defined
* Build LIKE expression
* @access private
*/
function sql_like_expression($expression)
function _sql_like_expression($expression)
{
// Standard for most DBMS
if (strpos($expression, '_') === false)
{
return 'LIKE \'' . $this->sql_escape($expression) . '\'';
}
// sql_like_expression is only allowed directly within single quotes (to ease the use of it), therefore the special writing of ESCAPE below
return 'LIKE \'' . $this->sql_escape(str_replace('_', "\_", $expression)) . "' ESCAPE '\\'";
return $expression . " ESCAPE '\\'";
}
/**

View file

@ -276,6 +276,15 @@ class dbal_mysql extends dbal
return @mysql_real_escape_string($msg, $this->db_connect_id);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private

View file

@ -245,6 +245,15 @@ class dbal_mysqli extends dbal
return @mysqli_real_escape_string($this->db_connect_id, $msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* Build db-specific query data
* @access private

View file

@ -533,6 +533,15 @@ class dbal_oracle extends dbal
return str_replace("'", "''", $msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression . " ESCAPE '\\'";
}
function _sql_custom_build($stage, $data)
{
return $data;

View file

@ -345,6 +345,15 @@ class dbal_postgres extends dbal
return @pg_escape_string($msg);
}
/**
* Build LIKE expression
* @access private
*/
function _sql_like_expression($expression)
{
return $expression;
}
/**
* return sql error array
* @access private

View file

@ -247,12 +247,14 @@ class dbal_sqlite extends dbal
*/
function sql_like_expression($expression)
{
if (strpos($expression, '_') === false)
{
return "LIKE '" . $this->sql_escape($expression) . "'";
}
// Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it!
// We only catch * and ? here, not the character map possible on file globbing.
$expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression);
return "GLOB '" . $this->sql_escape(str_replace('%', '*', $expression)) . "'";
$expression = str_replace(array('?', '*'), array("\?", "\*"), $expression);
$expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression);
return 'GLOB \'' . $this->sql_escape($expression) . '\'';
}
/**

View file

@ -3877,7 +3877,7 @@ function page_header($page_title = '', $display_online_list = true)
{
$f = request_var('f', 0);
$reading_sql = ' AND s.session_page ' . $db->sql_like_expression("%_f_={$f}x%");
$reading_sql = ' AND s.session_page ' . $db->sql_like_expression("{$db->any_char}_f_={$f}x{$db->any_char}");
}
// Get number of online guests

View file

@ -2206,7 +2206,7 @@ function cache_moderators()
AND a.group_id = ug.group_id
AND ' . $db->sql_in_set('ug.user_id', $ug_id_ary) . "
AND ug.user_pending = 0
AND o.auth_option " . $db->sql_like_expression('m_%'),
AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char),
));
$result = $db->sql_query($sql);

View file

@ -273,7 +273,7 @@ class search_backend
$sql_where = '';
foreach ($words as $word)
{
$sql_where .= " OR search_keywords " . $db->sql_like_expression('%' . $word . '%');
$sql_where .= " OR search_keywords " . $db->sql_like_expression($db->any_char . $word . $db->any_char);
}
$sql = 'SELECT search_key

View file

@ -226,7 +226,7 @@ class template
FROM ' . STYLES_TEMPLATE_DATA_TABLE . '
WHERE template_id = ' . $user->theme['template_id'] . "
AND (template_filename = '" . $db->sql_escape($this->filename[$handle]) . "'
OR template_included " . $db->sql_like_expression('%' . $this->filename[$handle] . ':%') . ')';
OR template_included " . $db->sql_like_expression($db->any_char . $this->filename[$handle] . ':' . $db->any_char) . ')';
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);

View file

@ -148,7 +148,7 @@ class ucp_register
'email' => strtolower(request_var('email', '')),
'email_confirm' => strtolower(request_var('email_confirm', '')),
'confirm_code' => request_var('confirm_code', ''),
'lang' => request_var('lang', $user->lang_name),
'lang' => basename(request_var('lang', $user->lang_name)),
'tz' => request_var('tz', (float) $timezone),
);

View file

@ -1015,12 +1015,12 @@ switch ($mode)
{
for ($i = 97; $i < 123; $i++)
{
$sql_where .= ' AND u.username_clean NOT ' . $db->sql_like_expression(chr($i) . '%');
$sql_where .= ' AND u.username_clean NOT ' . $db->sql_like_expression(chr($i) . $db->any_char);
}
}
else if ($first_char)
{
$sql_where .= ' AND u.username_clean ' . $db->sql_like_expression(substr($first_char, 0, 1) . '%');
$sql_where .= ' AND u.username_clean ' . $db->sql_like_expression(substr($first_char, 0, 1) . $db->any_char);
}
// Are we looking at a usergroup? If so, fetch additional info

View file

@ -100,7 +100,7 @@ if ($keywords || $author || $author_id || $search_id || $submit)
trigger_error(sprintf($user->lang['TOO_FEW_AUTHOR_CHARS'], $config['min_search_author_chars']));
}
$sql_where = (strpos($author, '*') !== false) ? ' username_clean ' . $db->sql_like_expression(str_replace('*', '%', utf8_clean_string($author))) : " username_clean = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
$sql_where = (strpos($author, '*') !== false) ? ' username_clean ' . $db->sql_like_expression(str_replace('*', $db->any_char, utf8_clean_string($author))) : " username_clean = '" . $db->sql_escape(utf8_clean_string($author)) . "'";
$sql = 'SELECT user_id
FROM ' . USERS_TABLE . "