diff --git a/src/MultibyteStringStream.php b/src/MultibyteStringStream.php index 75eda94..48abf98 100644 --- a/src/MultibyteStringStream.php +++ b/src/MultibyteStringStream.php @@ -58,19 +58,23 @@ public function onClose() { } public function filter($in, $out, &$consumed, $closing) { - $buffer = &$this->buffer; + $buffer = &$this->buffer; + $pass_on = false; while ($bucket = stream_bucket_make_writeable($in)) { $encoded_data = $buffer . $bucket->data; $valid_chars = $this->truncateInvalidCharacters($encoded_data); $buffer = substr($encoded_data, strlen($valid_chars)); - $decoded_data = $this->convert($valid_chars, $this->to_encoding); + $consumed += $bucket->datalen; - $bucket->data = $decoded_data; - $consumed = $consumed + $bucket->datalen; + if (!empty($valid_chars)) { + $bucket->data = $this->convert($valid_chars, $this->to_encoding); - stream_bucket_append($out, $bucket); + stream_bucket_append($out, $bucket); + + $pass_on = true; + } } if ($closing && !empty($buffer)) { @@ -82,13 +86,11 @@ public function filter($in, $out, &$consumed, $closing) { $buffer = ''; stream_bucket_append($out, $bucket); - } - if (!empty($buffer)) { - return PSFS_FEED_ME; + $pass_on = true; } - return PSFS_PASS_ON; + return $pass_on ? PSFS_PASS_ON : PSFS_FEED_ME; } private function truncateInvalidCharacters($data) { diff --git a/tests/MultibyteStringStreamTest.php b/tests/MultibyteStringStreamTest.php index 0f69f59..bc451db 100644 --- a/tests/MultibyteStringStreamTest.php +++ b/tests/MultibyteStringStreamTest.php @@ -118,6 +118,30 @@ public function testMultibyteEdgeHandling() { ); } + public function testMultibyteEdgeHandlingAfterBucketWrite() { + $output = fopen('php://memory', 'w+'); + $filtername = 'convert.mbstring.UTF-8/UTF-8'; + + stream_filter_append($output, $filtername, STREAM_FILTER_WRITE); + + $bucket_data = str_pad('', 128, 'abc'); + $malformed_data = substr("🍩", 0, 2); + + fwrite($output, $bucket_data . $malformed_data); + fflush($output); + + rewind($output); + + $expected = $bucket_data; + $result = stream_get_contents($output); + + $this->assertSame( + $expected, + $result, + 'Failed to preserve valid data' + ); + } + public function testCloseInvalidData() { $output = fopen('php://output', 'w'); $filtername = 'convert.mbstring.UTF-8/UTF-8';