diff --git a/adminer/include/adminer.inc.php b/adminer/include/adminer.inc.php index cc4c40d7..fb4bbd72 100644 --- a/adminer/include/adminer.inc.php +++ b/adminer/include/adminer.inc.php @@ -443,8 +443,7 @@ username.form['auth[driver]'].onchange(); && (!preg_match("~[\x80-\xFF]~", $val["val"]) || $is_text) ) { $name = idf_escape($name); - $charset = charset($connection); - $cols[] = ($jush == "sql" && $is_text && !preg_match("~^$charset" . "_~", $field["collation"]) ? "CONVERT($name USING $charset)" : $name); + $cols[] = ($jush == "sql" && $is_text && !preg_match("~^utf8_~", $field["collation"]) ? "CONVERT($name USING " . charset($connection) . ")" : $name); } } $return[] = ($cols ? "(" . implode("$cond OR ", $cols) . "$cond)" : "0"); diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 73a9d772..8e6a35a6 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -375,6 +375,17 @@ function unique_array($row, $indexes) { } } +/** Escape column key used in where() +* @param string +* @return string +*/ +function escape_key($key) { + if (preg_match('(^([\w(]+)(' . str_replace("_", ".*", preg_quote(idf_escape("_"))) . ')([ \w)]+)$)', $key, $match)) { //! columns looking like functions + return $match[1] . idf_escape(idf_unescape($match[2])) . $match[3]; //! SQL injection + } + return idf_escape($key); +} + /** Create SQL condition from parsed query string * @param array parsed query string * @param array @@ -383,10 +394,9 @@ function unique_array($row, $indexes) { function where($where, $fields = array()) { global $connection, $jush; $return = array(); - $function_pattern = '(^[\w\(]+(' . str_replace("_", ".*", preg_quote(idf_escape("_"))) . ')?\)+$)'; //! columns looking like functions foreach ((array) $where["where"] as $key => $val) { $key = bracket_escape($key, 1); // 1 - back - $column = (preg_match($function_pattern, $key) ? $key : idf_escape($key)); //! SQL injection + $column = escape_key($key); $return[] = $column . (($jush == "sql" && preg_match('~^[0-9]*\\.[0-9]*$~', $val)) || $jush == "mssql" ? " LIKE " . q(addcslashes($val, "%_\\")) @@ -398,7 +408,7 @@ function where($where, $fields = array()) { } } foreach ((array) $where["null"] as $key) { - $return[] = (preg_match($function_pattern, $key) ? $key : idf_escape($key)) . " IS NULL"; + $return[] = escape_key($key) . " IS NULL"; } return implode(" AND ", $return); } diff --git a/adminer/select.inc.php b/adminer/select.inc.php index 3e70feb6..20a335bc 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -360,7 +360,8 @@ if (!$columns && support("table")) { $unique_idf = ""; foreach ($unique_array as $key => $val) { if (($jush == "sql" || $jush == "pgsql") && strlen($val) > 64) { - $key = "MD5(" . (strpos($key, '(') ? $key : idf_escape($key)) . ")"; //! columns looking like functions + $key = (strpos($key, '(') ? $key : idf_escape($key)); //! columns looking like functions + $key = "MD5(" . ($jush == 'sql' && preg_match("~^utf8_~", $fields[$key]["collation"]) ? $key : "CONVERT($key USING " . charset($connection) . ")") . ")"; $val = md5($val); } $unique_idf .= "&" . ($val !== null ? urlencode("where[" . bracket_escape($key) . "]") . "=" . urlencode($val) : "null%5B%5D=" . urlencode($key)); diff --git a/changes.txt b/changes.txt index bb465bc8..820d87f6 100644 --- a/changes.txt +++ b/changes.txt @@ -2,6 +2,7 @@ Adminer 4.1.1-dev: Fix reading routine column collations Unlock session in alter database Make master key unreadable to others (bug #410) +Fix edit by long non-utf8 string MySQL: Use utf8mb4 if available Adminer 4.1.0 (released 2014-04-18)