Skip to content

Commit b1afeaf

Browse files
authored
removes user and password from dsn in commands (fixes #2013) (#2047)
* add assertion for #2013 * remove user and password from dsn * fix missing non-key-value elements
1 parent 1288611 commit b1afeaf

File tree

2 files changed

+64
-16
lines changed

2 files changed

+64
-16
lines changed

src/Propel/Generator/Command/AbstractCommand.php

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -144,23 +144,35 @@ protected function createDirectory(string $directory): void
144144
*/
145145
protected function parseConnection(string $connection): array
146146
{
147-
$length = strpos($connection, '=') ?: null;
148-
$name = substr($connection, 0, $length);
149-
$dsn = substr($connection, $length + 1, strlen($connection));
147+
$firstEqualsSignPosition = strpos($connection, '=') ?: null;
148+
$name = substr($connection, 0, $firstEqualsSignPosition);
149+
$remainder = substr($connection, $firstEqualsSignPosition + 1);
150150

151-
$length = strpos($dsn, ':') ?: null;
152-
$adapter = substr($dsn, 0, $length);
151+
$firstColonPosition = strpos($remainder, ':') ?: null;
152+
$adapter = substr($remainder, 0, $firstColonPosition);
153+
$remainder = substr($remainder, $firstColonPosition + 1);
153154

154155
$extras = [];
155-
foreach (explode(';', $dsn) as $element) {
156+
$dsn = $adapter . ':';
157+
foreach (explode(';', $remainder) as $element) {
156158
$parts = explode('=', $element);
159+
157160
if (count($parts) === 2) {
158-
$extras[strtolower($parts[0])] = urldecode($parts[1]);
161+
$key = strtolower($parts[0]);
162+
$value = urldecode($parts[1]);
163+
$extras[$key] = $value;
164+
165+
if ($key === 'user' || $key === 'password') {
166+
// dsn can't contain user or password for (at least) sql server
167+
continue;
168+
}
159169
}
170+
171+
$dsn .= $element . ';';
160172
}
161173
$extras['adapter'] = $adapter;
162174

163-
return [$name, $dsn, $extras];
175+
return [$name, trim($dsn, ';'), $extras];
164176
}
165177

166178
/**

tests/Propel/Tests/Generator/Command/AbstractCommandTest.php

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
*/
2121
class AbstractCommandTest extends TestCase
2222
{
23-
protected $command;
23+
protected TestableAbstractCommand $command;
2424

2525
/**
2626
* @return void
@@ -33,23 +33,59 @@ public function setUp(): void
3333
/**
3434
* @return void
3535
*/
36-
public function testParseConnection()
36+
public function testParseConnectionWithCredentials(): void
3737
{
38+
$user = 'root';
3839
$password = 'H7{“Qj1n>\%28=;P';
3940
$connectionName = 'bookstore';
40-
$dsn = 'mysql:host=127.0.0.1;dbname=test;user=root;password=' . urlencode($password);
41-
$result = $this->command->parseConnection($connectionName . '=' . $dsn);
41+
$dsn = 'mysql:host=127.0.0.1;dbname=test';
42+
$connection = sprintf(
43+
'%s=%s;user=%s;password=%s',
44+
$connectionName,
45+
$dsn,
46+
$user,
47+
urlencode($password)
48+
);
49+
$result = $this->command->parseConnection($connection);
4250

51+
$this->assertCount(3, $result);
4352
$this->assertEquals($connectionName, $result[0]);
44-
$this->assertEquals($dsn, $result[1]);
45-
$this->assertEquals('root', $result[2]['user']);
53+
$this->assertEquals($dsn, $result[1], 'DSN should not contain user and password parameters');
54+
$this->assertArrayHasKey('adapter', $result[2]);
55+
$this->assertEquals('mysql', $result[2]['adapter']);
56+
$this->assertArrayHasKey('user', $result[2]);
57+
$this->assertEquals($user, $result[2]['user']);
58+
$this->assertArrayHasKey('password', $result[2]);
4659
$this->assertEquals($password, $result[2]['password']);
4760
}
4861

4962
/**
5063
* @return void
5164
*/
52-
public function testRecursiveSearch()
65+
public function testParseConnectionWithoutCredentials(): void
66+
{
67+
$connectionName = 'bookstore';
68+
$dsn = 'sqlite:/tmp/test.sq3';
69+
$connection = sprintf(
70+
'%s=%s',
71+
$connectionName,
72+
$dsn
73+
);
74+
$result = $this->command->parseConnection($connection);
75+
76+
$this->assertCount(3, $result);
77+
$this->assertEquals($connectionName, $result[0]);
78+
$this->assertEquals($dsn, $result[1], 'DSN should not contain user and password parameters');
79+
$this->assertArrayHasKey('adapter', $result[2]);
80+
$this->assertEquals('sqlite', $result[2]['adapter']);
81+
$this->assertArrayNotHasKey('user', $result[2]);
82+
$this->assertArrayNotHasKey('password', $result[2]);
83+
}
84+
85+
/**
86+
* @return void
87+
*/
88+
public function testRecursiveSearch(): void
5389
{
5490
$app = new Application();
5591
$app->add($this->command);
@@ -83,7 +119,7 @@ class TestableAbstractCommand extends AbstractCommand
83119
/**
84120
* @return void
85121
*/
86-
protected function configure()
122+
protected function configure(): void
87123
{
88124
parent::configure();
89125
$this->setName('testable-command');

0 commit comments

Comments
 (0)