diff --git a/CHANGELOG.md b/CHANGELOG.md index 637b9fac..1c0f608a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Autofocus added field in alter table - Executed SQL commands: Add button for copy to clipboard - Load more: run syntax highlighter +- Allow connecting to IPv6 (bug #1095) - MySQL: Fix saving empty enum (bug #1152) - MySQL 5.0-: Do not load partitioning info in alter table (bug #1099) - MariaDB: Parse COLLATE in routine definition (bug #1104) diff --git a/adminer/drivers/mssql.inc.php b/adminer/drivers/mssql.inc.php index 6bbe22a6..77bfc83c 100644 --- a/adminer/drivers/mssql.inc.php +++ b/adminer/drivers/mssql.inc.php @@ -39,7 +39,8 @@ if (isset($_GET["mssql"])) { if ($db != "") { $connection_info["Database"] = $db; } - $this->link = @sqlsrv_connect(preg_replace('~:~', ',', $server), $connection_info); + list($host, $port) = host_port($server); + $this->link = @sqlsrv_connect($host . ($port ? ",$port" : ""), $connection_info); if ($this->link) { $info = sqlsrv_server_info($this->link); $this->server_info = $info['SQLServerVersion']; @@ -182,7 +183,8 @@ if (isset($_GET["mssql"])) { public $extension = "PDO_SQLSRV"; function attach(?string $server, string $username, string $password): string { - return $this->dsn("sqlsrv:Server=" . str_replace(":", ",", $server), $username, $password); + list($host, $port) = host_port($server); + return $this->dsn("sqlsrv:Server=$host" . ($port ? ",$port" : ""), $username, $password); } } @@ -191,7 +193,8 @@ if (isset($_GET["mssql"])) { public $extension = "PDO_DBLIB"; function attach(?string $server, string $username, string $password): string { - return $this->dsn("dblib:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)), $username, $password); + list($host, $port) = host_port($server); + return $this->dsn("dblib:charset=utf8;host=$host" . ($port ? (is_numeric($port) ? ";port=" : ";unix_socket=") . $port : ""), $username, $password); } } } diff --git a/adminer/drivers/mysql.inc.php b/adminer/drivers/mysql.inc.php index 7afb1ab9..8ba4e68b 100644 --- a/adminer/drivers/mysql.inc.php +++ b/adminer/drivers/mysql.inc.php @@ -18,7 +18,7 @@ if (!defined('Adminer\DRIVER')) { function attach(?string $server, string $username, string $password): string { mysqli_report(MYSQLI_REPORT_OFF); // stays between requests, not required since PHP 5.3.4 - list($host, $port) = explode(":", $server, 2); // part after : is used for port or socket + list($host, $port) = host_port($server); $ssl = adminer()->connectSsl(); if ($ssl) { $this->ssl_set($ssl['key'], $ssl['cert'], $ssl['ca'], '', ''); @@ -175,8 +175,9 @@ if (!defined('Adminer\DRIVER')) { $options[\PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT] = $ssl['verify']; } } + list($host, $port) = host_port($server); return $this->dsn( - "mysql:charset=utf8;host=" . str_replace(":", ";unix_socket=", preg_replace('~:(\d)~', ';port=\1', $server)), + "mysql:charset=utf8;host=$host" . ($port ? (is_numeric($port) ? ";port=" : ";unix_socket=") . $port : ""), $username, $password, $options diff --git a/adminer/drivers/pgsql.inc.php b/adminer/drivers/pgsql.inc.php index da6e6db7..73827af3 100644 --- a/adminer/drivers/pgsql.inc.php +++ b/adminer/drivers/pgsql.inc.php @@ -23,7 +23,8 @@ if (isset($_GET["pgsql"])) { function attach(?string $server, string $username, string $password): string { $db = adminer()->database(); set_error_handler(array($this, '_error')); - $this->string = "host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'"; + list($host, $port) = host_port(addcslashes($server, "'\\")); + $this->string = "host='$host'" . ($port ? " port='$port'" : "") . " user='" . addcslashes($username, "'\\") . "' password='" . addcslashes($password, "'\\") . "'"; $ssl = adminer()->connectSsl(); if (isset($ssl["mode"])) { $this->string .= " sslmode='" . $ssl["mode"] . "'"; @@ -145,8 +146,9 @@ if (isset($_GET["pgsql"])) { function attach(?string $server, string $username, string $password): string { $db = adminer()->database(); + list($host, $port) = host_port(addcslashes($server, "'\\")); //! client_encoding is supported since 9.1, but we can't yet use min_version here - $dsn = "pgsql:host='" . str_replace(":", "' port='", addcslashes($server, "'\\")) . "' client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'"; + $dsn = "pgsql:host='$host'" . ($port ? " port='$port'" : "") . " client_encoding=utf8 dbname='" . ($db != "" ? addcslashes($db, "'\\") : "postgres") . "'"; $ssl = adminer()->connectSsl(); if (isset($ssl["mode"])) { $dsn .= " sslmode='" . $ssl["mode"] . "'"; diff --git a/adminer/include/auth.inc.php b/adminer/include/auth.inc.php index 69f875a7..f0476d98 100644 --- a/adminer/include/auth.inc.php +++ b/adminer/include/auth.inc.php @@ -172,7 +172,7 @@ if (isset($_GET["username"]) && !class_exists('Adminer\Db')) { $connection = ''; if (isset($_GET["username"]) && is_string(get_password())) { - list($host, $port) = explode(":", SERVER, 2); + list($host, $port) = host_port(SERVER); 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); } diff --git a/adminer/include/functions.inc.php b/adminer/include/functions.inc.php index ef61073e..e3425cde 100644 --- a/adminer/include/functions.inc.php +++ b/adminer/include/functions.inc.php @@ -819,6 +819,16 @@ function is_shortable(array $field): bool { return preg_match('~char|text|json|lob|geometry|point|linestring|polygon|string|bytea|hstore~', $field["type"]); } +/** Split server into host and (port or socket) +* @return array{0: string, 1: string} +*/ +function host_port(string $server) { + return (preg_match('~^(\[(.+)]|([^:]+)):([^:]+)$~', $server, $match) // [a:b] - IPv6 + ? array($match[2] . $match[3], $match[4]) + : array($server, '') + ); +} + /** Get query to compute number of found rows * @param list $where * @param list $group diff --git a/plugins/drivers/imap.php b/plugins/drivers/imap.php index 1686db61..3557cf52 100644 --- a/plugins/drivers/imap.php +++ b/plugins/drivers/imap.php @@ -25,7 +25,8 @@ if (isset($_GET["imap"])) { private $imap; function attach($server, $username, $password): string { - $this->mailbox = "{" . "$server:993/ssl}"; // Adminer disallows specifying privileged port in server name + list($host, $port) = host_port($server); + $this->mailbox = "{" . "$host:" . ($port ?: 993) . "/ssl}"; // Adminer disallows specifying privileged port in server name $this->imap = @imap_open($this->mailbox, $username, $password, OP_HALFOPEN, 1); return ($this->imap ? '' : imap_last_error()); }