Merge branch '2.3' into 2.4
* 2.3: fix docblock Fixed incompatibility of x509 auth with nginx [Process] Setting STDIN while running should not be possible [FrameworkBundle] improve English in RouterMatchCommand [Doctrine Bridge] simplify session handler by using main connection Conflicts: src/Symfony/Component/Process/Tests/AbstractProcessTest.php
This commit is contained in:
commit
0deaceb2ff
@ -12,21 +12,12 @@
|
||||
namespace Symfony\Bridge\Doctrine\HttpFoundation;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver\Connection as DriverConnection;
|
||||
use Doctrine\DBAL\Driver\Mysqli\MysqliConnection;
|
||||
use Doctrine\DBAL\Driver\OCI8\OCI8Connection;
|
||||
use Doctrine\DBAL\Driver\PDOConnection;
|
||||
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvConnection;
|
||||
use Doctrine\DBAL\Platforms\MySqlPlatform;
|
||||
use Doctrine\DBAL\Platforms\OraclePlatform;
|
||||
use Doctrine\DBAL\Platforms\SqlitePlatform;
|
||||
use Doctrine\DBAL\Platforms\SQLServerPlatform;
|
||||
|
||||
/**
|
||||
* DBAL based session storage.
|
||||
*
|
||||
* This implementation is very similar to Symfony\Component\HttpFoundation\Session\Storage\Handler\PdoSessionHandler
|
||||
* but uses the Doctrine driver connection interface and thus also works with non-PDO-based drivers like mysqli and OCI8.
|
||||
* but uses a Doctrine connection and thus also works with non-PDO-based drivers like mysqli and OCI8.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Johannes M. Schmitt <schmittjoh@gmail.com>
|
||||
@ -35,7 +26,7 @@ use Doctrine\DBAL\Platforms\SQLServerPlatform;
|
||||
class DbalSessionHandler implements \SessionHandlerInterface
|
||||
{
|
||||
/**
|
||||
* @var DriverConnection
|
||||
* @var Connection
|
||||
*/
|
||||
private $con;
|
||||
|
||||
@ -62,10 +53,10 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param DriverConnection $con A driver connection, preferably a wrapper Doctrine\DBAL\Connection for lazy connections
|
||||
* @param string $tableName Table name
|
||||
* @param Connection $con A connection
|
||||
* @param string $tableName Table name
|
||||
*/
|
||||
public function __construct(DriverConnection $con, $tableName = 'sessions')
|
||||
public function __construct(Connection $con, $tableName = 'sessions')
|
||||
{
|
||||
$this->con = $con;
|
||||
$this->table = $tableName;
|
||||
@ -74,7 +65,7 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function open($path = null, $name = null)
|
||||
public function open($savePath, $sessionName)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -90,14 +81,14 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function destroy($id)
|
||||
public function destroy($sessionId)
|
||||
{
|
||||
// delete the record associated with this id
|
||||
$sql = "DELETE FROM $this->table WHERE $this->idCol = :id";
|
||||
|
||||
try {
|
||||
$stmt = $this->con->prepare($sql);
|
||||
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Exception was thrown when trying to delete a session: %s', $e->getMessage()), 0, $e);
|
||||
@ -109,14 +100,14 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function gc($lifetime)
|
||||
public function gc($maxlifetime)
|
||||
{
|
||||
// delete the session records that have expired
|
||||
$sql = "DELETE FROM $this->table WHERE $this->timeCol < :time";
|
||||
|
||||
try {
|
||||
$stmt = $this->con->prepare($sql);
|
||||
$stmt->bindValue(':time', time() - $lifetime, \PDO::PARAM_INT);
|
||||
$stmt->bindValue(':time', time() - $maxlifetime, \PDO::PARAM_INT);
|
||||
$stmt->execute();
|
||||
} catch (\Exception $e) {
|
||||
throw new \RuntimeException(sprintf('Exception was thrown when trying to delete expired sessions: %s', $e->getMessage()), 0, $e);
|
||||
@ -128,13 +119,13 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function read($id)
|
||||
public function read($sessionId)
|
||||
{
|
||||
$sql = "SELECT $this->dataCol FROM $this->table WHERE $this->idCol = :id";
|
||||
|
||||
try {
|
||||
$stmt = $this->con->prepare($sql);
|
||||
$stmt->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$stmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$stmt->execute();
|
||||
|
||||
// We use fetchAll instead of fetchColumn to make sure the DB cursor gets closed
|
||||
@ -153,7 +144,7 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function write($id, $data)
|
||||
public function write($sessionId, $data)
|
||||
{
|
||||
// Session data can contain non binary safe characters so we need to encode it.
|
||||
$encoded = base64_encode($data);
|
||||
@ -166,7 +157,7 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
|
||||
if (null !== $mergeSql) {
|
||||
$mergeStmt = $this->con->prepare($mergeSql);
|
||||
$mergeStmt->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
|
||||
$mergeStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$mergeStmt->execute();
|
||||
@ -180,13 +171,13 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
$deleteStmt = $this->con->prepare(
|
||||
"DELETE FROM $this->table WHERE $this->idCol = :id"
|
||||
);
|
||||
$deleteStmt->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$deleteStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$deleteStmt->execute();
|
||||
|
||||
$insertStmt = $this->con->prepare(
|
||||
"INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)"
|
||||
);
|
||||
$insertStmt->bindParam(':id', $id, \PDO::PARAM_STR);
|
||||
$insertStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR);
|
||||
$insertStmt->bindParam(':data', $encoded, \PDO::PARAM_STR);
|
||||
$insertStmt->bindValue(':time', time(), \PDO::PARAM_INT);
|
||||
$insertStmt->execute();
|
||||
@ -211,32 +202,24 @@ class DbalSessionHandler implements \SessionHandlerInterface
|
||||
*/
|
||||
private function getMergeSql()
|
||||
{
|
||||
$platform = $pdoDriver = null;
|
||||
$platform = $this->con->getDatabasePlatform()->getName();
|
||||
|
||||
if ($this->con instanceof Connection) {
|
||||
$platform = $this->con->getDatabasePlatform();
|
||||
} elseif ($this->con instanceof PDOConnection) {
|
||||
$pdoDriver = $this->con->getAttribute(\PDO::ATTR_DRIVER_NAME);
|
||||
}
|
||||
|
||||
switch (true) {
|
||||
case $this->con instanceof MysqliConnection || $platform instanceof MySqlPlatform || 'mysql' === $pdoDriver:
|
||||
switch ($platform) {
|
||||
case 'mysql':
|
||||
return "INSERT INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) " .
|
||||
"ON DUPLICATE KEY UPDATE $this->dataCol = VALUES($this->dataCol), $this->timeCol = VALUES($this->timeCol)";
|
||||
case $this->con instanceof OCI8Connection || $platform instanceof OraclePlatform || 'oci' === $pdoDriver:
|
||||
case 'oracle':
|
||||
// DUAL is Oracle specific dummy table
|
||||
return "MERGE INTO $this->table USING DUAL ON ($this->idCol = :id) " .
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) " .
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data";
|
||||
case $this->con instanceof SQLSrvConnection || $platform instanceof SQLServerPlatform || 'sqlsrv' === $pdoDriver:
|
||||
case 'mssql':
|
||||
// MS SQL Server requires MERGE be terminated by semicolon
|
||||
return "MERGE INTO $this->table USING (SELECT 'x' AS dummy) AS src ON ($this->idCol = :id) " .
|
||||
"WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time) " .
|
||||
"WHEN MATCHED THEN UPDATE SET $this->dataCol = :data;";
|
||||
case $platform instanceof SqlitePlatform || 'sqlite' === $pdoDriver:
|
||||
case 'sqlite':
|
||||
return "INSERT OR REPLACE INTO $this->table ($this->idCol, $this->dataCol, $this->timeCol) VALUES (:id, :data, :time)";
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -22,9 +22,7 @@ class DbalSessionHandlerTest extends \PHPUnit_Framework_TestCase
|
||||
{
|
||||
public function testConstruct()
|
||||
{
|
||||
$this->connection = $this->getMock('Doctrine\DBAL\Driver\Connection');
|
||||
$mock = $this->getMockBuilder('Symfony\Bridge\Doctrine\HttpFoundation\DbalSessionHandler');
|
||||
$mock->setConstructorArgs(array($this->connection));
|
||||
$this->driver = $mock->getMock();
|
||||
$connection = $this->getMockBuilder('Doctrine\DBAL\Connection')->disableOriginalConstructor()->getMock();
|
||||
$handler = new DbalSessionHandler($connection);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ EOF
|
||||
}
|
||||
|
||||
if (!$matches) {
|
||||
$output->writeln('<fg=red>None of the routes matches</>');
|
||||
$output->writeln('<fg=red>None of the routes match</>');
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
@ -33,7 +33,7 @@ class BooleanNodeDefinition extends ScalarNodeDefinition
|
||||
/**
|
||||
* Instantiate a Node
|
||||
*
|
||||
* @return boolNode The node
|
||||
* @return BooleanNode The node
|
||||
*/
|
||||
protected function instantiateNode()
|
||||
{
|
||||
|
@ -23,7 +23,7 @@ class IntegerNodeDefinition extends NumericNodeDefinition
|
||||
/**
|
||||
* Instantiates a Node.
|
||||
*
|
||||
* @return intNode The node
|
||||
* @return IntegerNode The node
|
||||
*/
|
||||
protected function instantiateNode()
|
||||
{
|
||||
|
@ -81,7 +81,7 @@ class NodeBuilder implements NodeParentInterface
|
||||
*
|
||||
* @param string $name The name of the node
|
||||
*
|
||||
* @return boolNodeDefinition The child node
|
||||
* @return BooleanNodeDefinition The child node
|
||||
*/
|
||||
public function booleanNode($name)
|
||||
{
|
||||
@ -93,7 +93,7 @@ class NodeBuilder implements NodeParentInterface
|
||||
*
|
||||
* @param string $name the name of the node
|
||||
*
|
||||
* @return intNodeDefinition The child node
|
||||
* @return IntegerNodeDefinition The child node
|
||||
*/
|
||||
public function integerNode($name)
|
||||
{
|
||||
|
@ -929,9 +929,15 @@ class Process
|
||||
* @param string|null $stdin The new contents
|
||||
*
|
||||
* @return self The current Process instance
|
||||
*
|
||||
* @throws LogicException In case the process is running
|
||||
*/
|
||||
public function setStdin($stdin)
|
||||
{
|
||||
if ($this->isRunning()) {
|
||||
throw new LogicException('STDIN can not be set while the process is running.');
|
||||
}
|
||||
|
||||
$this->stdin = $stdin;
|
||||
|
||||
return $this;
|
||||
|
@ -12,6 +12,7 @@
|
||||
namespace Symfony\Component\Process\Tests;
|
||||
|
||||
use Symfony\Component\Process\Exception\ProcessTimedOutException;
|
||||
use Symfony\Component\Process\Exception\LogicException;
|
||||
use Symfony\Component\Process\Process;
|
||||
use Symfony\Component\Process\Exception\RuntimeException;
|
||||
use Symfony\Component\Process\ProcessPipes;
|
||||
@ -157,6 +158,20 @@ abstract class AbstractProcessTest extends \PHPUnit_Framework_TestCase
|
||||
$this->assertEquals($expectedLength, strlen($p->getErrorOutput()));
|
||||
}
|
||||
|
||||
public function testSetStdinWhileRunningThrowsAnException()
|
||||
{
|
||||
$process = $this->getProcess('php -r "usleep(500000);"');
|
||||
$process->start();
|
||||
try {
|
||||
$process->setStdin('foobar');
|
||||
$process->stop();
|
||||
$this->fail('A LogicException should have been raised.');
|
||||
} catch (LogicException $e) {
|
||||
$this->assertEquals('STDIN can not be set while the process is running.', $e->getMessage());
|
||||
}
|
||||
$process->stop();
|
||||
}
|
||||
|
||||
public function chainedCommandsOutputProvider()
|
||||
{
|
||||
if (defined('PHP_WINDOWS_VERSION_BUILD')) {
|
||||
|
@ -41,10 +41,17 @@ class X509AuthenticationListener extends AbstractPreAuthenticatedListener
|
||||
*/
|
||||
protected function getPreAuthenticatedData(Request $request)
|
||||
{
|
||||
if (!$request->server->has($this->userKey)) {
|
||||
throw new BadCredentialsException(sprintf('SSL key was not found: %s', $this->userKey));
|
||||
$user = null;
|
||||
if ($request->server->has($this->userKey)) {
|
||||
$user = $request->server->get($this->userKey);
|
||||
} elseif ($request->server->has($this->credentialKey) && preg_match('#/emailAddress=(.+\@.+\..+)(/|$)#', $request->server->get($this->credentialKey), $matches)) {
|
||||
$user = $matches[1];
|
||||
}
|
||||
|
||||
return array($request->server->get($this->userKey), $request->server->get($this->credentialKey, ''));
|
||||
if (null === $user) {
|
||||
throw new BadCredentialsException(sprintf('SSL credentials not found: %s, %s', $this->userKey, $this->credentialKey));
|
||||
}
|
||||
|
||||
return array($user, $request->server->get($this->credentialKey, ''));
|
||||
}
|
||||
}
|
||||
|
@ -35,11 +35,7 @@ class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
|
||||
|
||||
$listener = new X509AuthenticationListener(
|
||||
$context,
|
||||
$authenticationManager,
|
||||
'TheProviderKey'
|
||||
);
|
||||
$listener = new X509AuthenticationListener($context, $authenticationManager, 'TheProviderKey');
|
||||
|
||||
$method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
|
||||
$method->setAccessible(true);
|
||||
@ -56,10 +52,39 @@ class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderGetPreAuthenticatedDataNoUser
|
||||
*/
|
||||
public function testGetPreAuthenticatedDataNoUser($emailAddress)
|
||||
{
|
||||
$credentials = 'CN=Sample certificate DN/emailAddress='.$emailAddress;
|
||||
$request = new Request(array(), array(), array(), array(), array(), array('SSL_CLIENT_S_DN' => $credentials));
|
||||
|
||||
$context = $this->getMock('Symfony\Component\Security\Core\SecurityContextInterface');
|
||||
|
||||
$authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
|
||||
|
||||
$listener = new X509AuthenticationListener($context, $authenticationManager, 'TheProviderKey');
|
||||
|
||||
$method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
|
||||
$method->setAccessible(true);
|
||||
|
||||
$result = $method->invokeArgs($listener, array($request));
|
||||
$this->assertSame($result, array($emailAddress, $credentials));
|
||||
}
|
||||
|
||||
public static function dataProviderGetPreAuthenticatedDataNoUser()
|
||||
{
|
||||
return array(
|
||||
'basicEmailAddress' => array('cert@example.com'),
|
||||
'emailAddressWithPlusSign' => array('cert+something@example.com'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Security\Core\Exception\BadCredentialsException
|
||||
*/
|
||||
public function testGetPreAuthenticatedDataNoUser()
|
||||
public function testGetPreAuthenticatedDataNoData()
|
||||
{
|
||||
$request = new Request(array(), array(), array(), array(), array(), array());
|
||||
|
||||
@ -67,11 +92,7 @@ class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
|
||||
|
||||
$listener = new X509AuthenticationListener(
|
||||
$context,
|
||||
$authenticationManager,
|
||||
'TheProviderKey'
|
||||
);
|
||||
$listener = new X509AuthenticationListener($context, $authenticationManager, 'TheProviderKey');
|
||||
|
||||
$method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
|
||||
$method->setAccessible(true);
|
||||
@ -91,13 +112,7 @@ class X509AuthenticationListenerTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$authenticationManager = $this->getMock('Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface');
|
||||
|
||||
$listener = new X509AuthenticationListener(
|
||||
$context,
|
||||
$authenticationManager,
|
||||
'TheProviderKey',
|
||||
'TheUserKey',
|
||||
'TheCredentialsKey'
|
||||
);
|
||||
$listener = new X509AuthenticationListener($context, $authenticationManager, 'TheProviderKey', 'TheUserKey', 'TheCredentialsKey');
|
||||
|
||||
$method = new \ReflectionMethod($listener, 'getPreAuthenticatedData');
|
||||
$method->setAccessible(true);
|
||||
|
Reference in New Issue
Block a user