[HttpFoundation] implemented RFC6266 (Content-Disposition header)
references: * http://trac.tools.ietf.org/wg/httpbis/trac/wiki/ContentDispositionProducerAdvice * https://github.com/mnot/sweet/blob/master/lib/index.js * http://www.mnot.net/blog/2011/09/02/rfc6266_and_content-disposition
This commit is contained in:
parent
e7b2d2d659
commit
dccd2d560f
@ -22,6 +22,7 @@ To get the diff between two versions, go to https://github.com/symfony/symfony/c
|
|||||||
|
|
||||||
* added support for the PATCH method in Request
|
* added support for the PATCH method in Request
|
||||||
* removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3
|
* removed the ContentTypeMimeTypeGuesser class as it is deprecated and never used on PHP 5.3
|
||||||
|
* added ResponseHeaderBag::makeDisposition() (implements RFC 6266)
|
||||||
|
|
||||||
### Translation
|
### Translation
|
||||||
|
|
||||||
|
@ -200,6 +200,50 @@ class ResponseHeaderBag extends HeaderBag
|
|||||||
$this->setCookie(new Cookie($name, null, 1, $path, $domain));
|
$this->setCookie(new Cookie($name, null, 1, $path, $domain));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 function makeDisposition($disposition, $filename, $filenameFallback = '')
|
||||||
|
{
|
||||||
|
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 (preg_match('#[/\\\\]#', $filename) || preg_match('#[/\\\\]#', $filenameFallback)) {
|
||||||
|
throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$output = sprintf('%s; filename="%s"', $disposition, str_replace(array('\\', '"'), array('\\\\', '\\"'), $filenameFallback));
|
||||||
|
|
||||||
|
if ($filename != $filenameFallback) {
|
||||||
|
$output .= sprintf("; filename*=utf-8''%s", str_replace(array("'", '(', ')', '*'), array('%27', '%28', '%29', '%2A'), urlencode($filename)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the calculated value of the cache-control header.
|
* Returns the calculated value of the cache-control header.
|
||||||
*
|
*
|
||||||
|
@ -118,4 +118,49 @@ class ResponseHeaderBagTest extends \PHPUnit_Framework_TestCase
|
|||||||
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
$cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY);
|
||||||
$this->assertFalse(isset($cookies['foo.bar']));
|
$this->assertFalse(isset($cookies['foo.bar']));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dataProvider provideMakeDisposition
|
||||||
|
*/
|
||||||
|
public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected)
|
||||||
|
{
|
||||||
|
$headers = new ResponseHeaderBag();
|
||||||
|
|
||||||
|
$this->assertEquals($expected, $headers->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)
|
||||||
|
{
|
||||||
|
$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'),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user