[HttpFoundation] made ResponseHeaderBag::makeDisposition static
This commit is contained in:
parent
61d336b4ca
commit
d29b410262
@ -18,6 +18,9 @@ namespace Symfony\Component\HttpFoundation;
|
||||
*/
|
||||
class HeaderUtils
|
||||
{
|
||||
const DISPOSITION_ATTACHMENT = 'attachment';
|
||||
const DISPOSITION_INLINE = 'inline';
|
||||
|
||||
/**
|
||||
* This class should not be instantiated.
|
||||
*/
|
||||
@ -143,6 +146,54 @@ class HeaderUtils
|
||||
return preg_replace('/\\\\(.)|"/', '$1', $s);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a HTTP Content-Disposition field-value.
|
||||
*
|
||||
* @param string $disposition One of "inline" or "attachment"
|
||||
* @param string $filename A unicode string
|
||||
* @param string $filenameFallback A string containing only ASCII characters that
|
||||
* is semantically equivalent to $filename. If the filename is already ASCII,
|
||||
* it can be omitted, or just copied from $filename
|
||||
*
|
||||
* @return string A string suitable for use as a Content-Disposition field-value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see RFC 6266
|
||||
*/
|
||||
public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string
|
||||
{
|
||||
if (!\in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
|
||||
throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
|
||||
}
|
||||
|
||||
if ('' === $filenameFallback) {
|
||||
$filenameFallback = $filename;
|
||||
}
|
||||
|
||||
// filenameFallback is not ASCII.
|
||||
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
|
||||
throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
|
||||
}
|
||||
|
||||
// percent characters aren't safe in fallback.
|
||||
if (false !== strpos($filenameFallback, '%')) {
|
||||
throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
|
||||
}
|
||||
|
||||
// path separators aren't allowed in either.
|
||||
if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
|
||||
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||
}
|
||||
|
||||
$params = array('filename' => $filenameFallback);
|
||||
if ($filename !== $filenameFallback) {
|
||||
$params['filename*'] = "utf-8''".rawurlencode($filename);
|
||||
}
|
||||
|
||||
return $disposition.'; '.self::toString($params, ';');
|
||||
}
|
||||
|
||||
private static function groupParts(array $matches, string $separators): array
|
||||
{
|
||||
$separator = $separators[0];
|
||||
|
@ -251,51 +251,11 @@ class ResponseHeaderBag extends HeaderBag
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a HTTP Content-Disposition field-value.
|
||||
*
|
||||
* @param string $disposition One of "inline" or "attachment"
|
||||
* @param string $filename A unicode string
|
||||
* @param string $filenameFallback A string containing only ASCII characters that
|
||||
* is semantically equivalent to $filename. If the filename is already ASCII,
|
||||
* it can be omitted, or just copied from $filename
|
||||
*
|
||||
* @return string A string suitable for use as a Content-Disposition field-value
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
*
|
||||
* @see RFC 6266
|
||||
* @see HeaderUtils::makeDisposition()
|
||||
*/
|
||||
public function makeDisposition($disposition, $filename, $filenameFallback = '')
|
||||
{
|
||||
if (!\in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) {
|
||||
throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE));
|
||||
}
|
||||
|
||||
if ('' == $filenameFallback) {
|
||||
$filenameFallback = $filename;
|
||||
}
|
||||
|
||||
// filenameFallback is not ASCII.
|
||||
if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) {
|
||||
throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.');
|
||||
}
|
||||
|
||||
// percent characters aren't safe in fallback.
|
||||
if (false !== strpos($filenameFallback, '%')) {
|
||||
throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.');
|
||||
}
|
||||
|
||||
// path separators aren't allowed in either.
|
||||
if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) {
|
||||
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||
}
|
||||
|
||||
$params = array('filename' => $filenameFallback);
|
||||
if ($filename !== $filenameFallback) {
|
||||
$params['filename*'] = "utf-8''".rawurlencode($filename);
|
||||
}
|
||||
|
||||
return $disposition.'; '.HeaderUtils::toString($params, ';');
|
||||
return HeaderUtils::makeDisposition((string) $disposition, (string) $filename, (string) $filenameFallback);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,4 +82,53 @@ class HeaderUtilsTest extends TestCase
|
||||
$this->assertEquals('foo "bar"', HeaderUtils::unquote('"foo \"\b\a\r\""'));
|
||||
$this->assertEquals('foo \\ bar', HeaderUtils::unquote('"foo \\\\ bar"'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionInvalidDisposition()
|
||||
{
|
||||
HeaderUtils::makeDisposition('invalid', 'foo.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDisposition
|
||||
*/
|
||||
public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
|
||||
{
|
||||
$this->assertEquals($expected, HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback));
|
||||
}
|
||||
|
||||
public function provideMakeDisposition()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo.html', 'foo.html', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo.html', '', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'),
|
||||
array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'),
|
||||
array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'),
|
||||
array('attachment', 'föö.html', 'foo.html', 'attachment; filename=foo.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDispositionFail
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionFail($disposition, $filename)
|
||||
{
|
||||
HeaderUtils::makeDisposition($disposition, $filename);
|
||||
}
|
||||
|
||||
public function provideMakeDispositionFail()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo%20bar.html'),
|
||||
array('attachment', 'foo/bar.html'),
|
||||
array('attachment', '/foo.html'),
|
||||
array('attachment', 'foo\bar.html'),
|
||||
array('attachment', '\foo.html'),
|
||||
array('attachment', 'föö.html'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -250,26 +250,6 @@ class ResponseHeaderBagTest extends TestCase
|
||||
$bag->getCookies('invalid_argument');
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionInvalidDisposition()
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$headers->makeDisposition('invalid', 'foo.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDisposition
|
||||
*/
|
||||
public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback));
|
||||
}
|
||||
|
||||
public function testToStringDoesntMessUpHeaders()
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
@ -284,41 +264,6 @@ class ResponseHeaderBagTest extends TestCase
|
||||
$this->assertEquals(array('text/html'), $allHeaders['Content-type']);
|
||||
}
|
||||
|
||||
public function provideMakeDisposition()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo.html', 'foo.html', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo.html', '', 'attachment; filename=foo.html'),
|
||||
array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'),
|
||||
array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'),
|
||||
array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'),
|
||||
array('attachment', 'föö.html', 'foo.html', 'attachment; filename=foo.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider provideMakeDispositionFail
|
||||
* @expectedException \InvalidArgumentException
|
||||
*/
|
||||
public function testMakeDispositionFail($disposition, $filename)
|
||||
{
|
||||
$headers = new ResponseHeaderBag();
|
||||
|
||||
$headers->makeDisposition($disposition, $filename);
|
||||
}
|
||||
|
||||
public function provideMakeDispositionFail()
|
||||
{
|
||||
return array(
|
||||
array('attachment', 'foo%20bar.html'),
|
||||
array('attachment', 'foo/bar.html'),
|
||||
array('attachment', '/foo.html'),
|
||||
array('attachment', 'foo\bar.html'),
|
||||
array('attachment', '\foo.html'),
|
||||
array('attachment', 'föö.html'),
|
||||
);
|
||||
}
|
||||
|
||||
public function testDateHeaderAddedOnCreation()
|
||||
{
|
||||
$now = time();
|
||||
|
Reference in New Issue
Block a user