Support IPv6 in database DSN (#9937)

This commit is contained in:
Aleksander Machniak
2025-07-25 18:55:21 +02:00
parent 55000023ce
commit 70e4e86148
3 changed files with 40 additions and 7 deletions

View File

@@ -2,6 +2,7 @@
## Unreleased
- Support IPv6 in database DSN (#9937)
## Release 1.7-beta

View File

@@ -1280,9 +1280,18 @@ class rcube_db
// process the different protocol options
$parsed['protocol'] = !empty($proto) ? $proto : 'tcp';
$proto_opts = rawurldecode($proto_opts);
if (strpos($proto_opts, ':') !== false) {
// Support IPv6 in the host spec.
if (preg_match('/(\[[a-f0-9:]+\])/i', $proto_opts, $matches)) {
$proto_opts = str_replace($matches[1], '', $proto_opts);
if (($pos = strpos($proto_opts, ':')) !== false) {
$parsed['port'] = substr($proto_opts, $pos + 1);
}
$proto_opts = $matches[1];
} elseif (strpos($proto_opts, ':') !== false) {
[$proto_opts, $parsed['port']] = explode(':', $proto_opts);
}
if ($parsed['protocol'] == 'tcp' && strlen($proto_opts)) {
$parsed['hostspec'] = $proto_opts;
} elseif ($parsed['protocol'] == 'unix') {

View File

@@ -181,9 +181,7 @@ class DBTest extends TestCase
public function test_parse_dsn()
{
$dsn = 'mysql://USERNAME:PASSWORD@HOST:3306/DATABASE';
$result = \rcube_db::parse_dsn($dsn);
$result = \rcube_db::parse_dsn('mysql://USERNAME:PASSWORD@HOST:3306/DATABASE');
$this->assertSame('mysql', $result['phptype']);
$this->assertSame('USERNAME', $result['username']);
@@ -192,9 +190,7 @@ class DBTest extends TestCase
$this->assertSame('HOST', $result['hostspec']);
$this->assertSame('DATABASE', $result['database']);
$dsn = 'pgsql:///DATABASE';
$result = \rcube_db::parse_dsn($dsn);
$result = \rcube_db::parse_dsn('pgsql:///DATABASE');
$this->assertSame('pgsql', $result['phptype']);
$this->assertTrue(!array_key_exists('username', $result));
@@ -202,6 +198,33 @@ class DBTest extends TestCase
$this->assertTrue(!array_key_exists('port', $result));
$this->assertTrue(!array_key_exists('hostspec', $result));
$this->assertSame('DATABASE', $result['database']);
$result = \rcube_db::parse_dsn('mysql://user:pass@[fd00:3::11]:3306/roundcubemail');
$this->assertSame('mysql', $result['phptype']);
$this->assertSame('user', $result['username']);
$this->assertSame('pass', $result['password']);
$this->assertSame('[fd00:3::11]', $result['hostspec']);
$this->assertSame('3306', $result['port']);
$this->assertSame('roundcubemail', $result['database']);
$result = \rcube_db::parse_dsn('mysql://user:pass@[::1]/roundcubemail');
$this->assertSame('mysql', $result['phptype']);
$this->assertSame('user', $result['username']);
$this->assertSame('pass', $result['password']);
$this->assertSame('[::1]', $result['hostspec']);
$this->assertTrue(!array_key_exists('port', $result));
$this->assertSame('roundcubemail', $result['database']);
$result = \rcube_db::parse_dsn('mysql://192.168.0.1:1234/roundcubemail');
$this->assertSame('mysql', $result['phptype']);
$this->assertSame('192.168.0.1', $result['hostspec']);
$this->assertSame('1234', $result['port']);
$this->assertTrue(!array_key_exists('username', $result));
$this->assertTrue(!array_key_exists('password', $result));
$this->assertSame('roundcubemail', $result['database']);
}
/**