new wrapper for LIKE expressions to streamline the fixes. We actually need to adjust them for different DBMS as well as SQLite2 not supporting escaping characters in LIKE statements (which is a reason why we think about dropping sqlite support completely).

git-svn-id: file:///svn/phpbb/trunk@7788 89ea8834-ac86-4346-8a33-228a782c2dd0
This commit is contained in:
Meik Sievertsen 2007-06-23 12:16:20 +00:00
parent 1e2db705ca
commit 318418b0f2
18 changed files with 97 additions and 82 deletions

View file

@ -295,6 +295,7 @@ p a {
<li>[Fix] Correctly check permissions on the UCP subscription/bookmark pages (Bug #12595)</li>
<li>[Fix] Only convert non-orphaned PMs</li>
<li>[Fix] Fixed a few Postgres related errors (Bug #12587)</li>
<li>[Feature] New DBAL wrapper for LIKE expressions / sql_like_expression()</li>
</ul>

View file

@ -239,7 +239,7 @@ class acp_permission_roles
{
$sql = 'SELECT auth_option_id, auth_option
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '{$permission_type}%'
WHERE auth_option " . $db->sql_like_expression($permission_type . '%') . "
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 LIKE '{$permission_type}%'
WHERE auth_option " . $db->sql_like_expression($permission_type . '%') . "
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 LIKE '" . $db->sql_escape($permission_type) . "%'";
WHERE auth_option " . $db->sql_like_expression($permission_type . '%');
$result = $db->sql_query($sql);
$auth_settings = array();

View file

@ -1069,8 +1069,8 @@ 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 LIKE '" . $db->sql_escape($permission_type) . "%'";
$sql_permission_option = ' AND o.auth_option ' . $db->sql_like_expression($permission_type . '%');
$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 LIKE '" . $db->sql_escape(str_replace('*', '%', utf8_clean_string($username))) . "'" : '';
$where_sql .= ($email) ? " AND user_email LIKE '" . $db->sql_escape(str_replace('*', '%', $email)) . "' " : '';
$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 .= (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

@ -1830,15 +1830,9 @@ class acp_users
{
// Select auth options
$sql = 'SELECT auth_option, is_local, is_global
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '%" . $db->sql_escape('\_') . "'";
if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$sql .= " ESCAPE '\\' ";
}
$sql .= 'AND is_global = 1
FROM ' . ACL_OPTIONS_TABLE . '
WHERE auth_option ' . $db->sql_like_expression('%_') . '
AND is_global = 1
ORDER BY auth_option';
$result = $db->sql_query($sql);
@ -1857,15 +1851,9 @@ class acp_users
{
$sql = 'SELECT auth_option, is_local, is_global
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '%" . $db->sql_escape('\_') . "'";
if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$sql .= " ESCAPE '\\' ";
}
$sql .= 'AND is_local = 1
ORDER BY is_global DESC, auth_option';
WHERE auth_option " . $db->sql_like_expression('%_') . "
AND is_local = 1
ORDER BY is_global DESC, auth_option";
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))

View file

@ -966,20 +966,9 @@ class auth_admin extends auth
if ($permission_type !== false)
{
// Get permission type
if ($db->sql_layer == 'sqlite')
{
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '" . $db->sql_escape($permission_type) . "%'";
}
else
{
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option LIKE '" . $db->sql_escape(str_replace('_', "\_", $permission_type)) . "%'";
$sql .= ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : '';
}
$sql = 'SELECT auth_option, auth_option_id
FROM ' . ACL_OPTIONS_TABLE . "
WHERE auth_option " . $db->sql_like_expression($permission_type . '%');
$result = $db->sql_query($sql);
$auth_id_ary = array();

View file

@ -842,15 +842,7 @@ class auth
{
if (strpos($auth_options, '%') !== false)
{
if (strpos($auth_options, '_') !== false && $db->sql_layer !== 'sqlite')
{
$sql_opts = "AND $key LIKE '" . $db->sql_escape(str_replace('_', "\_", $auth_options)) . "'";
$sql_opts .= ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\' " : '';
}
else
{
$sql_opts = "AND $key LIKE '" . $db->sql_escape($auth_options) . "'";
}
$sql_opts = "AND $key " . $db->sql_like_expression($auth_options);
}
else
{
@ -881,16 +873,7 @@ class auth
{
if (strpos($option, '%') !== false)
{
if (strpos($option, '_') !== false && $db->sql_layer !== 'sqlite')
{
$_sql = $key . " LIKE '" . $db->sql_escape(str_replace('_', "\_", $option)) . "'";
$_sql .= ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : '';
$sql[] = $_sql;
}
else
{
$sql[] = $key . " LIKE '" . $db->sql_escape($option) . "'";
}
$sql[] = $key . ' ' . $db->sql_like_expression($option);
}
else
{

View file

@ -191,6 +191,21 @@ class dbal
return false;
}
/**
* Correctly adjust LIKE expression for special characters
* Some DBMS are handling them in a different way we need to take into account
*/
function sql_like_expression($expression)
{
// Standard for most DBMS
if (strpos($expression, '_') === false)
{
return 'LIKE \'' . $this->sql_escape($expression) . '\'';
}
return 'LIKE \'' . $this->sql_escape(str_replace('_', "\_", $expression)) . '\'';
}
/**
* SQL Transaction
* @access private

View file

@ -308,6 +308,22 @@ class dbal_mssql extends dbal
return str_replace("'", "''", $msg);
}
/**
* Correctly adjust LIKE expression for special characters
* MSSQL needs an escape character being defined
*/
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 sql error array
* @access private

View file

@ -319,6 +319,22 @@ class dbal_mssql_odbc extends dbal
return str_replace("'", "''", $msg);
}
/**
* Correctly adjust LIKE expression for special characters
* MSSQL needs an escape character being defined
*/
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 '\\'";
}
/**
* Build db-specific query data
* @access private

View file

@ -241,6 +241,20 @@ class dbal_sqlite extends dbal
return @sqlite_escape_string($msg);
}
/**
* Correctly adjust LIKE expression for special characters
* For SQLite an underscore is a not-known character... this may change with SQLite3
*/
function sql_like_expression($expression)
{
if (strpos($expression, '_') === false)
{
return "LIKE '" . $this->sql_escape($expression) . "'";
}
return "GLOB '" . $this->sql_escape(str_replace('%', '*', $expression)) . "'";
}
/**
* return sql error array
* @access private

View file

@ -3877,14 +3877,7 @@ function page_header($page_title = '', $display_online_list = true)
{
$f = request_var('f', 0);
// Do not change this (it is defined as _f_={forum_id}x within session.php)
$reading_sql = " AND s.session_page LIKE '%" . $db->sql_escape("\_f\_={$f}x") . "%'";
// Specify escape character for MSSQL
if ($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc')
{
$reading_sql .= " ESCAPE '\\' ";
}
$reading_sql = ' AND s.session_page ' . $db->sql_like_expression("%_f_={$f}x%");
}
// Get number of online guests

View file

@ -2206,8 +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 LIKE '" . $db->sql_escape('m\_') . "%'" .
(($db->sql_layer == 'mssql' || $db->sql_layer == 'mssql_odbc') ? " ESCAPE '\\'" : ''),
AND o.auth_option " . $db->sql_like_expression('m_%'),
));
$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 LIKE \'%' . $db->sql_escape($word) . '%\'';
$sql_where .= " OR search_keywords " . $db->sql_like_expression('%' . $word . '%');
}
$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 LIKE '%" . $db->sql_escape($this->filename[$handle]) . ":%')";
OR template_included " . $db->sql_like_expression('%' . $this->filename[$handle] . ':%') . ')';
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);

View file

@ -31,7 +31,7 @@ unset($dbpasswd);
*/
$convertor_data = array(
'forum_name' => 'phpBB 2.0.x',
'version' => '1.0.RC2-dev',
'version' => '1.0.RC2',
'phpbb_version' => '3.0.0',
'author' => '<a href="http://www.phpbb.com/">phpBB Group</a>',
'dbms' => $dbms,

View file

@ -934,13 +934,13 @@ switch ($mode)
$s_find_active_time .= '<option value="' . $key . '"' . $selected . '>' . $value . '</option>';
}
$sql_where .= ($username) ? " AND u.username_clean LIKE '" . str_replace('*', '%', $db->sql_escape(utf8_clean_string($username))) . "'" : '';
$sql_where .= ($email) ? " AND u.user_email LIKE '" . str_replace('*', '%', $db->sql_escape($email)) . "' " : '';
$sql_where .= ($icq) ? " AND u.user_icq LIKE '" . str_replace('*', '%', $db->sql_escape($icq)) . "' " : '';
$sql_where .= ($aim) ? " AND u.user_aim LIKE '" . str_replace('*', '%', $db->sql_escape($aim)) . "' " : '';
$sql_where .= ($yahoo) ? " AND u.user_yim LIKE '" . str_replace('*', '%', $db->sql_escape($yahoo)) . "' " : '';
$sql_where .= ($msn) ? " AND u.user_msnm LIKE '" . str_replace('*', '%', $db->sql_escape($msn)) . "' " : '';
$sql_where .= ($jabber) ? " AND u.user_jabber LIKE '" . str_replace('*', '%', $db->sql_escape($jabber)) . "' " : '';
$sql_where .= ($username) ? ' AND u.username_clean ' . $db->sql_like_expression(str_replace('*', '%', utf8_clean_string($username))) : '';
$sql_where .= ($email) ? ' AND u.user_email ' . $db->sql_like_expression(str_replace('*', '%', $email)) . ' ' : '';
$sql_where .= ($icq) ? ' AND u.user_icq ' . $db->sql_like_expression(str_replace('*', '%', $icq)) . ' ' : '';
$sql_where .= ($aim) ? ' AND u.user_aim ' . $db->sql_like_expression(str_replace('*', '%', $aim)) . ' ' : '';
$sql_where .= ($yahoo) ? ' AND u.user_yim ' . $db->sql_like_expression(str_replace('*', '%', $yahoo)) . ' ' : '';
$sql_where .= ($msn) ? ' AND u.user_msnm ' . $db->sql_like_expression(str_replace('*', '%', $msn)) . ' ' : '';
$sql_where .= ($jabber) ? ' AND u.user_jabber ' . $db->sql_like_expression(str_replace('*', '%', $jabber)) . ' ' : '';
$sql_where .= (is_numeric($count)) ? ' AND u.user_posts ' . $find_key_match[$count_select] . ' ' . (int) $count . ' ' : '';
$sql_where .= (sizeof($joined) > 1) ? " AND u.user_regdate " . $find_key_match[$joined_select] . ' ' . gmmktime(0, 0, 0, intval($joined[1]), intval($joined[2]), intval($joined[0])) : '';
$sql_where .= (sizeof($active) > 1) ? " AND u.user_lastvisit " . $find_key_match[$active_select] . ' ' . gmmktime(0, 0, 0, $active[1], intval($active[2]), intval($active[0])) : '';
@ -1015,12 +1015,12 @@ switch ($mode)
{
for ($i = 97; $i < 123; $i++)
{
$sql_where .= " AND u.username_clean NOT LIKE '" . chr($i) . "%'";
$sql_where .= ' AND u.username_clean NOT ' . $db->sql_like_expression(chr($i) . '%');
}
}
else if ($first_char)
{
$sql_where .= " AND u.username_clean LIKE '" . $db->sql_escape(substr($first_char, 0, 1)) . "%'";
$sql_where .= ' AND u.username_clean ' . $db->sql_like_expression(substr($first_char, 0, 1) . '%');
}
// Are we looking at a usergroup? If so, fetch additional info

View file

@ -100,10 +100,11 @@ 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) ? ' LIKE ' : ' = ';
$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 = 'SELECT user_id
FROM ' . USERS_TABLE . "
WHERE username_clean $sql_where '" . $db->sql_escape(preg_replace('#\*+#', '%', utf8_clean_string($author))) . "'
WHERE $sql_where
AND user_type IN (" . USER_NORMAL . ', ' . USER_FOUNDER . ')';
$result = $db->sql_query_limit($sql, 100);