diff --git a/src/DatabaseDriver.php b/src/DatabaseDriver.php index 849dd12b..87e77e38 100644 --- a/src/DatabaseDriver.php +++ b/src/DatabaseDriver.php @@ -1893,4 +1893,63 @@ public function updateObject($table, &$object, $key, $nulls = false) return true; } + + /** + * Extract pure host name (or IP address) and port or socket from host name option. + * + * @param integer $defaultPort The default port number to be used if no port is given. + * + * @since __DEPLOY_VERSION__ + */ + protected function setHostPortSocket($defaultPort) + { + $port = $this->options['port'] ?? $defaultPort; + + if (preg_match('/^unix:(?P[^:]+)$/', $this->options['host'], $matches)) { + // UNIX socket URI, e.g. 'unix:/path/to/unix/socket.sock' + $this->options['host'] = null; + $this->options['socket'] = $matches['socket']; + $this->options['port'] = null; + } elseif ( + preg_match( + '/^(?P((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:(?P.+))?$/', + $this->options['host'], + $matches + ) + ) { + // It's an IPv4 address with or without port + $this->options['host'] = $matches['host']; + + if (!empty($matches['port'])) { + $port = $matches['port']; + } + } elseif (preg_match('/^(?P\[.*\])(:(?P.+))?$/', $this->options['host'], $matches)) { + // We assume square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306 + $this->options['host'] = $matches['host']; + + if (!empty($matches['port'])) { + $port = $matches['port']; + } + } elseif (preg_match('/^(?P(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P[^:]+))?$/i', $this->options['host'], $matches)) { + // Named host (e.g example.com or localhost) with or without port + $this->options['host'] = $matches['host']; + + if (!empty($matches['port'])) { + $port = $matches['port']; + } + } elseif (preg_match('/^:(?P[^:]+)$/', $this->options['host'], $matches)) { + // Empty host, just port, e.g. ':3306' + $this->options['host'] = 'localhost'; + $port = $matches['port']; + } + + // ... else we assume normal (naked) IPv6 address, so host and port stay as they are or default + + // Get the port number or socket name + if (is_numeric($port)) { + $this->options['port'] = (int) $port; + } else { + $this->options['socket'] = $port; + } + } } diff --git a/src/Mysqli/MysqliDriver.php b/src/Mysqli/MysqliDriver.php index 7050f7b0..dbc6977c 100644 --- a/src/Mysqli/MysqliDriver.php +++ b/src/Mysqli/MysqliDriver.php @@ -198,58 +198,8 @@ public function connect() throw new UnsupportedAdapterException('The MySQLi extension is not available'); } - /* - * Unlike mysql_connect(), mysqli_connect() takes the port and socket as separate arguments. Therefore, we - * have to extract them from the host string. - */ - $port = isset($this->options['port']) ? $this->options['port'] : 3306; - - if (preg_match('/^unix:(?P[^:]+)$/', $this->options['host'], $matches)) { - // UNIX socket URI, e.g. 'unix:/path/to/unix/socket.sock' - $this->options['host'] = null; - $this->options['socket'] = $matches['socket']; - $this->options['port'] = null; - } elseif ( - preg_match( - '/^(?P((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(:(?P.+))?$/', - $this->options['host'], - $matches - ) - ) { - // It's an IPv4 address with or without port - $this->options['host'] = $matches['host']; - - if (!empty($matches['port'])) { - $port = $matches['port']; - } - } elseif (preg_match('/^(?P\[.*\])(:(?P.+))?$/', $this->options['host'], $matches)) { - // We assume square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306 - $this->options['host'] = $matches['host']; - - if (!empty($matches['port'])) { - $port = $matches['port']; - } - } elseif (preg_match('/^(?P(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P[^:]+))?$/i', $this->options['host'], $matches)) { - // Named host (e.g example.com or localhost) with or without port - $this->options['host'] = $matches['host']; - - if (!empty($matches['port'])) { - $port = $matches['port']; - } - } elseif (preg_match('/^:(?P[^:]+)$/', $this->options['host'], $matches)) { - // Empty host, just port, e.g. ':3306' - $this->options['host'] = 'localhost'; - $port = $matches['port']; - } - - // ... else we assume normal (naked) IPv6 address, so host and port stay as they are or default - - // Get the port number or socket name - if (is_numeric($port)) { - $this->options['port'] = (int) $port; - } else { - $this->options['socket'] = $port; - } + // Extract host and port or socket from host option + $this->setHostPortSocket(3306); $this->connection = mysqli_init(); diff --git a/src/Pdo/PdoDriver.php b/src/Pdo/PdoDriver.php index 9aee3754..6bdfe857 100644 --- a/src/Pdo/PdoDriver.php +++ b/src/Pdo/PdoDriver.php @@ -209,7 +209,8 @@ public function connect() break; case 'mysql': - $this->options['port'] = $this->options['port'] ?? 3306; + // Extract host and port or socket from host option + $this->setHostPortSocket(3306); if ($this->options['socket'] !== null) { $format = 'mysql:unix_socket=#SOCKET#;dbname=#DBNAME#;charset=#CHARSET#'; @@ -257,7 +258,8 @@ public function connect() break; case 'pgsql': - $this->options['port'] = $this->options['port'] ?? 5432; + // Extract host and port or socket from host option + $this->setHostPortSocket(5432); if ($this->options['socket'] !== null) { $format = 'pgsql:host=#SOCKET#;dbname=#DBNAME#';