1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-30 17:50:00 +02:00

Refactor drivers definition and compilation

- Rename 'server' driver to 'mysql'
- MySQL driver is no longer the required default
- Fix compiled SQLite single-driver Adminer
- Allow to compile only selected drivers
This commit is contained in:
Peter Knut
2024-11-06 22:22:36 +01:00
parent 214d7745a7
commit ee26735ac6
10 changed files with 164 additions and 111 deletions

View File

@@ -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",

View File

@@ -1,8 +1,8 @@
<?php
$drivers = array("server" => "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 {

View File

@@ -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 . '&' : '')

View File

@@ -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]" : "")

View File

@@ -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('<?php echo html_select("auth[driver]", $drivers, DRIVER) . "\n"; ?>', "<input type='hidden' name='auth[driver]' value='" . ($driver == "mysql" ? "server" : $driver) . "'>" . 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('<?php echo script_src("static/editing.js?" . filemtime("../adminer/static/editing.js")); ?>' . "\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";

View File

@@ -77,7 +77,7 @@ class Adminer {
function loginForm() {
echo "<table cellspacing='0' class='layout'>\n";
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input type="hidden" name="auth[driver]" value="server"><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(gid('username'));"));
echo $this->loginFormField('username', '<tr><th>' . lang('Username') . '<td>', '<input type="hidden" name="auth[driver]" value="mysql"><input name="auth[username]" id="username" value="' . h($_GET["username"]) . '" autocomplete="username" autocapitalize="off">' . script("focus(gid('username'));"));
echo $this->loginFormField('password', '<tr><th>' . lang('Password') . '<td>', '<input type="password" name="auth[password]" autocomplete="current-password">' . "\n");
echo "</table>\n";
echo "<p><input type='submit' value='" . lang('Login') . "'>\n";

View File

@@ -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)),

View File

@@ -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;

View File

@@ -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 {
}
}
}
}

View File

@@ -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 . "<select name='auth[server]'>" . optionlist(array_keys($this->servers), SERVER) . "</select>\n";
}
}
}