Skip to content

Commit 779833b

Browse files
committed
Merge branch '2.8'
* 2.8: Fixed tabs when there are several groups of tabs in the same page Fix mode Fixed failing test for HHVM Removed unused logic in MockStream Update coding standard for MockStream [Filesystem] added tempnam() stream wrapper aware version of PHP's native tempnam() and fixed dumpFile to allow dumping to streams Renamed key to secret
2 parents f37932c + 775129f commit 779833b

File tree

16 files changed

+314
-29
lines changed

16 files changed

+314
-29
lines changed

UPGRADE-3.0.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -611,7 +611,8 @@ UPGRADE FROM 2.x to 3.0
611611

612612
* The `Resources/` directory was moved to `Core/Resources/`
613613

614-
* The `key` settings of `anonymous` and `remember_me` are renamed to `secret`.
614+
* The `key` settings of `anonymous`, `remember_me` and `http_digest` are
615+
renamed to `secret`.
615616

616617
Before:
617618

@@ -624,6 +625,8 @@ UPGRADE FROM 2.x to 3.0
624625
anonymous: { key: "%secret%" }
625626
remember_me:
626627
key: "%secret%"
628+
http_digest:
629+
key: "%secret%"
627630
```
628631

629632
```xml
@@ -636,6 +639,7 @@ UPGRADE FROM 2.x to 3.0
636639
637640
<anonymous key="%secret%"/>
638641
<remember-me key="%secret%"/>
642+
<http-digest key="%secret%"/>
639643
</firewall>
640644
</config>
641645
```
@@ -648,6 +652,7 @@ UPGRADE FROM 2.x to 3.0
648652
// ...
649653
'anonymous' => array('key' => '%secret%'),
650654
'remember_me' => array('key' => '%secret%'),
655+
'http_digest' => array('key' => '%secret%'),
651656
),
652657
));
653658
```
@@ -663,6 +668,8 @@ UPGRADE FROM 2.x to 3.0
663668
anonymous: { secret: "%secret%" }
664669
remember_me:
665670
secret: "%secret%"
671+
http_digest:
672+
secret: "%secret%"
666673
```
667674

668675
```xml
@@ -675,6 +682,7 @@ UPGRADE FROM 2.x to 3.0
675682
676683
<anonymous secret="%secret%"/>
677684
<remember-me secret="%secret%"/>
685+
<http-digest secret="%secret%"/>
678686
</firewall>
679687
</config>
680688
```
@@ -687,6 +695,7 @@ UPGRADE FROM 2.x to 3.0
687695
// ...
688696
'anonymous' => array('secret' => '%secret%'),
689697
'remember_me' => array('secret' => '%secret%'),
698+
'http_digest' => array('secret' => '%secret%'),
690699
),
691700
));
692701
```

src/Symfony/Bundle/SecurityBundle/CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ CHANGELOG
99
2.8.0
1010
-----
1111

12-
* deprecated the `key` setting of `anonymous` and `remember_me` in favor of the
13-
`secret` setting.
12+
* deprecated the `key` setting of `anonymous`, `remember_me` and `http_digest`
13+
in favor of the `secret` setting.
1414

1515
2.6.0
1616
-----

src/Symfony/Bundle/SecurityBundle/DependencyInjection/Security/Factory/HttpDigestFactory.php

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,26 @@ public function getKey()
5858
public function addConfiguration(NodeDefinition $node)
5959
{
6060
$node
61+
->beforeNormalization()
62+
->ifTrue(function ($v) { return isset($v['key']); })
63+
->then(function ($v) {
64+
if (isset($v['secret'])) {
65+
throw new \LogicException('Cannot set both key and secret options for http_digest, use only secret instead.');
66+
}
67+
68+
@trigger_error('http_digest.key is deprecated since version 2.8 and will be removed in 3.0. Use http_digest.secret instead.', E_USER_DEPRECATED);
69+
70+
$v['secret'] = $v['key'];
71+
72+
unset($v['key']);
73+
74+
return $v;
75+
})
76+
->end()
6177
->children()
6278
->scalarNode('provider')->end()
6379
->scalarNode('realm')->defaultValue('Secured Area')->end()
64-
->scalarNode('key')->isRequired()->cannotBeEmpty()->end()
80+
->scalarNode('secret')->isRequired()->cannotBeEmpty()->end()
6581
->end()
6682
;
6783
}
@@ -76,7 +92,7 @@ protected function createEntryPoint($container, $id, $config, $defaultEntryPoint
7692
$container
7793
->setDefinition($entryPointId, new DefinitionDecorator('security.authentication.digest_entry_point'))
7894
->addArgument($config['realm'])
79-
->addArgument($config['key'])
95+
->addArgument($config['secret'])
8096
;
8197

8298
return $entryPointId;

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/php/container1.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@
6464
'simple' => array('pattern' => '/login', 'security' => false),
6565
'secure' => array('stateless' => true,
6666
'http_basic' => true,
67-
'http_digest' => array('key' => 'TheKey'),
67+
'http_digest' => array('secret' => 'TheSecret'),
6868
'form_login' => true,
6969
'anonymous' => true,
7070
'switch_user' => true,

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/xml/container1.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949

5050
<firewall name="secure" stateless="true">
5151
<http-basic />
52-
<http-digest key="TheKey" />
52+
<http-digest secret="TheSecret" />
5353
<form-login />
5454
<anonymous />
5555
<switch-user />

src/Symfony/Bundle/SecurityBundle/Tests/DependencyInjection/Fixtures/yml/container1.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ security:
4747
stateless: true
4848
http_basic: true
4949
http_digest:
50-
key: TheKey
50+
secret: TheSecret
5151
form_login: true
5252
anonymous: true
5353
switch_user: true

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@
359359
activeTab = activeTab.parentNode;
360360
}
361361
362+
/* get the full list of tabs through the parent of the active tab element */
363+
var tabNavigation = activeTab.parentNode.children;
362364
for (var k = 0; k < tabNavigation.length; k++) {
363365
var tabId = tabNavigation[k].getAttribute('data-tab-id');
364366
document.getElementById(tabId).className = 'hidden';

src/Symfony/Component/Filesystem/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ CHANGELOG
66

77
* removed `$mode` argument from `Filesystem::dumpFile()`
88

9+
2.8.0
10+
-----
11+
12+
* added tempnam() a stream aware version of PHP's native tempnam()
13+
914
2.6.0
1015
-----
1116

src/Symfony/Component/Filesystem/Filesystem.php

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,58 @@ public function isAbsolutePath($file)
452452
);
453453
}
454454

455+
/**
456+
* Creates a temporary file with support for custom stream wrappers.
457+
*
458+
* @param string $dir The directory where the temporary filename will be created.
459+
* @param string $prefix The prefix of the generated temporary filename.
460+
* Note: Windows uses only the first three characters of prefix.
461+
*
462+
* @return string The new temporary filename (with path), or throw an exception on failure.
463+
*/
464+
public function tempnam($dir, $prefix)
465+
{
466+
list($scheme, $hierarchy) = $this->getSchemeAndHierarchy($dir);
467+
468+
// If no scheme or scheme is "file" create temp file in local filesystem
469+
if (null === $scheme || 'file' === $scheme) {
470+
$tmpFile = tempnam($hierarchy, $prefix);
471+
472+
// If tempnam failed or no scheme return the filename otherwise prepend the scheme
473+
if (false !== $tmpFile) {
474+
if (null !== $scheme) {
475+
return $scheme.'://'.$tmpFile;
476+
}
477+
478+
return $tmpFile;
479+
}
480+
481+
throw new IOException('A temporary file could not be created.');
482+
}
483+
484+
// Loop until we create a valid temp file or have reached 10 attempts
485+
for ($i = 0; $i < 10; ++$i) {
486+
// Create a unique filename
487+
$tmpFile = $dir.'/'.$prefix.uniqid(mt_rand(), true);
488+
489+
// Use fopen instead of file_exists as some streams do not support stat
490+
// Use mode 'x+' to atomically check existence and create to avoid a TOCTOU vulnerability
491+
$handle = @fopen($tmpFile, 'x+');
492+
493+
// If unsuccessful restart the loop
494+
if (false === $handle) {
495+
continue;
496+
}
497+
498+
// Close the file if it was successfully opened
499+
@fclose($handle);
500+
501+
return $tmpFile;
502+
}
503+
504+
throw new IOException('A temporary file could not be created.');
505+
}
506+
455507
/**
456508
* Atomically dumps content into a file.
457509
*
@@ -470,7 +522,7 @@ public function dumpFile($filename, $content)
470522
throw new IOException(sprintf('Unable to write to the "%s" directory.', $dir), 0, null, $dir);
471523
}
472524

473-
$tmpFile = tempnam($dir, basename($filename));
525+
$tmpFile = $this->tempnam($dir, basename($filename));
474526

475527
if (false === @file_put_contents($tmpFile, $content)) {
476528
throw new IOException(sprintf('Failed to write file "%s".', $filename), 0, null, $filename);
@@ -492,4 +544,18 @@ private function toIterator($files)
492544

493545
return $files;
494546
}
547+
548+
/**
549+
* Gets a 2-tuple of scheme (may be null) and hierarchical part of a filename (e.g. file:///tmp -> array(file, tmp)).
550+
*
551+
* @param string $filename The filename to be parsed.
552+
*
553+
* @return array The filename scheme and hierarchical part
554+
*/
555+
private function getSchemeAndHierarchy($filename)
556+
{
557+
$components = explode('://', $filename, 2);
558+
559+
return 2 === count($components) ? array($components[0], $components[1]) : array(null, $components[0]);
560+
}
495561
}

src/Symfony/Component/Filesystem/Tests/FilesystemTest.php

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,110 @@ public function providePathsForIsAbsolutePath()
946946
);
947947
}
948948

949+
public function testTempnam()
950+
{
951+
$dirname = $this->workspace;
952+
953+
$filename = $this->filesystem->tempnam($dirname, 'foo');
954+
955+
$this->assertFileExists($filename);
956+
}
957+
958+
public function testTempnamWithFileScheme()
959+
{
960+
$scheme = 'file://';
961+
$dirname = $scheme.$this->workspace;
962+
963+
$filename = $this->filesystem->tempnam($dirname, 'foo');
964+
965+
$this->assertStringStartsWith($scheme, $filename);
966+
$this->assertFileExists($filename);
967+
}
968+
969+
public function testTempnamWithMockScheme()
970+
{
971+
stream_wrapper_register('mock', 'Symfony\Component\Filesystem\Tests\Fixtures\MockStream\MockStream');
972+
973+
$scheme = 'mock://';
974+
$dirname = $scheme.$this->workspace;
975+
976+
$filename = $this->filesystem->tempnam($dirname, 'foo');
977+
978+
$this->assertStringStartsWith($scheme, $filename);
979+
$this->assertFileExists($filename);
980+
}
981+
982+
/**
983+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
984+
*/
985+
public function testTempnamWithZlibSchemeFails()
986+
{
987+
$scheme = 'compress.zlib://';
988+
$dirname = $scheme.$this->workspace;
989+
990+
// The compress.zlib:// stream does not support mode x: creates the file, errors "failed to open stream: operation failed" and returns false
991+
$this->filesystem->tempnam($dirname, 'bar');
992+
993+
}
994+
995+
public function testTempnamWithPHPTempSchemeFails()
996+
{
997+
$scheme = 'php://temp';
998+
$dirname = $scheme;
999+
1000+
$filename = $this->filesystem->tempnam($dirname, 'bar');
1001+
1002+
$this->assertStringStartsWith($scheme, $filename);
1003+
1004+
// The php://temp stream deletes the file after close
1005+
$this->assertFileNotExists($filename);
1006+
}
1007+
1008+
/**
1009+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
1010+
*/
1011+
public function testTempnamWithPharSchemeFails()
1012+
{
1013+
// Skip test if Phar disabled phar.readonly must be 0 in php.ini
1014+
if (!\Phar::canWrite()) {
1015+
$this->markTestSkipped('This test cannot run when phar.readonly is 1.');
1016+
}
1017+
1018+
$scheme = 'phar://';
1019+
$dirname = $scheme.$this->workspace;
1020+
$pharname = 'foo.phar';
1021+
1022+
new \Phar($this->workspace.'/'.$pharname, 0, $pharname);
1023+
// The phar:// stream does not support mode x: fails to create file, errors "failed to open stream: phar error: "$filename" is not a file in phar "$pharname"" and returns false
1024+
$this->filesystem->tempnam($dirname, $pharname.'/bar');
1025+
}
1026+
1027+
/**
1028+
* @expectedException \Symfony\Component\Filesystem\Exception\IOException
1029+
*/
1030+
public function testTempnamWithHTTPSchemeFails()
1031+
{
1032+
$scheme = 'http://';
1033+
$dirname = $scheme.$this->workspace;
1034+
1035+
// The http:// scheme is read-only
1036+
$this->filesystem->tempnam($dirname, 'bar');
1037+
}
1038+
1039+
public function testTempnamOnUnwritableFallsBackToSysTmp()
1040+
{
1041+
$scheme = 'file://';
1042+
$dirname = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'does_not_exist';
1043+
1044+
$filename = $this->filesystem->tempnam($dirname, 'bar');
1045+
1046+
$this->assertStringStartsWith(rtrim($scheme.sys_get_temp_dir(), DIRECTORY_SEPARATOR), $filename);
1047+
$this->assertFileExists($filename);
1048+
1049+
// Tear down
1050+
@unlink($filename);
1051+
}
1052+
9491053
public function testDumpFile()
9501054
{
9511055
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
@@ -971,6 +1075,33 @@ public function testDumpFileOverwritesAnExistingFile()
9711075
$this->assertSame('bar', file_get_contents($filename));
9721076
}
9731077

1078+
public function testDumpFileWithFileScheme()
1079+
{
1080+
if (defined('HHVM_VERSION')) {
1081+
$this->markTestSkipped('HHVM does not handle the file:// scheme correctly');
1082+
}
1083+
1084+
$scheme = 'file://';
1085+
$filename = $scheme.$this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1086+
1087+
$this->filesystem->dumpFile($filename, 'bar', null);
1088+
1089+
$this->assertFileExists($filename);
1090+
$this->assertSame('bar', file_get_contents($filename));
1091+
}
1092+
1093+
public function testDumpFileWithZlibScheme()
1094+
{
1095+
$scheme = 'compress.zlib://';
1096+
$filename = $this->workspace.DIRECTORY_SEPARATOR.'foo'.DIRECTORY_SEPARATOR.'baz.txt';
1097+
1098+
$this->filesystem->dumpFile($filename, 'bar', null);
1099+
1100+
// Zlib stat uses file:// wrapper so remove scheme
1101+
$this->assertFileExists(str_replace($scheme, '', $filename));
1102+
$this->assertSame('bar', file_get_contents($filename));
1103+
}
1104+
9741105
public function testCopyShouldKeepExecutionPermission()
9751106
{
9761107
$this->markAsSkippedIfChmodIsMissing();

0 commit comments

Comments
 (0)