mirror of
https://github.com/vrana/adminer.git
synced 2025-08-30 01:30:12 +02:00
Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
507f335371 | ||
|
ea314b8103 | ||
|
e250470768 | ||
|
2fa42d50eb | ||
|
a366b7af09 | ||
|
b039a39e4d | ||
|
08e48c8641 | ||
|
78c2041cfd | ||
|
5d7c5fa268 | ||
|
8f1db4cf6f | ||
|
9daa88acca | ||
|
aa519b78ca | ||
|
aee800efed | ||
|
06d0f957d5 |
@@ -82,20 +82,39 @@ if ($_POST && !process_fields($row["fields"]) && !$error) {
|
||||
}
|
||||
|
||||
$partitioning = "";
|
||||
if ($partition_by[$row["partition_by"]]) {
|
||||
$partitions = array();
|
||||
if ($row["partition_by"] == 'RANGE' || $row["partition_by"] == 'LIST') {
|
||||
foreach (array_filter($row["partition_names"]) as $key => $val) {
|
||||
$value = $row["partition_values"][$key];
|
||||
$partitions[] = "\n PARTITION " . idf_escape($val) . " VALUES " . ($row["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
|
||||
if (support("partitioning")) {
|
||||
if (isset($partition_by[$row["partition_by"]])) {
|
||||
$params = array_filter($row, function ($key) {
|
||||
return preg_match('~^partition~', $key);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
|
||||
foreach ($params["partition_names"] as $key => $name) {
|
||||
if ($name === "") {
|
||||
unset($params["partition_names"][$key]);
|
||||
unset($params["partition_values"][$key]);
|
||||
}
|
||||
}
|
||||
|
||||
if ($params != get_partitions_info($TABLE)) {
|
||||
$partitions = [];
|
||||
if ($params["partition_by"] == 'RANGE' || $params["partition_by"] == 'LIST') {
|
||||
foreach ($params["partition_names"] as $key => $name) {
|
||||
$value = $params["partition_values"][$key];
|
||||
$partitions[] = "\n PARTITION " . idf_escape($name) . " VALUES " . ($params["partition_by"] == 'RANGE' ? "LESS THAN" : "IN") . ($value != "" ? " ($value)" : " MAXVALUE"); //! SQL injection
|
||||
}
|
||||
}
|
||||
|
||||
// $params["partition"] can be expression, not only column
|
||||
$partitioning .= "\nPARTITION BY {$params["partition_by"]}({$params["partition"]})";
|
||||
if ($partitions) {
|
||||
$partitioning .= " (" . implode(",", $partitions) . "\n)";
|
||||
} elseif ($params["partitions"]) {
|
||||
$partitioning .= " PARTITIONS " . (int)$params["partitions"];
|
||||
}
|
||||
}
|
||||
} elseif (preg_match("~partitioned~", $table_status["Create_options"])) {
|
||||
$partitioning .= "\nREMOVE PARTITIONING";
|
||||
}
|
||||
$partitioning .= "\nPARTITION BY $row[partition_by]($row[partition])" . ($partitions // $row["partition"] can be expression, not only column
|
||||
? " (" . implode(",", $partitions) . "\n)"
|
||||
: ($row["partitions"] ? " PARTITIONS " . (+$row["partitions"]) : "")
|
||||
);
|
||||
} elseif (support("partitioning") && preg_match("~partitioned~", $table_status["Create_options"])) {
|
||||
$partitioning .= "\nREMOVE PARTITIONING";
|
||||
}
|
||||
|
||||
$message = lang('Table has been altered.');
|
||||
@@ -141,13 +160,9 @@ if (!$_POST) {
|
||||
}
|
||||
|
||||
if (support("partitioning")) {
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($TABLE);
|
||||
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_ORDINAL_POSITION, PARTITION_EXPRESSION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
list($row["partition_by"], $row["partitions"], $row["partition"]) = $result->fetch_row();
|
||||
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
|
||||
$partitions[""] = "";
|
||||
$row["partition_names"] = array_keys($partitions);
|
||||
$row["partition_values"] = array_values($partitions);
|
||||
$row += get_partitions_info($TABLE);
|
||||
$row["partition_names"][] = "";
|
||||
$row["partition_values"][] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -637,6 +637,10 @@ WHERE sys1.xtype = 'TR' AND sys2.name = " . q($table)
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
return array();
|
||||
}
|
||||
|
@@ -1074,6 +1074,16 @@ if (!defined("DRIVER")) {
|
||||
return $strictMode;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
static $c_style = null;
|
||||
|
||||
if ($c_style === null) {
|
||||
$c_style = strpos(get_key_vals("SHOW VARIABLES LIKE 'sql_mode'")["sql_mode"], 'NO_BACKSLASH_ESCAPES') === false;
|
||||
}
|
||||
|
||||
return $c_style;
|
||||
}
|
||||
|
||||
/** Get process list
|
||||
* @return array ($row)
|
||||
*/
|
||||
|
@@ -493,6 +493,10 @@ AND c_src.TABLE_NAME = " . q($table);
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function process_list() {
|
||||
return get_rows('SELECT sess.process AS "process", sess.username AS "user", sess.schemaname AS "schema", sess.status AS "status", sess.wait_class AS "wait_class", sess.seconds_in_wait AS "seconds_in_wait", sql.sql_text AS "sql_text", sess.machine AS "machine", sess.port AS "port"
|
||||
FROM v$session sess LEFT OUTER JOIN v$sql sql
|
||||
|
@@ -885,6 +885,16 @@ AND typelem = 0"
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
static $c_style = null;
|
||||
|
||||
if ($c_style === null) {
|
||||
$c_style = get_vals("SHOW standard_conforming_strings")[0] == "off";
|
||||
}
|
||||
|
||||
return $c_style;
|
||||
}
|
||||
|
||||
function process_list() {
|
||||
return get_rows("SELECT * FROM pg_stat_activity ORDER BY " . (min_version(9.2) ? "pid" : "procpid"));
|
||||
}
|
||||
@@ -949,6 +959,7 @@ AND typelem = 0"
|
||||
"char|text" => "||",
|
||||
)
|
||||
),
|
||||
'c_style_escapes' => true,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -771,6 +771,10 @@ if (isset($_GET["sqlite"]) || isset($_GET["sqlite2"])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
function is_c_style_escapes() {
|
||||
return true;
|
||||
}
|
||||
|
||||
function show_status() {
|
||||
$return = array();
|
||||
foreach (get_vals("PRAGMA compile_options") as $option) {
|
||||
|
@@ -6,6 +6,7 @@ function adminer_errors($errno, $errstr) {
|
||||
error_reporting(6135); // errors and warnings
|
||||
set_error_handler('adminer_errors', E_WARNING);
|
||||
|
||||
include "../adminer/include/debug.inc.php";
|
||||
include "../adminer/include/coverage.inc.php";
|
||||
|
||||
// disable filter.default
|
||||
|
14
adminer/include/debug.inc.php
Normal file
14
adminer/include/debug.inc.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
function dump($value)
|
||||
{
|
||||
echo "<pre>";
|
||||
var_export($value);
|
||||
echo "</pre>\n";
|
||||
}
|
||||
|
||||
function dumpe($value)
|
||||
{
|
||||
dump($value);
|
||||
exit;
|
||||
}
|
@@ -221,12 +221,17 @@ function process_type($field, $collate = "COLLATE") {
|
||||
* @return array array("field", "type", "NULL", "DEFAULT", "ON UPDATE", "COMMENT", "AUTO_INCREMENT")
|
||||
*/
|
||||
function process_field($field, $type_field) {
|
||||
// MariaDB exports CURRENT_TIMESTAMP as a function.
|
||||
if ($field["on_update"]) {
|
||||
$field["on_update"] = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $field["on_update"]);
|
||||
}
|
||||
|
||||
return array(
|
||||
idf_escape(trim($field["field"])),
|
||||
process_type($type_field),
|
||||
($field["null"] ? " NULL" : " NOT NULL"), // NULL for timestamp
|
||||
default_value($field),
|
||||
(preg_match('~timestamp|datetime~', $field["type"]) && $field["on_update"] ? " ON UPDATE $field[on_update]" : ""),
|
||||
(preg_match('~timestamp|datetime~', $field["type"]) && $field["on_update"] ? " ON UPDATE " . $field["on_update"] : ""),
|
||||
(support("comment") && $field["comment"] != "" ? " COMMENT " . q($field["comment"]) : ""),
|
||||
($field["auto_increment"] ? auto_increment() : null),
|
||||
);
|
||||
@@ -240,10 +245,13 @@ function default_value($field) {
|
||||
$default = $field["default"];
|
||||
if ($default === null) return "";
|
||||
|
||||
if (preg_match('~^GENERATED ~i', $default)) {
|
||||
if (stripos($default, "GENERATED ") === 0) {
|
||||
return " $default";
|
||||
}
|
||||
|
||||
// MariaDB exports CURRENT_TIMESTAMP as a function.
|
||||
$default = str_ireplace("current_timestamp()", "CURRENT_TIMESTAMP", $default);
|
||||
|
||||
$quote = preg_match('~char|binary|text|enum|set~', $field["type"]) || preg_match('~^(?![a-z])~i', $default);
|
||||
|
||||
return " DEFAULT " . ($quote ? q($default) : $default);
|
||||
@@ -376,25 +384,43 @@ function normalize_enum($match) {
|
||||
return "'" . str_replace("'", "''", addcslashes(stripcslashes(str_replace($match[0][0] . $match[0][0], $match[0][0], substr($match[0], 1, -1))), '\\')) . "'";
|
||||
}
|
||||
|
||||
/** Issue grant or revoke commands
|
||||
* @param string GRANT or REVOKE
|
||||
* @param array
|
||||
* @param string
|
||||
* @param string
|
||||
* @return bool
|
||||
*/
|
||||
function grant($grant, $privileges, $columns, $on) {
|
||||
if (!$privileges) {
|
||||
return true;
|
||||
/**
|
||||
* Issue grant or revoke commands.
|
||||
*
|
||||
* @param bool $grant
|
||||
* @param array $privileges
|
||||
* @param string $columns
|
||||
* @param string $on
|
||||
* @param string $user
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function grant($grant, array $privileges, $columns, $on, $user) {
|
||||
if (!$privileges) return true;
|
||||
|
||||
if ($privileges == ["ALL PRIVILEGES", "GRANT OPTION"]) {
|
||||
if ($grant) {
|
||||
return (bool) queries("GRANT ALL PRIVILEGES ON $on TO $user WITH GRANT OPTION");
|
||||
} else {
|
||||
return queries("REVOKE ALL PRIVILEGES ON $on FROM $user") &&
|
||||
queries("REVOKE GRANT OPTION ON $on FROM $user");
|
||||
}
|
||||
}
|
||||
if ($privileges == array("ALL PRIVILEGES", "GRANT OPTION")) {
|
||||
// can't be granted or revoked together
|
||||
return ($grant == "GRANT"
|
||||
? queries("$grant ALL PRIVILEGES$on WITH GRANT OPTION")
|
||||
: queries("$grant ALL PRIVILEGES$on") && queries("$grant GRANT OPTION$on")
|
||||
);
|
||||
|
||||
if ($privileges == ["GRANT OPTION", "PROXY"]) {
|
||||
if ($grant) {
|
||||
return (bool) queries("GRANT PROXY ON $on TO $user WITH GRANT OPTION");
|
||||
} else {
|
||||
return (bool) queries("REVOKE PROXY ON $on FROM $user");
|
||||
}
|
||||
}
|
||||
return queries("$grant " . preg_replace('~(GRANT OPTION)\([^)]*\)~', '\1', implode("$columns, ", $privileges) . $columns) . $on);
|
||||
|
||||
return (bool) queries(
|
||||
($grant ? "GRANT " : "REVOKE ") .
|
||||
preg_replace('~(GRANT OPTION)\([^)]*\)~', '$1', implode("$columns, ", $privileges) . $columns) .
|
||||
" ON $on " .
|
||||
($grant ? "TO " : "FROM ") . $user
|
||||
);
|
||||
}
|
||||
|
||||
/** Drop old object and create a new one
|
||||
@@ -523,9 +549,9 @@ function tar_file($filename, $tmp_file) {
|
||||
function ini_bytes($ini) {
|
||||
$val = ini_get($ini);
|
||||
switch (strtolower(substr($val, -1))) {
|
||||
case 'g': $val *= 1024; // no break
|
||||
case 'm': $val *= 1024; // no break
|
||||
case 'k': $val *= 1024;
|
||||
case 'g': $val = (int)$val * 1024; // no break
|
||||
case 'm': $val = (int)$val * 1024; // no break
|
||||
case 'k': $val = (int)$val * 1024;
|
||||
}
|
||||
return $val;
|
||||
}
|
||||
|
@@ -477,24 +477,36 @@ function escape_key($key) {
|
||||
*/
|
||||
function where($where, $fields = array()) {
|
||||
global $connection, $jush;
|
||||
$return = array();
|
||||
|
||||
$conditions = [];
|
||||
|
||||
foreach ((array) $where["where"] as $key => $val) {
|
||||
$key = bracket_escape($key, 1); // 1 - back
|
||||
$column = escape_key($key);
|
||||
$return[] = $column
|
||||
. ($jush == "sql" && is_numeric($val) && preg_match('~\.~', $val) ? " LIKE " . q($val) // LIKE because of floats but slow with ints
|
||||
: ($jush == "mssql" ? " LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val)) // LIKE because of text
|
||||
: " = " . unconvert_field($fields[$key], q($val))
|
||||
))
|
||||
; //! enum and set
|
||||
if ($jush == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) { // not just [a-z] to catch non-ASCII characters
|
||||
$return[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
|
||||
|
||||
if ($jush == "sql" && $fields[$key]["type"] == "json") {
|
||||
$conditions[] = "$column = CAST(" . q($val) . " AS JSON)";
|
||||
} elseif ($jush == "sql" && is_numeric($val) && strpos($val, ".") !== false) {
|
||||
// LIKE because of floats but slow with ints.
|
||||
$conditions[] = "$column LIKE " . q($val);
|
||||
} elseif ($jush == "mssql") {
|
||||
// LIKE because of text.
|
||||
$conditions[] = "$column LIKE " . q(preg_replace('~[_%[]~', '[\0]', $val));
|
||||
} else {
|
||||
$conditions[] = "$column = " . unconvert_field($fields[$key], q($val));
|
||||
}
|
||||
|
||||
// Not just [a-z] to catch non-ASCII characters.
|
||||
if ($jush == "sql" && preg_match('~char|text~', $fields[$key]["type"]) && preg_match("~[^ -@]~", $val)) {
|
||||
$conditions[] = "$column = " . q($val) . " COLLATE " . charset($connection) . "_bin";
|
||||
}
|
||||
}
|
||||
|
||||
foreach ((array) $where["null"] as $key) {
|
||||
$return[] = escape_key($key) . " IS NULL";
|
||||
$conditions[] = escape_key($key) . " IS NULL";
|
||||
}
|
||||
return implode(" AND ", $return);
|
||||
|
||||
return implode(" AND ", $conditions);
|
||||
}
|
||||
|
||||
/** Create SQL condition from query string
|
||||
@@ -935,8 +947,9 @@ function enum_input($type, $attrs, $field, $value, $empty = null) {
|
||||
*/
|
||||
function input($field, $value, $function) {
|
||||
global $types, $adminer, $jush;
|
||||
|
||||
$name = h(bracket_escape($field["field"]));
|
||||
echo "<td class='function'>";
|
||||
|
||||
if (is_array($value) && !$function) {
|
||||
$args = array($value);
|
||||
if (version_compare(PHP_VERSION, 5.4) >= 0) {
|
||||
@@ -950,13 +963,18 @@ function input($field, $value, $function) {
|
||||
$function = null;
|
||||
}
|
||||
$functions = (isset($_GET["select"]) || $reset ? array("orig" => lang('original')) : array()) + $adminer->editFunctions($field);
|
||||
$attrs = " name='fields[$name]'";
|
||||
|
||||
$disabled = stripos($field["default"], "GENERATED ALWAYS AS ") === 0 ? " disabled=''" : "";
|
||||
$attrs = " name='fields[$name]' $disabled";
|
||||
|
||||
echo "<td class='function'>";
|
||||
|
||||
if ($field["type"] == "enum") {
|
||||
echo h($functions[""]) . "<td>" . $adminer->editInput($_GET["edit"], $field, $attrs, $value);
|
||||
} else {
|
||||
$has_function = (in_array($function, $functions) || isset($functions[$function]));
|
||||
echo (count($functions) > 1
|
||||
? "<select name='function[$name]'>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
||||
? "<select name='function[$name]' $disabled>" . optionlist($functions, $function === null || $has_function ? $function : "") . "</select>"
|
||||
. on_help("getTarget(event).value.replace(/^SQL\$/, '')", 1)
|
||||
. script("qsl('select').onchange = functionChange;", "")
|
||||
: h(reset($functions))
|
||||
@@ -1021,6 +1039,11 @@ function input($field, $value, $function) {
|
||||
*/
|
||||
function process_input($field) {
|
||||
global $adminer, $driver;
|
||||
|
||||
if (stripos($field["default"], "GENERATED ALWAYS AS ") === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$idf = bracket_escape($field["field"]);
|
||||
$function = $_POST["function"][$idf];
|
||||
$value = $_POST["fields"][$idf];
|
||||
@@ -1111,6 +1134,27 @@ function search_tables() {
|
||||
echo ($sep ? "<p class='message'>" . lang('No tables.') : "</ul>") . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @return array
|
||||
*/
|
||||
function get_partitions_info($table) {
|
||||
global $connection;
|
||||
|
||||
$from = "FROM information_schema.PARTITIONS WHERE TABLE_SCHEMA = " . q(DB) . " AND TABLE_NAME = " . q($table);
|
||||
|
||||
$result = $connection->query("SELECT PARTITION_METHOD, PARTITION_EXPRESSION, PARTITION_ORDINAL_POSITION $from ORDER BY PARTITION_ORDINAL_POSITION DESC LIMIT 1");
|
||||
|
||||
$info = [];
|
||||
list($info["partition_by"], $info["partition"], $info["partitions"]) = $result->fetch_row();
|
||||
|
||||
$partitions = get_key_vals("SELECT PARTITION_NAME, PARTITION_DESCRIPTION $from AND PARTITION_NAME != '' ORDER BY PARTITION_ORDINAL_POSITION");
|
||||
$info["partition_names"] = array_keys($partitions);
|
||||
$info["partition_values"] = array_values($partitions);
|
||||
|
||||
return $info;
|
||||
}
|
||||
|
||||
/** Send headers for export
|
||||
* @param string
|
||||
* @param bool
|
||||
@@ -1441,6 +1485,7 @@ function edit_form($table, $fields, $row, $update) {
|
||||
$adminer->editRowPrint($table, $fields, $row, $update);
|
||||
if ($row === false) {
|
||||
echo "<p class='error'>" . lang('No rows.') . "\n";
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<form action="" method="post" enctype="multipart/form-data" id="form">
|
||||
|
@@ -1,2 +1,2 @@
|
||||
<?php
|
||||
$VERSION = "4.9.2";
|
||||
$VERSION = "4.9.3";
|
||||
|
@@ -32,8 +32,8 @@ if (!$error && $_POST) {
|
||||
}
|
||||
|
||||
if (is_string($query)) { // get_file() returns error as number, fread() as false
|
||||
if (function_exists('memory_get_usage')) {
|
||||
@ini_set("memory_limit", max(ini_bytes("memory_limit"), 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
|
||||
if (function_exists('memory_get_usage') && ($memory_limit = ini_bytes("memory_limit")) != "-1") {
|
||||
@ini_set("memory_limit", max($memory_limit, 2 * strlen($query) + memory_get_usage() + 8e6)); // @ - may be disabled, 2 - substr and trim, 8e6 - other variables
|
||||
}
|
||||
|
||||
if ($query != "" && strlen($query) < 1e6) { // don't add big queries
|
||||
@@ -81,7 +81,21 @@ if (!$error && $_POST) {
|
||||
$offset = $pos + strlen($found);
|
||||
|
||||
if ($found && rtrim($found) != $delimiter) { // find matching quote or comment end
|
||||
while (preg_match('(' . ($found == '/*' ? '\*/' : ($found == '[' ? ']' : (preg_match('~^-- |^#~', $found) ? "\n" : preg_quote($found) . "|\\\\."))) . '|$)s', $query, $match, PREG_OFFSET_CAPTURE, $offset)) { //! respect sql_mode NO_BACKSLASH_ESCAPES
|
||||
$c_style_escapes = is_c_style_escapes() || ($jush == "pgsql" && ($pos > 0 && strtolower($query[$pos - 1]) == "e"));
|
||||
|
||||
$pattern = '(';
|
||||
if ($found == '/*') {
|
||||
$pattern .= '\*/';
|
||||
} elseif ($found == '[') {
|
||||
$pattern .= ']';
|
||||
} elseif (preg_match('~^-- |^#~', $found)) {
|
||||
$pattern .= "\n";
|
||||
} else {
|
||||
$pattern .= preg_quote($found) . ($c_style_escapes ? "|\\\\." : "");
|
||||
}
|
||||
$pattern .= '|$)s';
|
||||
|
||||
while (preg_match($pattern, $query, $match, PREG_OFFSET_CAPTURE, $offset)) {
|
||||
$s = $match[0][0];
|
||||
if (!$s && $fp && !feof($fp)) {
|
||||
$query .= fread($fp, 1e5);
|
||||
@@ -169,7 +183,8 @@ if (!$error && $_POST) {
|
||||
stop_session();
|
||||
}
|
||||
if (!$_POST["only_errors"]) {
|
||||
echo "<p class='message' title='" . h($connection->info) . "'>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n";
|
||||
$title = isset($connection->info) ? "title='" . h($connection->info) . "'" : "";
|
||||
echo "<p class='message' $title>" . lang('Query executed OK, %d row(s) affected.', $affected) . "$time\n";
|
||||
}
|
||||
}
|
||||
echo ($warnings ? "<div id='$warnings_id' class='hidden'>\n$warnings</div>\n" : "");
|
||||
|
@@ -19,15 +19,18 @@ fieldset { display: inline; vertical-align: top; padding: .5em .8em; margin: .8e
|
||||
p { margin: .8em 20px 0 0; }
|
||||
img { vertical-align: middle; border: 0; }
|
||||
td img { max-width: 200px; max-height: 200px; }
|
||||
code { background: #eee; }
|
||||
tbody tr:hover td, tbody tr:hover th { background: #eee; }
|
||||
code { font-size: 110%; padding: 1px 2px; background: #eee; }
|
||||
pre { margin: 1em 0 0; }
|
||||
pre, textarea { font: 100%/1.25 monospace; }
|
||||
pre code { display: block; font-size: 100%; }
|
||||
pre, textarea { font: 110%/1.25 monospace; }
|
||||
pre.jush { background: #fff; }
|
||||
input, select { vertical-align: middle; }
|
||||
input.default { box-shadow: 1px 1px 1px #777; }
|
||||
input.required { box-shadow: 1px 1px 1px red; }
|
||||
input.maxlength { box-shadow: 1px 1px 1px red; }
|
||||
input.wayoff { left: -1000px; position: absolute; }
|
||||
.center { text-align: center; }
|
||||
.block { display: block; }
|
||||
.version { color: #777; font-size: 67%; }
|
||||
.js .hidden, .nojs .jsonly { display: none; }
|
||||
|
@@ -211,13 +211,21 @@ function tableCheck() {
|
||||
}
|
||||
}
|
||||
|
||||
/** Uncheck single element
|
||||
* @param string
|
||||
*/
|
||||
/**
|
||||
* Uncheck single element.
|
||||
*/
|
||||
function formUncheck(id) {
|
||||
var el = qs('#' + id);
|
||||
el.checked = false;
|
||||
trCheck(el);
|
||||
formUncheckAll("#" + id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Uncheck elements matched by selector.
|
||||
*/
|
||||
function formUncheckAll(selector) {
|
||||
for (const element of qsa(selector)) {
|
||||
element.checked = false;
|
||||
trCheck(element);
|
||||
}
|
||||
}
|
||||
|
||||
/** Get number of checked elements matching given name
|
||||
|
@@ -85,8 +85,8 @@ if ($_POST && !$error) {
|
||||
unset($grants[$object]);
|
||||
}
|
||||
if (preg_match('~^(.+)\s*(\(.*\))?$~U', $object, $match) && (
|
||||
!grant("REVOKE", $revoke, $match[2], " ON $match[1] FROM $new_user") //! SQL injection
|
||||
|| !grant("GRANT", $grant, $match[2], " ON $match[1] TO $new_user")
|
||||
!grant(false, $revoke, $match[2], $match[1], $new_user) //! SQL injection
|
||||
|| !grant(true, $grant, $match[2], $match[1], $new_user)
|
||||
)) {
|
||||
$error = true;
|
||||
break;
|
||||
@@ -100,7 +100,7 @@ if ($_POST && !$error) {
|
||||
} elseif (!isset($_GET["grant"])) {
|
||||
foreach ($grants as $object => $revoke) {
|
||||
if (preg_match('~^(.+)(\(.*\))?$~U', $object, $match)) {
|
||||
grant("REVOKE", array_keys($revoke), $match[2], " ON $match[1] FROM $new_user");
|
||||
grant(false, array_keys($revoke), $match[2], $match[1], $new_user);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -150,33 +150,63 @@ foreach ($grants as $object => $grant) {
|
||||
}
|
||||
echo "</thead>\n";
|
||||
|
||||
foreach (array(
|
||||
foreach ([
|
||||
"" => "",
|
||||
"Server Admin" => lang('Server'),
|
||||
"Databases" => lang('Database'),
|
||||
"Tables" => lang('Table'),
|
||||
"Columns" => lang('Column'),
|
||||
"Procedures" => lang('Routine'),
|
||||
) as $context => $desc) {
|
||||
] as $context => $desc) {
|
||||
foreach ((array) $privileges[$context] as $privilege => $comment) {
|
||||
echo "<tr" . odd() . "><td" . ($desc ? ">$desc<td" : " colspan='2'") . ' lang="en" title="' . h($comment) . '">' . h($privilege);
|
||||
echo "<tr" . odd() . ">";
|
||||
if ($desc) {
|
||||
echo "<td>$desc</td>";
|
||||
}
|
||||
echo "<td" . (!$desc ? " colspan='2'" : "") . ' lang="en" title="' . h($comment) . '">' . h($privilege) . "</td>";
|
||||
|
||||
$i = 0;
|
||||
|
||||
foreach ($grants as $object => $grant) {
|
||||
$name = "'grants[$i][" . h(strtoupper($privilege)) . "]'";
|
||||
$value = $grant[strtoupper($privilege)];
|
||||
if ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*")) {
|
||||
echo "<td>";
|
||||
|
||||
$proxiedUser = strpos($object, "@") !== false;
|
||||
$newObject = $object == ".*";
|
||||
$allPrivileges = $privilege == "All privileges";
|
||||
$grantOption = $privilege == "Grant option";
|
||||
|
||||
if ($object == "*.*" && $privilege == "Proxy") {
|
||||
echo "<td></td>";
|
||||
} elseif ($proxiedUser && $privilege != "Proxy" && !$grantOption) {
|
||||
echo "<td></td>";
|
||||
} elseif ($context == "Server Admin" && $object != (isset($grants["*.*"]) ? "*.*" : ".*") && !(($proxiedUser || $newObject) && $privilege == "Proxy")) {
|
||||
echo "<td></td>";
|
||||
} elseif (isset($_GET["grant"])) {
|
||||
echo "<td><select name=$name><option><option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</select>";
|
||||
echo "<td><select name=$name>" .
|
||||
"<option></option>" .
|
||||
"<option value='1'" . ($value ? " selected" : "") . ">" . lang('Grant') . "</option>" .
|
||||
"<option value='0'" . ($value == "0" ? " selected" : "") . ">" . lang('Revoke') . "</option>" .
|
||||
"</select></td>";
|
||||
} else {
|
||||
echo "<td align='center'><label class='block'>";
|
||||
echo "<input type='checkbox' name=$name value='1'" . ($value ? " checked" : "") . ($privilege == "All privileges"
|
||||
? " id='grants-$i-all'>" //! uncheck all except grant if all is checked
|
||||
: ">" . ($privilege == "Grant option" ? "" : script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };")));
|
||||
echo "<td class='center'><label class='block'>";
|
||||
echo "<input type='checkbox' name=$name value='1'" .
|
||||
($value ? " checked" : "") .
|
||||
($allPrivileges ? " id='grants-$i-all'" : (!$grantOption ? " class='grants-$i'" : "")) .
|
||||
">";
|
||||
|
||||
if ($allPrivileges) {
|
||||
echo script("qsl('input').onclick = function () { if (this.checked) formUncheckAll('.grants-$i'); };");
|
||||
} elseif (!$grantOption) {
|
||||
echo script("qsl('input').onclick = function () { if (this.checked) formUncheck('grants-$i-all'); };");
|
||||
}
|
||||
echo "</label>";
|
||||
}
|
||||
|
||||
$i++;
|
||||
}
|
||||
|
||||
echo "</tr>";
|
||||
}
|
||||
}
|
||||
|
||||
|
14
changes.txt
14
changes.txt
@@ -1,3 +1,17 @@
|
||||
Adminer 4.9.3 (released 2024-10-02):
|
||||
- MySQL, PostgreSQL: Fix queries splitting and string constants.
|
||||
- MySQL: Fix where clause for JSON column.
|
||||
- MySQL: Fix editing user's proxy privilege, refactoring.
|
||||
- MariaDB: Fix comparing CURRENT_TIMESTAMP definition while altering a table.
|
||||
- PostgreSQL: Fix editing record that contains a field with GENERATED ALWAYS default value.
|
||||
- Fix using undefined Min_DB::info property.
|
||||
- Do not include unchanged PARTITION BY definition into ALTER TABLE query.
|
||||
- Do not limit unlimited memory while executing queries.
|
||||
- Fix number conversion warning while reading INI settings.
|
||||
- Hide invalid edit form if table record is not found.
|
||||
- CSS: Fix background color of <pre> used as edit field.
|
||||
- CSS: Bigger font size for code blocks.
|
||||
|
||||
Adminer 4.9.2 (released 2024-09-18):
|
||||
- Fix textarea height for single-line inputs (used typically for SQLite text field).
|
||||
- Fix undefined property in error message if driver does not support error number (e.g. PostgreSQL).
|
||||
|
Reference in New Issue
Block a user