From a93e4cb6942af1004e6e6d4fb6505c32fb731a1e Mon Sep 17 00:00:00 2001 From: Jakub Vrana Date: Sun, 30 Mar 2025 08:18:25 +0200 Subject: [PATCH] Return Db from connection() It's not a real type declaration because compile.php passes stdClass here. --- adminer/call.inc.php | 2 +- adminer/drivers/mysql.inc.php | 8 +++----- adminer/include/auth.inc.php | 15 +++++++++------ adminer/include/db.inc.php | 2 +- adminer/include/editing.inc.php | 1 - adminer/include/functions.inc.php | 27 ++++++++++++--------------- adminer/sql.inc.php | 4 ++-- compile.php | 2 +- 8 files changed, 29 insertions(+), 32 deletions(-) diff --git a/adminer/call.inc.php b/adminer/call.inc.php index b9ffbaa5..aae0012a 100644 --- a/adminer/call.inc.php +++ b/adminer/call.inc.php @@ -42,7 +42,7 @@ if (!$error && $_POST) { echo "

" . error() . "\n"; } else { $connection2 = connect(adminer()->credentials()); - if (is_object($connection2)) { + if ($connection2) { $connection2->select_db(DB); } diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 9203a0ae..260d8ea3 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -8,7 +8,7 @@ if (!defined('Adminer\DRIVER')) { // MySQLi supports everything, MySQL doesn't support multiple result sets, PDO_MySQL doesn't support orgtable if (extension_loaded("mysqli") && $_GET["ext"] != "pdo") { class Db extends \MySQLi { - /** @var Db|string */ static $instance = ''; + /** @var Db */ static $instance; public string $extension = "MySQLi", $flavor = ''; function __construct() { @@ -533,10 +533,9 @@ if (!defined('Adminer\DRIVER')) { } /** Get table indexes - * @param Db|string $connection2 * @return Index[] */ - function indexes(string $table, $connection2 = null): array { + function indexes(string $table, Db $connection2 = null): array { $return = array(); foreach (get_rows("SHOW INDEX FROM " . table($table), $connection2) as $row) { $name = $row["Key_name"]; @@ -1065,9 +1064,8 @@ if (!defined('Adminer\DRIVER')) { } /** Set current schema - * @param Db|string $connection2 */ - function set_schema(string $schema, $connection2 = null): bool { + function set_schema(string $schema, Db $connection2 = null): bool { return true; } } diff --git a/adminer/include/auth.inc.php b/adminer/include/auth.inc.php index d9a75a15..9a5f5cdd 100644 --- a/adminer/include/auth.inc.php +++ b/adminer/include/auth.inc.php @@ -167,24 +167,27 @@ if (isset($_GET["username"]) && !class_exists('Adminer\Db')) { exit; } +$connection = ''; if (isset($_GET["username"]) && is_string(get_password())) { list($host, $port) = explode(":", SERVER, 2); if (preg_match('~^\s*([-+]?\d+)~', $port, $match) && ($match[1] < 1024 || $match[1] > 65535)) { // is_numeric('80#') would still connect to port 80 auth_error(lang('Connecting to privileged ports is not allowed.'), $permanent); } check_invalid_login($permanent); - Db::$instance = connect(adminer()->credentials()); - if (is_object(Db::$instance)) { - Driver::$instance = new Driver(Db::$instance); - if (Db::$instance->flavor) { + $credentials = adminer()->credentials(); + $connection = Driver::connect($credentials[0], $credentials[1], $credentials[2]); + if (is_object($connection)) { + Db::$instance = $connection; + Driver::$instance = new Driver($connection); + if ($connection->flavor) { save_settings(array("vendor-" . DRIVER . "-" . SERVER => get_driver(DRIVER))); } } } $login = null; -if (!is_object(connection()) || ($login = adminer()->login($_GET["username"], get_password())) !== true) { - $error = (is_string(connection()) ? nl_br(h(connection())) : (is_string($login) ? $login : lang('Invalid credentials.'))); +if (!is_object($connection) || ($login = adminer()->login($_GET["username"], get_password())) !== true) { + $error = (is_string($connection) ? nl_br(h($connection)) : (is_string($login) ? $login : lang('Invalid credentials.'))); auth_error( $error . (preg_match('~^ | $~', get_password()) ? '
' . lang('There is a space in the input password which might be the cause.') : ''), $permanent diff --git a/adminer/include/db.inc.php b/adminer/include/db.inc.php index 2477231f..2260a2f5 100644 --- a/adminer/include/db.inc.php +++ b/adminer/include/db.inc.php @@ -4,7 +4,7 @@ namespace Adminer; // this could be interface when "Db extends \mysqli" can have compatible type declarations (PHP 7) // interfaces can include properties only since PHP 8.4 abstract class SqlDb { - /** @var Db|string */ static $instance = ''; // string means error + /** @var Db */ static $instance; public string $extension; // extension name public string $flavor = ''; // different vendor with the same API, e.g. MariaDB; usually stays empty diff --git a/adminer/include/editing.inc.php b/adminer/include/editing.inc.php index 68c4116e..026e5561 100644 --- a/adminer/include/editing.inc.php +++ b/adminer/include/editing.inc.php @@ -5,7 +5,6 @@ namespace Adminer; /** Print select result * @param Result $result -* @param Db|string $connection2 * @param string[] $orgtables * @param int|numeric-string $limit * @return string[] $orgtables diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 29ac368a..cd033ccd 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -4,12 +4,12 @@ namespace Adminer; // This file is used both in Adminer and Adminer Editor. /** Get database connection -* @param Db|string $connection2 custom connection to use instead of the default -* @return Db|string string means error +* @param ?Db $connection2 custom connection to use instead of the default +* @return Db */ -function connection($connection2 = null) { +function connection(Db $connection2 = null) { // can be used in customization, Db::$instance is minified - return (is_object($connection2) ? $connection2 : Db::$instance); + return ($connection2 ?: Db::$instance); } /** Get Adminer object @@ -26,10 +26,10 @@ function driver(): Driver { /** Connect to the database * @param array{?string, string, string} $credentials [$server, $username, $password] -* @return Db|string string for error */ -function connect(array $credentials) { - return driver()->connect($credentials[0], $credentials[1], $credentials[2]); +function connect(array $credentials): ?Db { + $return = driver()->connect($credentials[0], $credentials[1], $credentials[2]); + return (is_object($return) ? $return : null); } /** Unescape database identifier @@ -105,9 +105,8 @@ function bracket_escape(string $idf, bool $back = false): string { /** Check if connection has at least the given version * @param string|float $version required version * @param string|float $maria_db required MariaDB version -* @param Db|string $connection2 defaults to connection() */ -function min_version($version, $maria_db = "", $connection2 = null): bool { +function min_version($version, $maria_db = "", Db $connection2 = null): bool { $connection2 = connection($connection2); $server_info = $connection2->server_info; if ($maria_db && preg_match('~([\d.]+)-MariaDB~', $server_info, $match)) { @@ -188,10 +187,9 @@ function get_vals(string $query, $column = 0): array { } /** Get keys from first column and values from second -* @param Db|string $connection2 * @return string[] */ -function get_key_vals(string $query, $connection2 = null, bool $set_keys = true): array { +function get_key_vals(string $query, Db $connection2 = null, bool $set_keys = true): array { $connection2 = connection($connection2); $return = array(); $result = $connection2->query($query); @@ -208,10 +206,9 @@ function get_key_vals(string $query, $connection2 = null, bool $set_keys = true) } /** Get all rows of result -* @param Db|string $connection2 * @return list of associative arrays */ -function get_rows(string $query, $connection2 = null, string $error = "

"): array { +function get_rows(string $query, Db $connection2 = null, string $error = "

"): array { $conn = connection($connection2); $return = array(); $result = $conn->query($query); @@ -219,7 +216,7 @@ function get_rows(string $query, $connection2 = null, string $error = "

fetch_assoc()) { $return[] = $row; } - } elseif (!$result && $connection2 === null && $error && (defined('Adminer\PAGE_HEADER') || $error == "-- ")) { + } elseif (!$result && !$connection2 && $error && (defined('Adminer\PAGE_HEADER') || $error == "-- ")) { echo $error . error() . "\n"; } return $return; @@ -833,7 +830,7 @@ function slow_query(string $query): array { $connection2 = null; if (!$slow_query && support("kill")) { $connection2 = connect(adminer()->credentials()); - if (is_object($connection2) && ($db == "" || $connection2->select_db($db))) { + if ($connection2 && ($db == "" || $connection2->select_db($db))) { $kill = get_val(connection_id(), 0, $connection2); // MySQL and MySQLi can use thread_id but it's not in PDO_MySQL echo script("const timeout = setTimeout(() => { ajax('" . js_escape(ME) . "script=kill', function () {}, 'kill=$kill&token=" . get_token() . "'); }, 1000 * $timeout);"); } diff --git a/adminer/sql.inc.php b/adminer/sql.inc.php index 4860c5fb..ebb354e5 100644 --- a/adminer/sql.inc.php +++ b/adminer/sql.inc.php @@ -55,7 +55,7 @@ if (!$error && $_POST) { $offset = 0; $empty = true; $connection2 = connect(adminer()->credentials()); // connection for exploring indexes and EXPLAIN (to not replace FOUND_ROWS()) //! PDO - silent error - if (is_object($connection2) && DB != "") { + if ($connection2 && DB != "") { $connection2->select_db(DB); if ($_GET["ns"] != "") { set_schema($_GET["ns"], $connection2); @@ -126,7 +126,7 @@ if (!$error && $_POST) { } $start = microtime(true); //! don't allow changing of character_set_results, convert encoding of displayed query - if (connection()->multi_query($q) && is_object($connection2) && preg_match("~^$space*+USE\\b~i", $q)) { + if (connection()->multi_query($q) && $connection2 && preg_match("~^$space*+USE\\b~i", $q)) { $connection2->query($q); } diff --git a/compile.php b/compile.php index e248013e..60d0056d 100755 --- a/compile.php +++ b/compile.php @@ -278,7 +278,6 @@ if ($_SERVER["argv"][1]) { include __DIR__ . "/adminer/include/db.inc.php"; include __DIR__ . "/adminer/include/pdo.inc.php"; include __DIR__ . "/adminer/include/driver.inc.php"; -Adminer\SqlDb::$instance = (object) array('flavor' => '', 'server_info' => '99'); // used in support() $features = array("check", "call" => "routine", "dump", "event", "privileges", "procedure" => "routine", "processlist", "routine", "scheme", "sequence", "sql", "status", "trigger", "type", "user" => "privileges", "variables", "view"); $lang_ids = array(); // global variable simplifies usage in a callback function $file = file_get_contents(__DIR__ . "/$project/index.php"); @@ -286,6 +285,7 @@ $file = preg_replace('~\*/~', "* @version " . Adminer\VERSION . "\n*/", $file, 1 if ($vendor) { $_GET[$vendor] = true; // to load the driver include_once __DIR__ . $driver_path; + Adminer\Db::$instance = (object) array('flavor' => '', 'server_info' => '99'); // used in support() foreach ($features as $key => $feature) { if (!Adminer\support($feature)) { if (!is_int($key)) {