From 799b33ff5c0ebc495883440520334724e463767b Mon Sep 17 00:00:00 2001 From: Helmut Hummel Date: Wed, 13 Apr 2016 13:27:54 +0200 Subject: [PATCH] [BUGFIX] Properly escape options of dump database task --- Tests/Unit/Task/BaseTaskTest.php | 1 + Tests/Unit/Task/DumpDatabaseTaskTest.php | 51 ++++++++++++++++++++++++ src/Task/DumpDatabaseTask.php | 45 +++++++++++++++++++-- 3 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 Tests/Unit/Task/DumpDatabaseTaskTest.php diff --git a/Tests/Unit/Task/BaseTaskTest.php b/Tests/Unit/Task/BaseTaskTest.php index 62d66da8..5f296087 100644 --- a/Tests/Unit/Task/BaseTaskTest.php +++ b/Tests/Unit/Task/BaseTaskTest.php @@ -88,6 +88,7 @@ protected function setUp() } $this->node = new \TYPO3\Surf\Domain\Model\Node('TestNode'); + $this->node->setHostname('hostname'); $this->deployment = new \TYPO3\Surf\Domain\Model\Deployment('TestDeployment'); /** @var \Psr\Log\LoggerInterface|\PHPUnit_Framework_MockObject_MockObject $mockLogger */ $mockLogger = $this->getMock('Psr\Log\LoggerInterface'); diff --git a/Tests/Unit/Task/DumpDatabaseTaskTest.php b/Tests/Unit/Task/DumpDatabaseTaskTest.php new file mode 100644 index 00000000..9613d144 --- /dev/null +++ b/Tests/Unit/Task/DumpDatabaseTaskTest.php @@ -0,0 +1,51 @@ +application->setDeploymentPath('/home/jdoe/app'); + } + + /** + * @test + */ + public function executeProperlyEscapesInputOptions() + { + $options = array( + 'sourceHost' => 'localhost', + 'sourceUser' => 'user', + 'sourcePassword' => '(pass)', + 'sourceDatabase' => 'db', + 'targetHost' => 'localhost', + 'targetUser' => 'user', + 'targetPassword' => '(pass)', + 'targetDatabase' => 'db', + ); + $this->task->execute($this->node, $this->application, $this->deployment, $options); + + $this->assertCommandExecuted("'mysqldump' '-h' 'localhost' '-u' 'user' '-p(pass)' 'db' | 'ssh' 'hostname' ''\''mysql'\'' '\''-h'\'' '\''localhost'\'' '\''-u'\'' '\''user'\'' '\''-p(pass)'\'' '\''db'\'''"); + } + + /** + * @return \TYPO3\Surf\Domain\Model\Task + */ + protected function createTask() + { + return new \TYPO3\Surf\Task\DumpDatabaseTask(); + } +} diff --git a/src/Task/DumpDatabaseTask.php b/src/Task/DumpDatabaseTask.php index bb6560ad..a4332138 100755 --- a/src/Task/DumpDatabaseTask.php +++ b/src/Task/DumpDatabaseTask.php @@ -6,6 +6,7 @@ * * * */ +use Symfony\Component\Process\ProcessBuilder; use TYPO3\Surf\Domain\Model\Application; use TYPO3\Surf\Domain\Model\Deployment; use TYPO3\Surf\Domain\Model\Node; @@ -37,15 +38,53 @@ public function execute(Node $node, Application $application, Deployment $deploy { $this->assertRequiredOptionsExist($options); + $dumpCommand = new ProcessBuilder(); + $dumpCommand->setPrefix('mysqldump'); + $dumpCommand->setArguments( + array( + '-h', + $options['sourceHost'], + '-u', + $options['sourceUser'], + '-p' . $options['sourcePassword'], + $options['sourceDatabase'] + ) + ); + + $mysqlCommand = new ProcessBuilder(); + $mysqlCommand->setPrefix('mysql'); + $mysqlCommand->setArguments( + array( + '-h', + $options['targetHost'], + '-u', + $options['targetUser'], + '-p' . $options['targetPassword'], + $options['targetDatabase'] + ) + ); + + $arguments = array(); $username = isset($options['username']) ? $options['username'] . '@' : ''; $hostname = $node->getHostname(); - $port = $node->hasOption('port') ? '-P ' . escapeshellarg($node->getOption('port')) : ''; - $commands[] = "mysqldump -h {$options['sourceHost']} -u{$options['sourceUser']} -p{$options['sourcePassword']} {$options['sourceDatabase']} | ssh {$port} {$username}{$hostname} 'mysql -h {$options['targetHost']} -u{$options['targetUser']} -p{$options['targetPassword']} {$options['targetDatabase']}'"; + $arguments[] = $username . $hostname; + if ($node->hasOption('port')) { + $arguments[] = '-P'; + $arguments[] = $node->getOption('port'); + } + $arguments[] = $mysqlCommand->getProcess()->getCommandLine(); + $sshCommand = new ProcessBuilder(); + $sshCommand->setPrefix('ssh'); + $sshCommand->setArguments($arguments); + + $command = $dumpCommand->getProcess()->getCommandLine() + . ' | ' + . $sshCommand->getProcess()->getCommandLine(); $localhost = new Node('localhost'); $localhost->setHostname('localhost'); - $this->shell->executeOrSimulate($commands, $localhost, $deployment); + $this->shell->executeOrSimulate($command, $localhost, $deployment); } /**