diff --git a/adminer/drivers/mssql.inc.php b/adminer/drivers/mssql.inc.php index 298528713..fc991e07c 100644 --- a/adminer/drivers/mssql.inc.php +++ b/adminer/drivers/mssql.inc.php @@ -51,7 +51,7 @@ function attach(string $server, string $username, string $password): string { } function quote(string $string): string { - $unicode = strlen($string) != strlen(utf8_decode($string)); + $unicode = preg_match('~[\x80-\xFF]~', $string); return ($unicode ? "N" : "") . "'" . str_replace("'", "''", $string) . "'"; } diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 53e0fdb52..797ede919 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -17,7 +17,7 @@ function __construct() { } function attach(string $server, string $username, string $password): string { - mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4 + mysqli_report(MYSQLI_REPORT_OFF); list($host, $port) = host_port($server); $ssl = adminer()->connectSsl(); if ($ssl) { @@ -36,7 +36,7 @@ function attach(string $server, string $username, string $password): string { return ($return ? '' : $this->error); } - function set_charset($charset) { + function set_charset($charset): bool { if (parent::set_charset($charset)) { return true; } @@ -45,8 +45,8 @@ function set_charset($charset) { return $this->query("SET NAMES $charset"); } - function next_result() { - return self::more_results() && parent::next_result(); // triggers E_STRICT on PHP < 7.4 otherwise + function next_result(): bool { + return self::more_results() && parent::next_result(); } function quote(string $string): string { @@ -54,106 +54,6 @@ function quote(string $string): string { } } - } elseif (extension_loaded("mysql") && !((ini_bool("sql.safe_mode") || ini_bool("mysql.allow_local_infile")) && extension_loaded("pdo_mysql"))) { - class Db extends SqlDb { - /** @var resource */ private $link; - - function attach(string $server, string $username, string $password): string { - if (ini_bool("mysql.allow_local_infile")) { - return lang('Disable %s or enable %s or %s extensions.', "'mysql.allow_local_infile'", "MySQLi", "PDO_MySQL"); - } - $this->link = @mysql_connect( - ($server != "" ? $server : ini_get("mysql.default_host")), - ($server . $username != "" ? $username : ini_get("mysql.default_user")), - ($server . $username . $password != "" ? $password : ini_get("mysql.default_password")), - true, - 131072 // CLIENT_MULTI_RESULTS for CALL - ); - if (!$this->link) { - return mysql_error(); - } - $this->server_info = mysql_get_server_info($this->link); - return ''; - } - - /** Set the client character set */ - function set_charset(string $charset): bool { - if (function_exists('mysql_set_charset')) { - if (mysql_set_charset($charset, $this->link)) { - return true; - } - // the client library may not support utf8mb4 - mysql_set_charset('utf8', $this->link); - } - return $this->query("SET NAMES $charset"); - } - - function quote(string $string): string { - return "'" . mysql_real_escape_string($string, $this->link) . "'"; - } - - function select_db(string $database) { - return mysql_select_db($database, $this->link); - } - - function query(string $query, bool $unbuffered = false) { - $result = @($unbuffered ? mysql_unbuffered_query($query, $this->link) : mysql_query($query, $this->link)); // @ - mute mysql.trace_mode - $this->error = ""; - if (!$result) { - $this->errno = mysql_errno($this->link); - $this->error = mysql_error($this->link); - return false; - } - if ($result === true) { - $this->affected_rows = mysql_affected_rows($this->link); - $this->info = mysql_info($this->link); - return true; - } - return new Result($result); - } - } - - class Result { - public $num_rows; // number of rows in the result - /** @var resource */ private $result; - private int $offset = 0; - - /** @param resource $result */ - function __construct($result) { - $this->result = $result; - $this->num_rows = mysql_num_rows($result); - } - - /** Fetch next row as associative array - * @return array|false - */ - function fetch_assoc() { - return mysql_fetch_assoc($this->result); - } - - /** Fetch next row as numbered array - * @return list|false - */ - function fetch_row() { - return mysql_fetch_row($this->result); - } - - /** Fetch next field - * @return \stdClass properties: name, type (0 number, 15 varchar, 254 char), charsetnr (63 binary); optionally: table, orgtable, orgname - */ - function fetch_field(): \stdClass { - $return = mysql_fetch_field($this->result, $this->offset++); // offset required under certain conditions - $return->orgtable = $return->table; - $return->charsetnr = ($return->blob ? 63 : 0); - return $return; - } - - /** Free result set */ - function __destruct() { - mysql_free_result($this->result); - } - } - } elseif (extension_loaded("pdo_mysql")) { class Db extends PdoDb { public $extension = "PDO_MySQL"; diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index e5fcaeec8..68b71a4f5 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -88,12 +88,8 @@ function query(string $query, bool $unbuffered = false) { } function warnings() { - if (PHP_VERSION_ID >= 70100) { - $return = implode("\n", pg_last_notice($this->link, 2)); // 2 - PGSQL_NOTICE_ALL - pg_last_notice($this->link, 3); // 3 - PGSQL_NOTICE_CLEAR - } else { - $return = pg_last_notice($this->link); - } + $return = implode("\n", pg_last_notice($this->link, PGSQL_NOTICE_ALL)); + pg_last_notice($this->link, PGSQL_NOTICE_CLEAR); return nl_br(h($return)); } diff --git a/adminer/include/bootstrap.inc.php b/adminer/include/bootstrap.inc.php index c9a599906..c05632547 100644 --- a/adminer/include/bootstrap.inc.php +++ b/adminer/include/bootstrap.inc.php @@ -50,15 +50,7 @@ session_start(); } -// disable magic quotes to be able to use database escaping function -if (function_exists("get_magic_quotes_gpc") && get_magic_quotes_gpc()) { - $_GET = remove_slashes($_GET, $filter); - $_POST = remove_slashes($_POST, $filter); - $_COOKIE = remove_slashes($_COOKIE, $filter); -} -if (function_exists("get_magic_quotes_runtime") && get_magic_quotes_runtime()) { - set_magic_quotes_runtime(false); -} + @set_time_limit(0); // @ - can be disabled @ini_set("precision", '15'); // @ - can be disabled, 15 - internal PHP precision diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index 816921d24..864075e06 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -562,7 +562,7 @@ function upload_error(int $error): string { /** Create repeat pattern for preg */ function repeat_pattern(string $pattern, int $length): string { // fix for Compilation failed: number too big in {} quantifier - return str_repeat("$pattern{0,65535}", $length / 65535) . "$pattern{0," . ($length % 65535) . "}"; // can create {0,0} which is OK + return str_repeat($pattern . "{0,65535}", $length / 65535) . $pattern . "{0," . ($length % 65535) . "}"; // can create {0,0} which is OK } /** Check whether the string is in UTF-8 */ diff --git a/adminer/select.inc.php b/adminer/select.inc.php index 6255c4c09..a344b4403 100644 --- a/adminer/select.inc.php +++ b/adminer/select.inc.php @@ -371,7 +371,7 @@ if ($_GET["modify"]) { foreach ($rows as $row) { foreach ($row as $key => $val) { - $lengths[$key] = max($lengths[$key], min(40, strlen(utf8_decode($val)))); + $lengths[$key] = max($lengths[$key], min(40, (int) mb_strlen((string) $val))); } } } diff --git a/composer.json b/composer.json index 7c70f84fc..92815d86c 100644 --- a/composer.json +++ b/composer.json @@ -30,7 +30,7 @@ "GPL-2.0-only" ], "require": { - "php": ">=7.4" + "php": ">=8.0" }, "scripts": { "check": [ diff --git a/phpstan.neon b/phpstan.neon index 1b2253aea..4e3ecc440 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -9,8 +9,6 @@ parameters: - "~Function Adminer\\\\queries\\(\\) never returns Adminer\\\\Result~" # mysqli_result # not real problems - - identifier: include.fileNotFound # includes in include/ relative from index.php - - "~^Function (set_magic_quotes_runtime|mysql_)~" # PHP < 7 functions - "~an unknown class OCI-?Lob~" # this looks like PHPStan bug - "~^Variable \\$error might not be defined~" # declared in bootstrap.inc.php - "~^Constant LANG not found~" # defined in lang.inc.php @@ -22,7 +20,6 @@ parameters: - "~expects bool~" # truthy values - "~fread expects int<1, max>, 100000~" # 1e6 - "~'strlen' given~" # used as a bool callback - - "~between int<70100~" # PHP_VERSION_ID check - message: "~ type specified~" # duplicate functions and methods @@ -32,21 +29,17 @@ parameters: # it probably doesn't like $ar[$key] instead of isset($ar[$key]) and thinks that $ar[$key] is always set - identifier: identical.alwaysFalse - - identifier: notEqual.alwaysFalse - - identifier: notIdentical.alwaysTrue - identifier: booleanNot.alwaysTrue - identifier: booleanNot.alwaysFalse - identifier: booleanAnd.alwaysFalse - identifier: booleanAnd.leftAlwaysTrue - identifier: booleanAnd.rightAlwaysTrue - - identifier: booleanAnd.rightAlwaysFalse - identifier: booleanOr.rightAlwaysTrue - identifier: ternary.alwaysTrue - identifier: if.alwaysTrue - identifier: isset.offset - identifier: deadCode.unreachable - "~Function Adminer\\\\get_driver\\(\\) never returns null~" - - "~on array\\{}~" paths: - adminer/drivers/mysql.inc.php # other drivers inherit the annotations so we take them from here @@ -59,9 +52,7 @@ parameters: - adminer/elastic.php - adminer/sqlite.php - phpVersion: - min: 70100 - max: 80499 + phpVersion: 80100 typeAliases: TableStatus: "array{Name:string, Engine?:?string, Comment?:string, Oid?:numeric-string, Rows?:?numeric-string, Collation?:string, Auto_increment?:?numeric-string, Data_length?:numeric-string, Index_length?:numeric-string, Data_free?:numeric-string, Create_options?:string, partition?:numeric-string, nspname?:string}"