From c04311764fa5f99db04fba2784ceff894d7e1f6a Mon Sep 17 00:00:00 2001 From: TravisCarden Date: Thu, 25 Aug 2016 15:35:28 -0500 Subject: [PATCH 1/2] [HttpFoundation] Fixed BinaryFileResponse sending wrong Content-Length header for files modified by stream wrappers/filters. --- src/Symfony/Component/HttpFoundation/File/File.php | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/Symfony/Component/HttpFoundation/File/File.php b/src/Symfony/Component/HttpFoundation/File/File.php index 4736b45c34839..6e4ae0a6dc0a2 100644 --- a/src/Symfony/Component/HttpFoundation/File/File.php +++ b/src/Symfony/Component/HttpFoundation/File/File.php @@ -133,4 +133,18 @@ protected function getName($name) return $originalName; } + + /** + * {@inheritdoc} + */ + public function getSize() + { + // Since stream wrappers and stream filters can change the file contents as read, the only + // reliable way to get the effective size of the file is to actually read it. + ob_start(); + $size = readfile($this->getPathname()); + ob_end_clean(); + + return $size; + } } From e8a498d356c35fe20f74b7a75c3e016c01649d65 Mon Sep 17 00:00:00 2001 From: TravisCarden Date: Mon, 19 Sep 2016 08:54:36 -0500 Subject: [PATCH 2/2] Unit test in progress... --- .../HttpFoundation/Tests/File/FileTest.php | 16 +++++ .../File/Fixtures/PaddingStreamFilter.php | 21 +++++++ .../File/Fixtures/PaddingStreamWrapper.php | 62 +++++++++++++++++++ 3 files changed, 99 insertions(+) create mode 100644 src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamFilter.php create mode 100644 src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamWrapper.php diff --git a/src/Symfony/Component/HttpFoundation/Tests/File/FileTest.php b/src/Symfony/Component/HttpFoundation/Tests/File/FileTest.php index a92f5728846e1..cf55ca2e18a57 100644 --- a/src/Symfony/Component/HttpFoundation/Tests/File/FileTest.php +++ b/src/Symfony/Component/HttpFoundation/Tests/File/FileTest.php @@ -13,6 +13,7 @@ use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; +use Symfony\Component\HttpFoundation\File\Tests\Fixtures\PaddingStreamWrapper; class FileTest extends \PHPUnit_Framework_TestCase { @@ -28,6 +29,21 @@ public function testGetMimeTypeUsesMimeTypeGuessers() $this->assertEquals('image/gif', $file->getMimeType()); } + public function testGetSizeWithStreamFilter() + { + // @todo Where should these fixture classes go so this isn't necessary? + require_once 'Fixtures/PaddingStreamWrapper.php'; + require_once 'Fixtures/PaddingStreamFilter.php'; + + stream_wrapper_register('pad', '\Symfony\Component\HttpFoundation\File\Tests\Fixtures\PaddingStreamWrapper'); + $path = 'pad://test'; + + $filtered_contents = file_get_contents($path); + $file = new File($path); + + $this->assertEquals(strlen($filtered_contents), $file->getSize()); + } + public function testGuessExtensionWithoutGuesser() { $file = new File(__DIR__.'/Fixtures/directory/.empty'); diff --git a/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamFilter.php b/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamFilter.php new file mode 100644 index 0000000000000..ffae2b91d4fbf --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamFilter.php @@ -0,0 +1,21 @@ +data .= self::PADDING; + $consumed += $bucket->datalen; + stream_bucket_append($out, $bucket); + } + + return PSFS_PASS_ON; + } +} diff --git a/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamWrapper.php b/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamWrapper.php new file mode 100644 index 0000000000000..7cd1071525141 --- /dev/null +++ b/src/Symfony/Component/HttpFoundation/Tests/File/Fixtures/PaddingStreamWrapper.php @@ -0,0 +1,62 @@ +file = fopen('php://temp', 'r+'); + + $path_parts = explode('://', $path); + $file_contents = end($path_parts); + fwrite($this->file, $file_contents); + fseek($this->file, 0); + + stream_filter_register(PaddingStreamFilter::NAME, '\Symfony\Component\HttpFoundation\File\Tests\Fixtures\PaddingStreamFilter'); + stream_filter_append($this->file, PaddingStreamFilter::NAME, STREAM_FILTER_READ); + + return (bool) $this->file; + } + + public function stream_read($count) + { + return fread($this->file, $count); + } + + public function stream_write($data) + { + return fwrite($this->file, $data); + } + + public function stream_tell() + { + return ftell($this->file); + } + + public function stream_eof() + { + return feof($this->file); + } + + public function stream_seek($offset, $whence) + { + return fseek($this->file, $offset, $whence); + } + + public function stream_stat() + { + return fstat($this->file); + } + + public function url_stat($path, $flags) + { + $file = fopen($path, 'r'); + $stat = fstat($file); + fclose($file); + + return $stat; + } +}