diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index af6952c611..56fa0ce1b5 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -7460,11 +7460,6 @@ parameters: count: 1 path: src/Dbal/DbalInterface.php - - - message: "#^Parameter \\#1 \\$haystack of function stripos expects string, string\\|null given\\.$#" - count: 1 - path: src/Dbal/DbiMysqli.php - - message: "#^Method PhpMyAdmin\\\\Dbal\\\\MysqliResult\\:\\:fetchAllAssoc\\(\\) should return array\\\\> but returns array\\.$#" count: 1 diff --git a/psalm-baseline.xml b/psalm-baseline.xml index cbad0b6158..1cfbe60709 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -5273,12 +5273,6 @@ Config::getInstance() - - $errorMessage - - - $errorMessage - diff --git a/src/DatabaseInterface.php b/src/DatabaseInterface.php index 080962264b..9aa7379218 100644 --- a/src/DatabaseInterface.php +++ b/src/DatabaseInterface.php @@ -7,6 +7,7 @@ namespace PhpMyAdmin; use PhpMyAdmin\Config\Settings\Server; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Dbal\Connection; +use PhpMyAdmin\Dbal\ConnectionException; use PhpMyAdmin\Dbal\DbalInterface; use PhpMyAdmin\Dbal\DbiExtension; use PhpMyAdmin\Dbal\DbiMysqli; @@ -1636,7 +1637,14 @@ class DatabaseInterface implements DbalInterface // Do not show location and backtrace for connection errors $errorHandler = ErrorHandler::getInstance(); $errorHandler->setHideLocation(true); - $result = $this->extension->connect($server); + try { + $result = $this->extension->connect($server); + } catch (ConnectionException $exception) { + trigger_error($exception->getMessage(), E_USER_WARNING); + + return null; + } + $errorHandler->setHideLocation(false); if ($result !== null) { diff --git a/src/Dbal/ConnectionException.php b/src/Dbal/ConnectionException.php new file mode 100644 index 0000000000..66f65e819f --- /dev/null +++ b/src/Dbal/ConnectionException.php @@ -0,0 +1,11 @@ +socket, $clientFlags, ); - } catch (mysqli_sql_exception) { - /** - * Switch to SSL if server asked us to do so, unfortunately - * there are more ways MySQL server can tell this: - * - * - MySQL 8.0 and newer should return error 3159 - * - #2001 - SSL Connection is required. Please specify SSL options and retry. - * - #9002 - SSL connection is required. Please specify SSL options and retry. - */ - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $errorNumber = $mysqli->connect_errno; - // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps - $errorMessage = $mysqli->connect_error; - if ( - ! $server->ssl - && ($errorNumber == 3159 - || (($errorNumber == 2001 || $errorNumber == 9002) - && stripos($errorMessage, 'SSL Connection is required') !== false)) - ) { - trigger_error( - __('SSL connection enforced by server, automatically enabling it.'), - E_USER_WARNING, - ); + } catch (mysqli_sql_exception $exception) { + $errorNumber = $exception->getCode(); + $errorMessage = $exception->getMessage(); + if (! $server->ssl && $this->isSslRequiredByServer($errorNumber, $errorMessage)) { return self::connect($server->withSSL(true)); } + mysqli_report(MYSQLI_REPORT_OFF); + if ($errorNumber === 1045 && $server->hideConnectionErrors) { - trigger_error( + throw new ConnectionException( sprintf( __( 'Error 1045: Access denied for user. Additional error information' @@ -143,15 +124,12 @@ class DbiMysqli implements DbiExtension '[code][doc@cfg_Servers_hide_connection_errors]' . '$cfg[\'Servers\'][$i][\'hide_connection_errors\'][/doc][/code]', ), - E_USER_ERROR, + $errorNumber, + $exception, ); - } else { - trigger_error($errorNumber . ': ' . $errorMessage, E_USER_WARNING); } - mysqli_report(MYSQLI_REPORT_OFF); - - return null; + throw new ConnectionException($errorNumber . ': ' . $errorMessage, $errorNumber, $exception); } $mysqli->options(MYSQLI_OPT_LOCAL_INFILE, (int) defined('PMA_ENABLE_LDI')); @@ -356,4 +334,19 @@ class DbiMysqli implements DbiExtension // phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps return $mysqli->warning_count; } + + /** + * Switch to SSL if server asked us to do so, unfortunately + * there are more ways MySQL server can tell this: + * + * - MySQL 8.0 and newer should return error 3159 + * - #2001 - SSL Connection is required. Please specify SSL options and retry. + * - #9002 - SSL connection is required. Please specify SSL options and retry. + */ + private function isSslRequiredByServer(int $errorNumber, string $errorMessage): bool + { + return $errorNumber === 3159 + || ($errorNumber === 2001 || $errorNumber === 9002) + && str_contains(strtolower($errorMessage), 'ssl connection is required'); + } }