From be9c675710258d031e89c30f8bd38a1ced33bb97 Mon Sep 17 00:00:00 2001 From: Nicolas Grekas Date: Thu, 19 Dec 2019 14:13:36 +0100 Subject: [PATCH] [Mime] strengthen is_resource() checks --- .../Component/Mime/CharacterStream.php | 5 +--- src/Symfony/Component/Mime/Email.php | 26 +++---------------- .../Mime/Encoder/Base64ContentEncoder.php | 5 +--- .../Mime/Encoder/QpContentEncoder.php | 4 --- src/Symfony/Component/Mime/Part/TextPart.php | 12 +++++---- 5 files changed, 13 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Component/Mime/CharacterStream.php b/src/Symfony/Component/Mime/CharacterStream.php index 749066f2a8..9d0a9c6618 100644 --- a/src/Symfony/Component/Mime/CharacterStream.php +++ b/src/Symfony/Component/Mime/CharacterStream.php @@ -97,10 +97,7 @@ final class CharacterStream } } if (\is_resource($input)) { - $blocks = 512; - if (stream_get_meta_data($input)['seekable'] ?? false) { - rewind($input); - } + $blocks = 16372; while (false !== $read = fread($input, $blocks)) { $this->write($read); } diff --git a/src/Symfony/Component/Mime/Email.php b/src/Symfony/Component/Mime/Email.php index fb91262181..e5f9f11b36 100644 --- a/src/Symfony/Component/Mime/Email.php +++ b/src/Symfony/Component/Mime/Email.php @@ -464,14 +464,8 @@ class Email extends Message $htmlPart = null; $html = $this->html; if (null !== $this->html) { - if (\is_resource($html)) { - if (stream_get_meta_data($html)['seekable'] ?? false) { - rewind($html); - } - - $html = stream_get_contents($html); - } $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + $html = $htmlPart->getBody(); preg_match_all('(]*src\s*=\s*(?:([\'"])cid:([^"]+)\\1|cid:([^>\s]+)))i', $html, $names); $names = array_filter(array_unique(array_merge($names[2], $names[3]))); } @@ -559,28 +553,16 @@ class Email extends Message public function __serialize(): array { if (\is_resource($this->text)) { - if (stream_get_meta_data($this->text)['seekable'] ?? false) { - rewind($this->text); - } - - $this->text = stream_get_contents($this->text); + $this->text = (new TextPart($this->text))->getBody(); } if (\is_resource($this->html)) { - if (stream_get_meta_data($this->html)['seekable'] ?? false) { - rewind($this->html); - } - - $this->html = stream_get_contents($this->html); + $this->html = (new TextPart($this->html))->getBody(); } foreach ($this->attachments as $i => $attachment) { if (isset($attachment['body']) && \is_resource($attachment['body'])) { - if (stream_get_meta_data($attachment['body'])['seekable'] ?? false) { - rewind($attachment['body']); - } - - $this->attachments[$i]['body'] = stream_get_contents($attachment['body']); + $this->attachments[$i]['body'] = (new TextPart($attachment['body']))->getBody(); } } diff --git a/src/Symfony/Component/Mime/Encoder/Base64ContentEncoder.php b/src/Symfony/Component/Mime/Encoder/Base64ContentEncoder.php index cb7f911678..881eaab77b 100644 --- a/src/Symfony/Component/Mime/Encoder/Base64ContentEncoder.php +++ b/src/Symfony/Component/Mime/Encoder/Base64ContentEncoder.php @@ -32,11 +32,8 @@ final class Base64ContentEncoder extends Base64Encoder implements ContentEncoder throw new RuntimeException('Unable to set the base64 content encoder to the filter.'); } - if (stream_get_meta_data($stream)['seekable'] ?? false) { - rewind($stream); - } while (!feof($stream)) { - yield fread($stream, 8192); + yield fread($stream, 16372); } stream_filter_remove($filter); } diff --git a/src/Symfony/Component/Mime/Encoder/QpContentEncoder.php b/src/Symfony/Component/Mime/Encoder/QpContentEncoder.php index e0b8605dd2..4703cc2e68 100644 --- a/src/Symfony/Component/Mime/Encoder/QpContentEncoder.php +++ b/src/Symfony/Component/Mime/Encoder/QpContentEncoder.php @@ -23,10 +23,6 @@ final class QpContentEncoder implements ContentEncoderInterface } // we don't use PHP stream filters here as the content should be small enough - if (stream_get_meta_data($stream)['seekable'] ?? false) { - rewind($stream); - } - yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength); } diff --git a/src/Symfony/Component/Mime/Part/TextPart.php b/src/Symfony/Component/Mime/Part/TextPart.php index a41d91ddec..b5c93d526c 100644 --- a/src/Symfony/Component/Mime/Part/TextPart.php +++ b/src/Symfony/Component/Mime/Part/TextPart.php @@ -31,6 +31,7 @@ class TextPart extends AbstractPart private $disposition; private $name; private $encoding; + private $seekable; /** * @param resource|string $body @@ -46,6 +47,7 @@ class TextPart extends AbstractPart $this->body = $body; $this->charset = $charset; $this->subtype = $subtype; + $this->seekable = \is_resource($body) ? stream_get_meta_data($body)['seekable'] && 0 === fseek($body, 0, SEEK_CUR) : null; if (null === $encoding) { $this->encoding = $this->chooseEncoding(); @@ -93,11 +95,11 @@ class TextPart extends AbstractPart public function getBody(): string { - if (!\is_resource($this->body)) { + if (null === $this->seekable) { return $this->body; } - if (stream_get_meta_data($this->body)['seekable'] ?? false) { + if ($this->seekable) { rewind($this->body); } @@ -111,8 +113,8 @@ class TextPart extends AbstractPart public function bodyToIterable(): iterable { - if (\is_resource($this->body)) { - if (stream_get_meta_data($this->body)['seekable'] ?? false) { + if (null !== $this->seekable) { + if ($this->seekable) { rewind($this->body); } yield from $this->getEncoder()->encodeByteStream($this->body); @@ -185,7 +187,7 @@ class TextPart extends AbstractPart public function __sleep() { // convert resources to strings for serialization - if (\is_resource($this->body)) { + if (null !== $this->seekable) { $this->body = $this->getBody(); }