Skip to content

Commit

Permalink
Move adjustment of options to constructor (#317)
Browse files Browse the repository at this point in the history
  • Loading branch information
richard67 authored Jan 8, 2025
1 parent 87cf891 commit fabf884
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 52 deletions.
54 changes: 31 additions & 23 deletions src/DatabaseDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -1897,59 +1897,67 @@ public function updateObject($table, &$object, $key, $nulls = false)
/**
* 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.
* @param string $host Host given in options used to configure the connection.
* @param integer|null $port Port given in options used to configure the connection, null if none.
* @param string|null $socket Socket given in options used to configure the connection, null if none.
* @param integer $defaultPort The default port number to be used if no port is given.
* @param boolean $ipv6SquareBrackets True if database connector uses ipv6 address with square brackets, false if not.
*
* @since __DEPLOY_VERSION__
* @return array Array with host, port and socket.
*
* @since __DEPLOY_VERSION__
*/
protected function setHostPortSocket($defaultPort)
protected function extractHostPortSocket(string $host, ?int $port, ?string $socket, int $defaultPort, bool $ipv6SquareBrackets = true): array
{
$port = $this->options['port'] ?? $defaultPort;
$portNew = $port ?? $defaultPort;

if (preg_match('/^unix:(?P<socket>[^:]+)$/', $this->options['host'], $matches)) {
if (preg_match('/^unix:(?P<socket>[^:]+)$/', $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;
$host = null;
$socket = $matches['socket'];
$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'],
$host,
$matches
)
) {
// It's an IPv4 address with or without port
$this->options['host'] = $matches['host'];
$host = $matches['host'];

if (!empty($matches['port'])) {
$port = $matches['port'];
$portNew = $matches['port'];
}
} elseif (preg_match('/^(?P<host>\[.*\])(:(?P<port>.+))?$/', $this->options['host'], $matches)) {
} elseif (preg_match('/^(?P<host>\[.*\])(:(?P<port>.+))?$/', $host, $matches)) {
// We assume square-bracketed IPv6 address with or without port, e.g. [fe80:102::2%eth1]:3306
$this->options['host'] = $matches['host'];
$host = $ipv6SquareBrackets ? $matches['host'] : rtrim(ltrim($matches['host'], '['), ']');

if (!empty($matches['port'])) {
$port = $matches['port'];
$portNew = $matches['port'];
}
} elseif (preg_match('/^(?P<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/i', $this->options['host'], $matches)) {
} elseif (preg_match('/^(?P<host>(\w+:\/{2,3})?[a-z0-9\.\-]+)(:(?P<port>[^:]+))?$/i', $host, $matches)) {
// Named host (e.g example.com or localhost) with or without port
$this->options['host'] = $matches['host'];
$host = $matches['host'];

if (!empty($matches['port'])) {
$port = $matches['port'];
$portNew = $matches['port'];
}
} elseif (preg_match('/^:(?P<port>[^:]+)$/', $this->options['host'], $matches)) {
} elseif (preg_match('/^:(?P<port>[^:]+)$/', $host, $matches)) {
// Empty host, just port, e.g. ':3306'
$this->options['host'] = 'localhost';
$port = $matches['port'];
$host = 'localhost';
$portNew = $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;
if (is_numeric($portNew)) {
$port = (int) $portNew;
} else {
$this->options['socket'] = $port;
$socket = $portNew;
}

return [$host, $port, $socket];
}
}
7 changes: 4 additions & 3 deletions src/Mysqli/MysqliDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,10 @@ public function __construct(array $options)
$options['ssl']['verify_server_cert'] = isset($options['ssl']['verify_server_cert']) ? $options['ssl']['verify_server_cert'] : null;
}

// Extract host and port or socket from host option
[$options['host'], $options['port'], $options['socket']]
= $this->extractHostPortSocket($options['host'], $options['port'], $options['socket'], 3306);

// Finalize initialisation.
parent::__construct($options);
}
Expand Down Expand Up @@ -198,9 +202,6 @@ public function connect()
throw new UnsupportedAdapterException('The MySQLi extension is not available');
}

// Extract host and port or socket from host option
$this->setHostPortSocket(3306);

$this->connection = mysqli_init();

$connectionFlags = 0;
Expand Down
87 changes: 61 additions & 26 deletions src/Pdo/PdoDriver.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ public function __construct(array $options)
$options['password'] = $options['password'] ?? '';
$options['driverOptions'] = $options['driverOptions'] ?? [];
$options['ssl'] = isset($options['ssl']) ? $options['ssl'] : [];
$options['socket'] = \strpos($options['host'], 'unix:') !== false ? \str_replace('unix:', '', $options['host']) : null;
$options['socket'] = $options['socket'] ?? null;

if ($options['ssl'] !== []) {
$options['ssl']['enable'] = isset($options['ssl']['enable']) ? $options['ssl']['enable'] : false;
Expand All @@ -92,6 +92,65 @@ public function __construct(array $options)
$options['ssl']['verify_server_cert'] = isset($options['ssl']['verify_server_cert']) ? $options['ssl']['verify_server_cert'] : null;
}

// Sanitize options
switch ($options['driver']) {
case 'cubrid':
$options['port'] = $options['port'] ?? 33000;

break;

case 'dblib':
case 'mssql':
case 'sybase':
$options['port'] = $options['port'] ?? 1433;

break;

case 'firebird':
$options['port'] = $options['port'] ?? 3050;

break;

case 'ibm':
$options['port'] = $options['port'] ?? 56789;

break;

case 'informix':
$options['port'] = $options['port'] ?? 1526;
$options['protocol'] = $options['protocol'] ?? 'onsoctcp';

break;

case 'mysql':
// Extract host and port or socket from host option
[$options['host'], $options['port'], $options['socket']]
= $this->extractHostPortSocket($options['host'], $options['port'], $options['socket'], 3306);

break;

case 'oci':
$options['port'] = $options['port'] ?? 1521;
$options['charset'] = $options['charset'] ?? 'AL32UTF8';

break;

case 'pgsql':
// Extract host and port or socket from host option and remove square brackets around ipv6 address
[$options['host'], $options['port'], $options['socket']]
= $this->extractHostPortSocket($options['host'], $options['port'], $options['socket'], 5432, false);

break;

case 'sqlite':
$options['version'] = isset($options['version']) ? (int) $options['version'] : 1;

break;

default:
// Do nothing
}

// Finalize initialisation
parent::__construct($options);
}
Expand Down Expand Up @@ -128,8 +187,6 @@ public function connect()
// Find the correct PDO DSN Format to use:
switch ($this->options['driver']) {
case 'cubrid':
$this->options['port'] = $this->options['port'] ?? 33000;

$format = 'cubrid:host=#HOST#;port=#PORT#;dbname=#DBNAME#';

$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
Expand All @@ -138,8 +195,6 @@ public function connect()
break;

case 'dblib':
$this->options['port'] = $this->options['port'] ?? 1433;

$format = 'dblib:host=#HOST#;port=#PORT#;dbname=#DBNAME#';

$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
Expand All @@ -148,8 +203,6 @@ public function connect()
break;

case 'firebird':
$this->options['port'] = $this->options['port'] ?? 3050;

$format = 'firebird:dbname=#DBNAME#';

$replace = ['#DBNAME#'];
Expand All @@ -158,8 +211,6 @@ public function connect()
break;

case 'ibm':
$this->options['port'] = $this->options['port'] ?? 56789;

if (!empty($this->options['dsn'])) {
$format = 'ibm:DSN=#DSN#';

Expand All @@ -175,9 +226,6 @@ public function connect()
break;

case 'informix':
$this->options['port'] = $this->options['port'] ?? 1526;
$this->options['protocol'] = $this->options['protocol'] ?? 'onsoctcp';

if (!empty($this->options['dsn'])) {
$format = 'informix:DSN=#DSN#';

Expand All @@ -199,8 +247,6 @@ public function connect()
break;

case 'mssql':
$this->options['port'] = $this->options['port'] ?? 1433;

$format = 'mssql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';

$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
Expand All @@ -209,9 +255,6 @@ public function connect()
break;

case 'mysql':
// 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#';
} else {
Expand All @@ -230,9 +273,6 @@ public function connect()
break;

case 'oci':
$this->options['port'] = $this->options['port'] ?? 1521;
$this->options['charset'] = $this->options['charset'] ?? 'AL32UTF8';

if (!empty($this->options['dsn'])) {
$format = 'oci:dbname=#DSN#';

Expand All @@ -258,9 +298,6 @@ public function connect()
break;

case 'pgsql':
// Extract host and port or socket from host option
$this->setHostPortSocket(5432);

if ($this->options['socket'] !== null) {
$format = 'pgsql:host=#SOCKET#;dbname=#DBNAME#';
} else {
Expand Down Expand Up @@ -297,7 +334,7 @@ public function connect()
break;

case 'sqlite':
if (isset($this->options['version']) && $this->options['version'] == 2) {
if ($this->options['version'] === 2) {
$format = 'sqlite2:#DBNAME#';
} else {
$format = 'sqlite:#DBNAME#';
Expand All @@ -309,8 +346,6 @@ public function connect()
break;

case 'sybase':
$this->options['port'] = $this->options['port'] ?? 1433;

$format = 'mssql:host=#HOST#;port=#PORT#;dbname=#DBNAME#';

$replace = ['#HOST#', '#PORT#', '#DBNAME#'];
Expand Down

0 comments on commit fabf884

Please sign in to comment.