From e88b6f6e1908842a7b6e2f85381acc886e1df9f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elan=20Ruusam=C3=A4e?= Date: Sun, 28 Feb 2021 00:27:48 +0200 Subject: [PATCH] Refactor data reader in Protocol\Smtp to use Generator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This isolates the logic of handling incomplete reads to own unit. Signed-off-by: Elan Ruusamäe --- src/Protocol/Smtp.php | 53 +++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 27 deletions(-) diff --git a/src/Protocol/Smtp.php b/src/Protocol/Smtp.php index e8bbc453..2d8975df 100644 --- a/src/Protocol/Smtp.php +++ b/src/Protocol/Smtp.php @@ -317,41 +317,42 @@ public function data($data) $this->_send('DATA'); $this->_expect(354, 120); // Timeout set for 2 minutes as per RFC 2821 4.5.3.2 - if (($fp = fopen("php://temp", "r+")) === false) { - throw new Exception\RuntimeException('cannot fopen'); - } - if (fwrite($fp, $data) === false) { - throw new Exception\RuntimeException('cannot fwrite'); - } - unset($data); - rewind($fp); + $chunkReader = static function($data, $chunkSize = 4096) { + if (($fp = fopen("php://temp", "r+")) === false) { + throw new Exception\RuntimeException('cannot fopen'); + } + if (fwrite($fp, $data) === false) { + throw new Exception\RuntimeException('cannot fwrite'); + } + rewind($fp); + + $line = null; + while (($buffer = fgets($fp, $chunkSize)) !== false) { + $line .= $buffer; - $chunkSize = 4096; - $line = ''; - while (($buffer = fgets($fp, $chunkSize)) !== false) { - $line .= $buffer; + // partial read, continue loop to read again to complete the line + if (strlen($buffer) === $chunkSize - 1 && $buffer[$chunkSize - 2] !== "\n") { + continue; + } - // partial read, continue loop to read again to complete the line - if (strlen($buffer) === $chunkSize - 1 && $buffer[$chunkSize - 2] !== "\n") { - continue; + yield $line; + $line = null; } + if ($line !== null) { + yield $line; + } + + fclose($fp); + }; + + foreach ($chunkReader($data) as $line) { $line = rtrim($line, "\r\n"); if (isset($line[0]) && $line[0] === '.') { // Escape lines prefixed with a '.' $line = '.' . $line; } - // max line length is 998 char + \r\n = 1000 - if (strlen($line) > 998) { - // Long lines are "folded" by inserting "" - // https://tools.ietf.org/html/rfc5322#section-2.2.3 - $line = substr(chunk_split($line, 998, Headers::FOLDING), 0, -strlen(Headers::FOLDING)); - } - $this->_send($line); - $line = ''; - } - if ($line) { // max line length is 998 char + \r\n = 1000 if (strlen($line) > 998) { // Long lines are "folded" by inserting "" @@ -362,8 +363,6 @@ public function data($data) $this->_send($line); } - fclose($fp); - $this->_send('.'); $this->_expect(250, 600); // Timeout set for 10 minutes as per RFC 2821 4.5.3.2 $this->data = true;