Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 59 additions & 0 deletions src/DatabaseDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<socket>[^:]+)$/', $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<host>((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<port>.+))?$/',
$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<host>\[.*\])(:(?P<port>.+))?$/', $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<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/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<port>[^:]+)$/', $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;
}
}
}
54 changes: 2 additions & 52 deletions src/Mysqli/MysqliDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<socket>[^:]+)$/', $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<host>((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<port>.+))?$/',
$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<host>\[.*\])(:(?P<port>.+))?$/', $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<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/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<port>[^:]+)$/', $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();

Expand Down
6 changes: 4 additions & 2 deletions src/Pdo/PdoDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -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#';
Expand Down Expand Up @@ -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#';
Expand Down