diff --git a/adminer/drivers/mongo.inc.php b/adminer/drivers/mongo.inc.php index 1d0961f2..26b757b6 100644 --- a/adminer/drivers/mongo.inc.php +++ b/adminer/drivers/mongo.inc.php @@ -205,9 +205,6 @@ if (isset($_GET["mongo"])) { return $connection->_db->selectCollection($_GET["select"])->count($where); } - $operators = array("="); - $operator_regexp = null; - } elseif (class_exists('MongoDB\Driver\Manager')) { class Min_DB { var $extension = "MongoDB", $server_info = MONGODB_VERSION, $affected_rows, $error, $last_id; @@ -556,30 +553,6 @@ if (isset($_GET["mongo"])) { } return $data; } - - $operators = array( - "=", - "!=", - ">", - "<", - ">=", - "<=", - "regex", - "(f)=", - "(f)!=", - "(f)>", - "(f)<", - "(f)>=", - "(f)<=", - "(date)=", - "(date)!=", - "(date)>", - "(date)<", - "(date)>=", - "(date)<=", - ); - - $operator_regexp = 'regex'; } function table($idf) { @@ -736,7 +709,38 @@ if (isset($_GET["mongo"])) { } function driver_config() { - global $operators, $operator_regexp; + if (class_exists('MongoDB')) { + $operators = ["="]; + $operator_regexp = null; + } elseif (class_exists('MongoDB\Driver\Manager')) { + $operators = [ + "=", + "!=", + ">", + "<", + ">=", + "<=", + "regex", + "(f)=", + "(f)!=", + "(f)>", + "(f)<", + "(f)>=", + "(f)<=", + "(date)=", + "(date)!=", + "(date)>", + "(date)<", + "(date)>=", + "(date)<=", + ]; + + $operator_regexp = 'regex'; + } else { + $operators = ["="]; + $operator_regexp = null; + } + return array( 'possible_drivers' => array("mongo", "mongodb"), 'jush' => "mongo", diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 6321c790..789d071b 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -1,8 +1,8 @@ "MySQL") + $drivers; +$drivers["mysql"] = "MySQL"; -if (!defined("DRIVER")) { - define("DRIVER", "server"); // server - backwards compatibility +if (isset($_GET["mysql"])) { + define("DRIVER", "mysql"); // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable if (extension_loaded("mysqli")) { class Min_DB extends MySQLi { diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index a84e5bc7..ad00e412 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -73,39 +73,73 @@ if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) { @ini_set("zend.ze1_compatibility_mode", false); // @ - deprecated @ini_set("precision", 15); // @ - can be disabled, 15 - internal PHP precision +// Migration for backward compatibility. This will keep MySQL users logged in. +if (isset($_GET["username"])) { + // Old 'server' URL param. + if (isset($_GET["server"])) { + $_GET["mysql"] = $_GET["server"]; + unset($_GET["server"]); + } + + // No URL param for any driver. + $driver_params = array_filter(["mysql", "pgsql", "sqlite", "sqlite2", "oracle", "mssql", "mongo", "clickhouse", "elastic", "elastic5", "firebird", "simpledb"], function ($driver) { + return isset($_GET[$driver]); + }); + if (!$driver_params) { + $_GET["mysql"] = ""; + } + + // Migrate session data. + if (isset($_SESSION["pwds"]["server"])) { + foreach (["pwds", "db", "dbs", "queries"] as $key) { + if (isset($_SESSION[$key]["server"])) { + $_SESSION[$key]["mysql"] = $_SESSION[$key]["server"]; + unset($_SESSION[$key]["server"]); + } + } + } +} + include "../adminer/include/lang.inc.php"; include "../adminer/lang/$LANG.inc.php"; + include "../adminer/include/pdo.inc.php"; include "../adminer/include/driver.inc.php"; -include "../adminer/drivers/sqlite.inc.php"; + +include "../adminer/drivers/mysql.inc.php"; include "../adminer/drivers/pgsql.inc.php"; +include "../adminer/drivers/sqlite.inc.php"; include "../adminer/drivers/oracle.inc.php"; include "../adminer/drivers/mssql.inc.php"; include "../adminer/drivers/mongo.inc.php"; + include "./include/adminer.inc.php"; -$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer); -include "../adminer/drivers/mysql.inc.php"; // must be included as last driver +$adminer = (function_exists('adminer_object') ? adminer_object() : new Adminer()); -$config = driver_config(); -$possible_drivers = $config['possible_drivers']; -$jush = $config['jush']; -$types = $config['types']; -$structured_types = $config['structured_types']; -$unsigned = $config['unsigned']; -$operators = $config['operators']; -$operator_like = $config['operator_like']; -$operator_regexp = $config['operator_regexp']; -$functions = $config['functions']; -$grouping = $config['grouping']; -$edit_functions = $config['edit_functions']; +if (defined("DRIVER")) { + $config = driver_config(); + $possible_drivers = $config['possible_drivers']; + $jush = $config['jush']; + $types = $config['types']; + $structured_types = $config['structured_types']; + $unsigned = $config['unsigned']; + $operators = $config['operators']; + $operator_like = $config['operator_like']; + $operator_regexp = $config['operator_regexp']; + $functions = $config['functions']; + $grouping = $config['grouping']; + $edit_functions = $config['edit_functions']; -if ($adminer->operators === null) { - $adminer->operators = $operators; - $adminer->operator_like = $operator_like; - $adminer->operator_regexp = $operator_regexp; + if ($adminer->operators === null) { + $adminer->operators = $operators; + $adminer->operator_like = $operator_like; + $adminer->operator_regexp = $operator_regexp; + } +} else { + define("DRIVER", null); } -define("SERVER", $_GET[DRIVER]); // read from pgsql=localhost +define("SERVER", DRIVER ? $_GET[DRIVER] : null); // read from pgsql=localhost define("DB", $_GET["db"]); // for the sake of speed and size define("ME", preg_replace('~\?.*~', '', relative_uri()) . '?' . (sid() ? SID . '&' : '') diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 28998c7c..4afe5996 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -614,7 +614,7 @@ function auth_url($vendor, $server, $username, $db = null) { preg_match('~([^?]*)\??(.*)~', remove_from_uri(implode("|", array_keys($drivers)) . "|username|" . ($db !== null ? "db|" : "") . session_name()), $match); return "$match[1]?" . (sid() ? SID . "&" : "") - . ($vendor != "server" || $server != "" ? urlencode($vendor) . "=" . urlencode($server) . "&" : "") + . urlencode($vendor) . "=" . urlencode($server) . "&" . "username=" . urlencode($username) . ($db != "" ? "&db=" . urlencode($db) : "") . ($match[2] ? "&$match[2]" : "") diff --git a/compile.php b/compile.php index 013dc5e6..684e59d4 100755 --- a/compile.php +++ b/compile.php @@ -42,15 +42,10 @@ function replace_lang($match) { } function put_file($match) { - global $project, $selected_languages, $driver; + global $project, $selected_languages, $single_driver; $filename = basename($match[2]); - // Skip debug functions. - if ($filename == 'debug.inc.php') { - return ""; - } - // Language is processed later. if ($filename == '$LANG.inc.php') { return $match[0]; @@ -74,10 +69,6 @@ function put_file($match) { } } - if ($driver && dirname($match[2]) == "../adminer/drivers") { - $content = preg_replace('~^if \(isset\(\$_GET\["' . $driver . '"]\)\) \{(.*)^}~ms', '\1', $content); - } - if ($filename == "lang.inc.php") { $content = str_replace( 'return $key; // compile: convert translation key', @@ -397,11 +388,15 @@ if ($argv[0] == "editor") { array_shift($argv); } -$driver = ""; -if ($argv && file_exists(dirname(__FILE__) . "/adminer/drivers/" . $argv[0] . ".inc.php")) { - $driver = $argv[0]; - array_shift($argv); +$selected_drivers = []; +if ($argv) { + $params = explode(",", $argv[0]); + if (file_exists(dirname(__FILE__) . "/adminer/drivers/" . $params[0] . ".inc.php")) { + $selected_drivers = $params; + array_shift($argv); + } } +$single_driver = count($selected_drivers) == 1 ? $selected_drivers[0] : null; $selected_languages = []; if ($argv) { @@ -419,20 +414,24 @@ if ($argv) { exit(1); } -// check function definition in drivers +// Check function definition in drivers. $file = file_get_contents(dirname(__FILE__) . "/adminer/drivers/mysql.inc.php"); $file = preg_replace('~class Min_Driver.*\n\t}~sU', '', $file); preg_match_all('~\bfunction ([^(]+)~', $file, $matches); //! respect context (extension, class) $functions = array_combine($matches[1], $matches[0]); //! do not warn about functions without declared support() unset($functions["__construct"], $functions["__destruct"], $functions["set_charset"]); -foreach (glob(dirname(__FILE__) . "/adminer/drivers/" . ($driver ?: "*") . ".inc.php") as $filename) { - if ($filename != "mysql.inc.php") { - $file = file_get_contents($filename); - foreach ($functions as $val) { - if (!strpos($file, "$val(")) { - fprintf(STDERR, "Missing $val in $filename\n"); - } + +foreach (glob(dirname(__FILE__) . "/adminer/drivers/*.inc.php") as $filename) { + preg_match('~/([^/.]+)\.inc\.php$~', $filename, $matches); + if ($matches[1] == "mysql" || ($selected_drivers && !in_array($matches[1], $selected_drivers))) { + continue; + } + + $file = file_get_contents($filename); + foreach ($functions as $function) { + if (!strpos($file, "$function(")) { + fprintf(STDERR, "Missing $function in $filename\n"); } } } @@ -443,13 +442,17 @@ include dirname(__FILE__) . "/adminer/include/driver.inc.php"; $features = ["call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "status", "trigger", "type", "user" => "privileges", "variables", "view"]; $lang_ids = []; // global variable simplifies usage in a callback functions +// Start with index.php. $file = file_get_contents(dirname(__FILE__) . "/$project/index.php"); -if ($driver) { - $_GET[$driver] = true; // to load the driver - include_once dirname(__FILE__) . "/adminer/drivers/$driver.inc.php"; + +// Remove including source code for unsupported features in single-driver file. +if ($single_driver) { + $_GET[$single_driver] = true; // to load the driver + include_once dirname(__FILE__) . "/adminer/drivers/$single_driver.inc.php"; + foreach ($features as $key => $feature) { if (!support($feature)) { - if (!is_int($key)) { + if (is_string($key)) { $feature = $key; } $file = str_replace("} elseif (isset(\$_GET[\"$feature\"])) {\n\tinclude \"./$feature.inc.php\";\n", "", $file); @@ -459,28 +462,39 @@ if ($driver) { $file = str_replace("if (isset(\$_GET[\"callf\"])) {\n\t\$_GET[\"call\"] = \$_GET[\"callf\"];\n}\nif (isset(\$_GET[\"function\"])) {\n\t\$_GET[\"procedure\"] = \$_GET[\"function\"];\n}\n", "", $file); } } -$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); -$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file); -if ($driver) { - $file = preg_replace('(include "../adminer/drivers/(?!' . preg_quote($driver) . '\.).*\s*)', '', $file); -} -$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); // bootstrap.inc.php -if ($driver) { +// Compile files included into the index.php. +$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); + +// Remove including debug files. +$file = str_replace('include "../adminer/include/debug.inc.php";', '', $file); +$file = str_replace('include "../adminer/include/coverage.inc.php";', '', $file); + +// Remove including unwanted drivers. +if ($selected_drivers) { + $file = preg_replace_callback('~include "../adminer/drivers/([^.]+).*\n~', function ($match) use ($selected_drivers) { + return in_array($match[1], $selected_drivers) ? $match[0] : ""; + }, $file); +} + +// Compile files included into the bootstrap.inc.php. +$file = preg_replace_callback('~\b(include|require) "([^"]*)";~', 'put_file', $file); + +if ($single_driver) { + // Remove source code for unsupported features. foreach ($features as $feature) { if (!support($feature)) { $file = preg_replace("((\t*)" . preg_quote('if (support("' . $feature . '")') . ".*\n\\1\\})sU", '', $file); } } - if (count($drivers) == 1) { - $file = str_replace('', "" . reset($drivers), $file); - } - $file = preg_replace('(;\.\./vendor/vrana/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($driver == "mysql" ? "sql" : $driver) . '\.)[^.]+.js)', '', $file); - $file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($driver) { + + $file = preg_replace('(;\.\./vendor/vrana/jush/modules/jush-(?!textarea\.|txt\.|js\.|' . preg_quote($single_driver == "mysql" ? "sql" : $single_driver) . '\.)[^.]+.js)', '', $file); + $file = preg_replace_callback('~doc_link\(array\((.*)\)\)~sU', function ($match) use ($single_driver) { list(, $links) = $match; - $links = preg_replace("~'(?!(" . ($driver == "mysql" ? "sql|mariadb" : $driver) . ")')[^']*' => [^,]*,?~", '', $links); + $links = preg_replace("~'(?!(" . ($single_driver == "mysql" ? "sql|mariadb" : $single_driver) . ")')[^']*' => [^,]*,?~", '', $links); return (trim($links) ? "doc_link(array($links))" : "''"); }, $file); + //! strip doc_link() definition } @@ -491,6 +505,7 @@ if ($project == "editor") { $file = preg_replace_callback("~lang\\('((?:[^\\\\']+|\\\\.)*)'([,)])~s", 'replace_lang', $file); $file = preg_replace_callback('~\b(include|require) "([^"]*\$LANG.inc.php)";~', 'put_file_lang', $file); + $file = str_replace("\r", "", $file); $file = str_replace('' . "\n", "", $file); $file = preg_replace('~\s+echo script_src\("\.\./vendor/vrana/jush/modules/jush-(textarea|txt|js|\$jush)\.js"\);~', '', $file); @@ -508,7 +523,7 @@ $file = php_shrink($file); @mkdir("temp", 0777, true); $filename = "temp/$project" . (is_dev_version() ? "" : "-$VERSION") - . ($driver ? "-$driver" : "") + . ($single_driver ? "-$single_driver" : "") . ($single_language ? "-$single_language" : "") . ".php"; diff --git a/editor/include/adminer.inc.php b/editor/include/adminer.inc.php index 00efa002..013d969e 100644 --- a/editor/include/adminer.inc.php +++ b/editor/include/adminer.inc.php @@ -77,7 +77,7 @@ class Adminer { function loginForm() { echo "
' . lang('Username') . ' | ', '' . script("focus(gid('username'));")); + echo $this->loginFormField('username', ' |
---|---|
' . lang('Username') . ' | ', '' . script("focus(gid('username'));")); echo $this->loginFormField('password', ' |
' . lang('Password') . ' | ', '' . "\n"); echo " |
\n"; diff --git a/editor/sqlite.php b/editor/sqlite.php index 71d747d5..29010863 100644 --- a/editor/sqlite.php +++ b/editor/sqlite.php @@ -2,16 +2,16 @@ function adminer_object() { include_once "../plugins/plugin.php"; include_once "../plugins/login-password-less.php"; - + class AdminerCustomization extends AdminerPlugin { function loginFormField($name, $heading, $value) { - return parent::loginFormField($name, $heading, str_replace('value="server"', 'value="sqlite"', $value)); + return parent::loginFormField($name, $heading, str_replace('value="mysql"', 'value="sqlite"', $value)); } function database() { return "PATH_TO_YOUR_SQLITE_HERE"; } } - + return new AdminerCustomization(array( // TODO: inline the result of password_hash() so that the password is not visible in source codes new AdminerLoginPasswordLess(password_hash("YOUR_PASSWORD_HERE", PASSWORD_DEFAULT)), diff --git a/plugins/dump-alter.php b/plugins/dump-alter.php index 8bfa466d..1322a405 100644 --- a/plugins/dump-alter.php +++ b/plugins/dump-alter.php @@ -7,13 +7,13 @@ * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) */ class AdminerDumpAlter { - + function dumpFormat() { - if (DRIVER == 'server') { + if (DRIVER == 'server' || DRIVER == 'mysql') { return array('sql_alter' => 'Alter'); } } - + function _database() { // drop old tables $query = "SELECT TABLE_NAME, ENGINE, TABLE_COLLATION, TABLE_COMMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = DATABASE()"; @@ -52,7 +52,7 @@ DROP PROCEDURE adminer_alter; SELECT @adminer_alter; "; } - + function dumpDatabase($db) { static $first = true; if ($_POST["format"] == "sql_alter") { @@ -66,7 +66,7 @@ SELECT @adminer_alter; return true; } } - + function dumpTable($table, $style, $is_view = 0) { if ($_POST["format"] == "sql_alter") { $create = create_sql($table, $_POST["auto_increment"], $style); @@ -146,7 +146,7 @@ DROP PROCEDURE adminer_alter; return true; } } - + function dumpData() { if ($_POST["format"] == "sql_alter") { return true; diff --git a/plugins/foreign-system.php b/plugins/foreign-system.php index 54c021c5..39cacb1c 100644 --- a/plugins/foreign-system.php +++ b/plugins/foreign-system.php @@ -7,9 +7,9 @@ * @license https://www.gnu.org/licenses/gpl-2.0.html GNU General Public License, version 2 (one or other) */ class AdminerForeignSystem { - + function foreignKeys($table) { - if (DRIVER == "server" && DB == "mysql") { + if ((DRIVER == "server" || DRIVER == "mysql") && DB == "mysql") { switch ($table) { case "columns_priv": return array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))); case "db": return array(array("table" => "user", "source" => array("Host", "User"), "target" => array("Host", "User"))); @@ -52,5 +52,5 @@ class AdminerForeignSystem { } } } - + } diff --git a/plugins/login-servers.php b/plugins/login-servers.php index d4a789f0..c91377e7 100644 --- a/plugins/login-servers.php +++ b/plugins/login-servers.php @@ -9,9 +9,9 @@ class AdminerLoginServers { /** @access protected */ var $servers; - + /** Set supported servers - * @param array array($description => array("server" => , "driver" => "server|pgsql|sqlite|...")) + * @param array array($description => array("server" => , "driver" => "mysql|pgsql|sqlite|...")) */ function __construct($servers) { $this->servers = $servers; @@ -20,17 +20,17 @@ class AdminerLoginServers { $_POST["auth"]["driver"] = $this->servers[$key]["driver"]; } } - + function credentials() { return array($this->servers[SERVER]["server"], $_GET["username"], get_password()); } - + function login($login, $password) { if (!$this->servers[SERVER]) { return false; } } - + function loginFormField($name, $heading, $value) { if ($name == 'driver') { return ''; @@ -38,5 +38,5 @@ class AdminerLoginServers { return $heading . "\n"; } } - + }