From 30a47d9398678197d7d62406ead1dc73ba449cfc Mon Sep 17 00:00:00 2001 From: wurst-hans <56444979+wurst-hans@users.noreply.github.com> Date: Wed, 7 May 2025 14:00:30 +0200 Subject: [PATCH 1/4] Reading whole lines from stream Replaced char-by-char retrieval from stream via fread() with fgets() to get full line from stream until EOF or newline. This speeds up data transfer by factor 10. --- src/Connection/Protocols/ImapProtocol.php | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/Connection/Protocols/ImapProtocol.php b/src/Connection/Protocols/ImapProtocol.php index ed1dac6e..6871d57f 100644 --- a/src/Connection/Protocols/ImapProtocol.php +++ b/src/Connection/Protocols/ImapProtocol.php @@ -135,14 +135,10 @@ protected function enableStartTls(): void { * @throws RuntimeException */ public function nextLine(Response $response): string { - $line = ""; - while (($next_char = fread($this->stream, 1)) !== false && !in_array($next_char, ["", "\n"])) { - $line .= $next_char; - } - if ($line === "" && ($next_char === false || $next_char === "")) { + $line = fgets($this->stream); + if ($line === false || $line === '') { throw new RuntimeException('empty response'); } - $line .= "\n"; $response->addResponse($line); if ($this->debug) echo "<< " . $line; return $line; From 48ec7f7f458c4ecf0a94da3c632db7e878a960a9 Mon Sep 17 00:00:00 2001 From: wurst-hans <56444979+wurst-hans@users.noreply.github.com> Date: Wed, 7 May 2025 20:05:28 +0200 Subject: [PATCH 2/4] Recursive handling of stdClass in response For example, calling overview() on a folder using LegacyProcotol (i.e. POP3) can result in error "Object of class stdClass could not be converted to string", because response might contain stdClass object which is not yet handled recursively by verify_data(). --- src/Connection/Protocols/Response.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Connection/Protocols/Response.php b/src/Connection/Protocols/Response.php index 9a30d56d..8650b90c 100644 --- a/src/Connection/Protocols/Response.php +++ b/src/Connection/Protocols/Response.php @@ -13,6 +13,7 @@ namespace Webklex\PHPIMAP\Connection\Protocols; +use stdClass; use Webklex\PHPIMAP\Exceptions\ResponseException; /** @@ -347,7 +348,7 @@ public function successful(): bool { * @return bool */ public function verify_data(mixed $data): bool { - if (is_array($data)) { + if (is_array($data) || $data instanceof stdClass) { foreach ($data as $line) { if (is_array($line)) { if(!$this->verify_data($line)){ @@ -414,4 +415,4 @@ public function setCanBeEmpty(bool $can_be_empty): Response { public function canBeEmpty(): bool { return $this->can_be_empty; } -} \ No newline at end of file +} From b8d5ef3555c9e2278c5c47ff1f79859a137c0409 Mon Sep 17 00:00:00 2001 From: wurst-hans <56444979+wurst-hans@users.noreply.github.com> Date: Wed, 7 May 2025 22:18:45 +0200 Subject: [PATCH 3/4] Fixed MIME header decoding without IMAP extension When IMAP C-extension for PHP is missing, MIME-encoded header fields aren't decoded correctly. --- src/Decoder/HeaderDecoder.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Decoder/HeaderDecoder.php b/src/Decoder/HeaderDecoder.php index 9a8a71b2..3355aef4 100644 --- a/src/Decoder/HeaderDecoder.php +++ b/src/Decoder/HeaderDecoder.php @@ -29,7 +29,9 @@ public function decode(array|string|null $value, ?string $encoding = null): mixe $decoder = $this->options['header']; if ($value !== null) { - if ($decoder === 'utf-8') { + if (self::isUTF8($value)) { + $value = mb_decode_mimeheader($value); + } else if ($decoder === 'utf-8') { $decoded_values = $this->mimeHeaderDecode($value); $tempValue = ""; foreach ($decoded_values as $decoded_value) { @@ -46,8 +48,6 @@ public function decode(array|string|null $value, ?string $encoding = null): mixe } } elseif ($decoder === 'iconv') { $value = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8"); - } else if (self::isUTF8($value)) { - $value = mb_decode_mimeheader($value); } if (self::notDecoded($original_value, $value)) { @@ -95,4 +95,4 @@ private function decodeHeaderArray(array $values): array { return $values; } -} \ No newline at end of file +} From c0c9826821d215787a73df9143275bed62748493 Mon Sep 17 00:00:00 2001 From: wurst-hans <56444979+wurst-hans@users.noreply.github.com> Date: Wed, 7 May 2025 22:21:42 +0200 Subject: [PATCH 4/4] Reverted last commit Have to investigate first, why tests fail --- src/Decoder/HeaderDecoder.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Decoder/HeaderDecoder.php b/src/Decoder/HeaderDecoder.php index 3355aef4..aad5ed5b 100644 --- a/src/Decoder/HeaderDecoder.php +++ b/src/Decoder/HeaderDecoder.php @@ -29,9 +29,7 @@ public function decode(array|string|null $value, ?string $encoding = null): mixe $decoder = $this->options['header']; if ($value !== null) { - if (self::isUTF8($value)) { - $value = mb_decode_mimeheader($value); - } else if ($decoder === 'utf-8') { + if ($decoder === 'utf-8') { $decoded_values = $this->mimeHeaderDecode($value); $tempValue = ""; foreach ($decoded_values as $decoded_value) { @@ -48,6 +46,8 @@ public function decode(array|string|null $value, ?string $encoding = null): mixe } } elseif ($decoder === 'iconv') { $value = iconv_mime_decode($value, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, "UTF-8"); + } else if (self::isUTF8($value)) { + $value = mb_decode_mimeheader($value); } if (self::notDecoded($original_value, $value)) {