/** * @param array $opts Additional options: * - eol: (boolean) If true, normalize EOLs in input. @since 2.2.0 * - skipscan: (boolean) If true, don't scan input for * binary/literal/quoted data. @since 2.2.0 */ public function __construct($data, array $opts = array()) { /* String data is stored in a stream. */ $this->_data = new Horde_Stream_Temp(); $this->_filter = $this->_filterParams(); if (empty($opts['skipscan'])) { stream_filter_register('horde_imap_client_string', 'Horde_Imap_Client_Data_Format_Filter_String'); $res = stream_filter_append($this->_data->stream, 'horde_imap_client_string', STREAM_FILTER_WRITE, $this->_filter); } else { $res = null; } if (empty($opts['eol'])) { $res2 = null; } else { stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); $res2 = stream_filter_append($this->_data->stream, 'horde_eol', STREAM_FILTER_WRITE); } $this->_data->add($data); if (!is_null($res)) { stream_filter_remove($res); } if (!is_null($res2)) { stream_filter_remove($res2); } }
public function testCrc32() { $filter = stream_filter_prepend($this->fp, 'horde_bin2hex', STREAM_FILTER_READ); rewind($this->fp); $this->assertEquals(bin2hex($this->testdata), stream_get_contents($this->fp)); stream_filter_remove($filter); }
/** * @param array $opts Additional options: * - eol: (boolean) If true, normalize EOLs in input. @since 2.2.0 * - skipscan: (boolean) If true, don't scan input for * binary/literal/quoted data. @since 2.2.0 * * @throws Horde_Imap_Client_Data_Format_Exception */ public function __construct($data, array $opts = array()) { /* String data is stored in a stream. */ $this->_data = new Horde_Stream_Temp(); if (empty($opts['skipscan'])) { $this->_filter = $this->_filterParams(); stream_filter_register('horde_imap_client_string', 'Horde_Imap_Client_Data_Format_Filter_String'); $res = stream_filter_append($this->_data->stream, 'horde_imap_client_string', STREAM_FILTER_WRITE, $this->_filter); } else { $res = null; } if (empty($opts['eol'])) { $res2 = null; } else { stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); $res2 = stream_filter_append($this->_data->stream, 'horde_eol', STREAM_FILTER_WRITE); } $this->_data->add($data); if (!is_null($res)) { stream_filter_remove($res); } if (!is_null($res2)) { stream_filter_remove($res2); } if (isset($this->_filter) && $this->_filter->nonascii && !$this instanceof Horde_Imap_Client_Data_Format_String_Support_Nonascii) { throw new Horde_Imap_Client_Data_Format_Exception('String contains non-ASCII characters.'); } }
protected function doBackup($stream, $tables, $gzip = false) { $db = Am_Di::getInstance()->db; $stream_filter = null; $hash = null; $len = 0; if ($gzip) { $hash = hash_init('crc32b'); // gzip file header fwrite($stream, $this->getGzHeader()); if (!($stream_filter = stream_filter_append($stream, "zlib.deflate", STREAM_FILTER_WRITE, self::COMPRESSION_LEVEL))) { throw new Am_Exception_InternalError("Could not attach gzencode filter to output stream"); } } $this->out($stream, "### aMember Pro " . AM_VERSION . " database backup\n", $len, $hash); $this->out($stream, "### Created: " . date('Y-m-d H:i:s') . "\n", $len, $hash); foreach ($tables as $table) { $this->out($stream, "\n\nDROP TABLE IF EXISTS {$table};\n", $len, $hash); $r = $db->selectRow("SHOW CREATE TABLE {$table}"); $this->out($stream, $r['Create Table'] . ";\n", $len, $hash); $q = $db->queryResultOnly("SELECT * FROM {$table}"); while ($a = $db->fetchRow($q)) { $fields = join(',', array_keys($a)); $values = join(',', array_map(array($db, 'escape'), array_values($a))); $this->out($stream, "INSERT INTO {$table} ({$fields}) VALUES ({$values});\n", $len, $hash); } $db->freeResult($q); } if ($stream_filter) { stream_filter_remove($stream_filter); fwrite($stream, $this->getGzFooter($len, $hash)); } return $stream; }
public function testNull() { $filter = stream_filter_prepend($this->fp, 'horde_null', STREAM_FILTER_READ); rewind($this->fp); $this->assertEquals('abcdefghij', stream_get_contents($this->fp)); stream_filter_remove($filter); }
/** */ public function __construct($data) { /* String data is stored in a stream. */ $this->_data = new Horde_Stream_Temp(); stream_filter_register('horde_imap_client_string', 'Horde_Imap_Client_Data_Format_Filter_String'); $this->_filter = $this->_filterParams(); $res = stream_filter_append($this->_data->stream, 'horde_imap_client_string', STREAM_FILTER_WRITE, $this->_filter); $this->_data->add($data); stream_filter_remove($res); }
public function testCrc32() { $params = new stdClass(); $filter = stream_filter_prepend($this->fp, 'horde_crc32', STREAM_FILTER_READ, $params); rewind($this->fp); while (fread($this->fp, 1024)) { } $this->assertObjectHasAttribute('crc32', $params); $this->assertEquals(crc32($this->testdata), $params->crc32); stream_filter_remove($filter); }
function test_64166($data) { $fd = fopen('php://temp', 'w+'); fwrite($fd, $data); rewind($fd); $res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array('line-break-chars' => "\n", 'line-length' => 74)); var_dump(stream_get_contents($fd, -1, 0)); stream_filter_remove($res); rewind($fd); stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array('line-break-chars' => "\n", 'line-length' => 6)); var_dump(stream_get_contents($fd, -1, 0)); fclose($fd); }
/** * Close this buffer. Flushes this buffer and then calls the close() * method on the underlying OuputStream. * */ public function close() { if (!$this->out) { return; } // Remove deflating filter so we can continue writing "raw" stream_filter_remove($this->filter); // Write GZIP footer: // * CRC32 (CRC-32 checksum) // * ISIZE (Input size) fwrite($this->out, pack('VV', create(new CRC32($this->md->digest()))->asInt32(), $this->length)); fclose($this->out); $this->out = NULL; }
/** * Close this buffer. Flushes this buffer and then calls the close() * method on the underlying OuputStream. * */ public function close() { if (!$this->out) { return; } // Remove deflating filter so we can continue writing "raw" stream_filter_remove($this->filter); $final = hash_final($this->md, true); // Write GZIP footer: // * CRC32 (CRC-32 checksum) // * ISIZE (Input size) fwrite($this->out, pack('aaaaV', $final[3], $final[2], $final[1], $final[0], $this->length)); fclose($this->out); $this->out = null; $this->md = null; }
public function getReadFilehandle() { if (!$this->final_read_fh) { $this->flushBuffer(); stream_filter_remove($this->gz_filter); $crc = hash_final($this->file_hash, TRUE); // hash_final is a string, not an integer fwrite($this->__fh, $crc[3] . $crc[2] . $crc[1] . $crc[0]); // need to reverse the hash_final string so it's little endian fwrite($this->__fh, pack("V", $this->uncompressed_bytes), 4); $this->filesize = ftell($this->__fh); rewind($this->__fh); $this->final_read_fh = $this->__fh; } return $this->final_read_fh; }
function main() { $fname = tempnam('/tmp', 'foo'); stream_filter_register('ClosingFilter', 'ClosingFilter'); $f = fopen($fname, 'r+'); $filter = stream_filter_append($f, 'ClosingFilter', STREAM_FILTER_WRITE); fwrite($f, 'foo bar'); fwrite($f, 'herp derp'); var_dump('written, removing'); stream_filter_remove($filter); var_dump('removed'); fwrite($f, 'post filter'); fclose($f); var_dump(file_get_contents($fname)); unlink($fname); }
function main() { stream_filter_register('Foo', 'Foo'); stream_filter_register('Bar', 'Bar'); $f = fopen('php://memory', 'r+'); $filter = stream_filter_append($f, 'Foo', STREAM_FILTER_WRITE); fwrite($f, 'herp'); stream_filter_remove($filter); rewind($f); var_dump(fread($f, 1024)); $f = fopen('php://memory', 'r+'); $filter = stream_filter_append($f, 'Bar', STREAM_FILTER_WRITE); fwrite($f, 'herp'); stream_filter_remove($filter); rewind($f); var_dump(fread($f, 1024)); }
function main() { $fname = tempnam('/tmp', 'foo'); $in = 'herpderp'; // Build a large blob that's hard to compress for ($i = 0; $i < 1000; ++$i) { $in .= md5($in); } var_dump('input md5: ' . md5($in)); $f = fopen($fname, 'r+'); $filter = stream_filter_append($f, 'zlib.deflate', STREAM_FILTER_WRITE); foreach (str_split($in, 8096) as $chunk) { fwrite($f, $chunk); } stream_filter_remove($filter); var_dump('deflated size: ' . fstat($f)['size']); fclose($f); $contents = file_get_contents($fname); var_dump('deflated contents: ' . md5($contents)); $f = fopen($fname, 'r+'); $filter = stream_filter_append($f, 'zlib.inflate', STREAM_FILTER_WRITE); foreach (str_split($contents, 8096) as $chunk) { var_dump('chunk write: ' . strlen($chunk)); fwrite($f, $chunk); } stream_filter_remove($filter); var_dump('stream size: ' . fstat($f)['size']); rewind($f); var_dump('inflated stream size: ' . fstat($f)['size']); var_dump('inflated stream md5: ' . md5(fread($f, fstat($f)['size']))); fclose($f); var_dump('inflated file size: ' . stat($fname)['size']); var_dump('inflated file md5: ' . md5(file_get_contents($fname))); unlink($fname); /* Handy for debugging - should match. Commented out as it's HHVM-only. $inflator = new __SystemLib\ChunkedInflator(); $output = ''; foreach (str_split($contents, 8096) as $chunk) { $output .= $inflator->inflateChunk($chunk); } var_dump('chunkedinflator size: '.strlen($output)); var_dump('chunkedinflator md5: '.md5($output)); */ }
function test_64166($data) { $fd = fopen('php://temp', 'w+'); fwrite($fd, $data); rewind($fd); $res = stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array('line-break-chars' => "\n", 'line-length' => 74)); $str = ""; while (($c = fread($fd, 1)) != "") { $str .= $c; } var_dump($str); stream_filter_remove($res); rewind($fd); stream_filter_append($fd, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array('line-break-chars' => "\n", 'line-length' => 6)); $str = ""; while (($c = fread($fd, 1)) != "") { $str .= $c; } var_dump($str); fclose($fd); }
/** * Checks if the data needs to be encoded like e.g., when outputing binary * data in-line during ITEMOPERATIONS requests. * * @param mixed $data The data to check. A string or stream resource. * @param string $tag The tag we are outputing. * * @return mixed The encoded data. A string or stream resource with * a filter attached. */ protected function _checkEncoding($data, $tag) { if ($tag == Horde_ActiveSync_Request_ItemOperations::ITEMOPERATIONS_DATA) { // See Bug: 14086. Use a STREAM_FILTER_WRITE and perform the // filtering here instead of using the currently broken behavior of // PHP when using base64-encode as STREAM_FILTER_READ. feof() is // apparently not safe to use when using STREAM_FILTER_READ. if (is_resource($data)) { $temp = fopen('php://temp/', 'r+'); $filter = stream_filter_prepend($temp, 'convert.base64-encode', STREAM_FILTER_WRITE); rewind($data); while (!feof($data)) { fwrite($temp, fread($data, 8192)); } stream_filter_remove($filter); rewind($temp); return $temp; } else { return base64_encode($data); } } return $data; }
public function EncodeQP($string, $line_max = 76, $space_conv = false) { if (function_exists('quoted_printable_encode')) { return quoted_printable_encode($string); } $filters = stream_get_filters(); if (!in_array('convert.*', $filters)) { return $this->EncodeQPphp($string, $line_max, $space_conv); } $fp = fopen('php://temp/', 'r+'); $string = preg_replace('/\\r\\n?/', $this->LE, $string); $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); fputs($fp, $string); rewind($fp); $out = stream_get_contents($fp); stream_filter_remove($s); $out = preg_replace('/^\\./m', '=2E', $out); fclose($fp); return $out; }
/** * Validate the body data to ensure consistent EOL and UTF8 data. Returns * body data in a stream object. * * @param array $data The body data. @see self::_bodyPartText() for * structure. * * @return array The validated body data array. @see self::_bodyPartText() */ protected function _validateBodyData(&$data) { $stream = new Horde_Stream_Temp(array('max_memory' => 1048576)); $filter_h = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE); $stream->add(Horde_ActiveSync_Utils::ensureUtf8($data['body'], $data['charset']), true); stream_filter_remove($filter_h); $data['body'] = $stream; }
/** * Remove a filter * * @param string $filter The name of the filter * @return bool Returns TRUE if the filter was detached, FALSE otherwise */ public function removeFilter($filter) { $result = false; if (!is_resource($filter) && isset($this->_filters[$filter])) { $filter = $this->_filters[$filter]; } if (is_resource($filter)) { $result = stream_filter_remove($filter); } return $result; }
/** * if this was created with a stream, return a filtered stream for * reading the content. very useful for large file attachments. * * @param string $EOL * @return stream * @throws Exception\RuntimeException if not a stream or unable to append filter */ public function getEncodedStream($EOL = Mime::LINEEND) { if (!$this->isStream) { throw new Exception\RuntimeException('Attempt to get a stream from a string part'); } //stream_filter_remove(); // ??? is that right? switch ($this->encoding) { case Mime::ENCODING_QUOTEDPRINTABLE: if (array_key_exists(Mime::ENCODING_QUOTEDPRINTABLE, $this->filters)) { stream_filter_remove($this->filters[Mime::ENCODING_QUOTEDPRINTABLE]); } $filter = stream_filter_append($this->content, 'convert.quoted-printable-encode', STREAM_FILTER_READ, array('line-length' => 76, 'line-break-chars' => $EOL)); $this->filters[Mime::ENCODING_QUOTEDPRINTABLE] = $filter; if (!is_resource($filter)) { throw new Exception\RuntimeException('Failed to append quoted-printable filter'); } break; case Mime::ENCODING_BASE64: if (array_key_exists(Mime::ENCODING_BASE64, $this->filters)) { stream_filter_remove($this->filters[Mime::ENCODING_BASE64]); } $filter = stream_filter_append($this->content, 'convert.base64-encode', STREAM_FILTER_READ, array('line-length' => 76, 'line-break-chars' => $EOL)); $this->filters[Mime::ENCODING_BASE64] = $filter; if (!is_resource($filter)) { throw new Exception\RuntimeException('Failed to append base64 filter'); } break; default: } return $this->content; }
/** * Remove a filter, either by resource (handed out from the append or prepend function) * or via getting the filter list) * * @param resource &$resource The resource. * @param boolean $byindex The index of the filter. * * @return boolean Result of operation * * @since 11.1 */ public function removeFilter(&$resource, $byindex = false) { $res = false; // Capture PHP errors $php_errormsg = ''; $track_errors = ini_get('track_errors'); ini_set('track_errors', true); if ($byindex) { $res = stream_filter_remove($this->filters[$resource]); } else { $res = stream_filter_remove($resource); } if ($res && $php_errormsg) { $this->setError($php_errormsg); } // Restore error tracking to what it was before. ini_set('track_errors', $track_errors); return $res; }
private function createResponse(TransactionInterface $transaction) { $errorNo = null; $errorMsg = null; $request = $transaction->getRequest(); $config = $request->getConfig(); if (isset($config['stream']) && $config['stream']) { $request->setHeader('Transfer-Encoding', 'chunked'); } elseif ($request->getBody() !== null) { $request->setHeader('Content-Length', $request->getBody()->getSize()); } $socket = @stream_socket_client($this->entrypoint, $errorNo, $errorMsg, $this->getDefaultTimeout($transaction), STREAM_CLIENT_CONNECT, $this->context); if (!$socket) { throw new RequestException(sprintf('Cannot open socket connection: %s [code %d] [%s]', $errorMsg, $errorNo, $this->entrypoint), $request); } // Check if tls is needed if ($this->useTls) { if (!@stream_socket_enable_crypto($socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { throw new RequestException(sprintf('Cannot enable tls: %s', error_get_last()['message']), $request); } } // Write headers $isWrite = $this->fwrite($socket, $this->getRequestHeaderAsString($request)); // Write body if set if ($request->getBody() !== null && $isWrite !== false) { $stream = $request->getBody(); $filter = null; if ($request->getHeader('Transfer-Encoding') == 'chunked') { $filter = stream_filter_prepend($socket, 'chunk', STREAM_FILTER_WRITE); } while (!$stream->eof() && $isWrite) { $isWrite = $this->fwrite($socket, $stream->read(self::CHUNK_SIZE)); } if ($request->getHeader('Transfer-Encoding') == 'chunked') { stream_filter_remove($filter); if (false !== $isWrite) { $isWrite = $this->fwrite($socket, "0\r\n\r\n"); } } } stream_set_timeout($socket, $this->getDefaultTimeout($transaction)); // Response should be available, extract headers do { $response = $this->getResponseWithHeaders($socket); } while ($response !== null && $response->getStatusCode() == 100); // Check timeout $metadata = stream_get_meta_data($socket); if ($metadata['timed_out']) { throw new RequestException('Timed out while reading socket', $request, $response); } if (false === $isWrite) { // When an error happen and no response it is most probably due to TLS configuration if ($response === null) { throw new RequestException('Error while sending request (Broken Pipe), check your TLS configuration and logs in docker daemon for more information ', $request); } throw new RequestException('Error while sending request (Broken Pipe)', $request, $response); } if (null == $response) { throw new RequestException('No response could be parsed: check server log', $request); } $this->setResponseStream($response, $socket, $request->getEmitter(), $config->hasKey('attach_filter') && $config->get('attach_filter')); $transaction->setResponse($response); // If wait read all contents if ($config->hasKey('wait') && $config->get('wait')) { $response->getBody()->getContents(); } return $response; }
/** * Prepares append message data for insertion into the IMAP command * string. * * @param mixed $data Either a resource or a string. * * @param Horde_Stream A stream containing the data. */ protected function _appendData($data) { $stream = new Horde_Stream_Temp(); stream_filter_register('horde_eol', 'Horde_Stream_Filter_Eol'); $res = stream_filter_append($stream->stream, 'horde_eol', STREAM_FILTER_WRITE); if (is_resource($data)) { rewind($data); } $stream->add($data, true); $this->_temp['appendsize'] += $stream->length(); stream_filter_remove($res); return $stream; }
function sgremove($filter) { if (@stream_filter_remove($filter) === false) { throw new RuntimeException('Unable to remove given filter'); } }
protected function handleCompression($filter, $offsetStart = 0) { if (!$this->isReadable() || $this->isConsumed() && !$this->isSeekable()) { return false; } $handle = fopen('php://temp', 'r+'); $filter = @stream_filter_append($handle, $filter, STREAM_FILTER_WRITE); if (!$filter) { return false; } $this->seek($offsetStart); while ($data = fread($this->stream, 8096)) { fwrite($handle, $data); } fclose($this->stream); $this->stream = $handle; stream_filter_remove($filter); $stat = fstat($this->stream); $this->size = $stat['size']; $this->rebuildCache(); $this->seek(0); $this->rewindFunction = null; return true; }
/** * Uses iconv to convert a stream from one charset to another. * * @param string $inCharset The charset of the stream. * @param string $outCharset The desired resulting charset. * @param resource $stream The stream to convert. The stream is assumed * to be seekable, and is read from its current position to its end, * after which, it is seeked back to its starting position. * * @return resource A new stream that uses the $out_charset. The stream is a * subset from the original stream, from its current position to its * end, seeked at its start. */ public static function iconvStream($inCharset, $outCharset, $stream) { $bytes = 0; $result = fopen('php://temp', 'r+b'); $iconvFilter = stream_filter_append($result, 'convert.iconv.' . $inCharset . '.' . $outCharset, STREAM_FILTER_WRITE); flock($stream, LOCK_SH); while (!feof($stream)) { $bytes += stream_copy_to_stream($stream, $result, 0xfffff); } fseek($stream, -$bytes, SEEK_CUR); flock($stream, LOCK_UN); stream_filter_remove($iconvFilter); rewind($result); return $result; }
/** * Encode a string or a stream into a base64 string * * @param string or stream $input * * @access public * @return string */ public static function EncodeBase64($input) { if (is_resource($input)) { ZLog::Write(LOGLEVEL_DEBUG, "Utils::EncodeBase64(): is_resource"); if (defined('BUG68532FIXED') && BUG68532FIXED === true) { ZLog::Write(LOGLEVEL_DEBUG, "Utils::EncodeBase64(): BUG68532FIXED"); $stream = $input; } elseif (($meta = stream_get_meta_data($input)) && $meta['stream_type'] === 'STDIO') { ZLog::Write(LOGLEVEL_DEBUG, "Utils::EncodeBase64(): STDIO"); $stream = $input; } else { ZLog::Write(LOGLEVEL_DEBUG, "Utils::EncodeBase64(): else"); //because of bug #68532, we can't work with memory stream, //so we copy input to a tmpfile $stream = tmpfile(); stream_copy_to_stream($input, $stream); fclose($input); rewind($stream); } $base64filter = stream_filter_append($stream, 'convert.base64-encode'); $base64 = stream_get_contents($stream); stream_filter_remove($base64filter); fclose($stream); return $base64; } elseif (is_string($input)) { ZLog::Write(LOGLEVEL_DEBUG, "Utils::EncodeBase64(): is_string"); return base64_encode($input); } else { throw new Exception("unsupported type : " . gettype($input)); } }
/** * Inflate deflated data from open file stream. * * PHP is buggy and currently (as of 5.6) requires the use of fseek() to * reset the internal buffer so that a stream filter can be applied so this * workaround is implemented. * * @param resource $fh Open file handle. * @param int $num Number of uncompressed bytes to read. * @return type */ static function inflateStream($fh, $num) { fseek($fh, ftell($fh)); // avoid bug in PHP stream buffering when applying a filter $filter = stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15]); $ret = fread($fh, $num); stream_filter_remove($filter); return $ret; }
/** * Encode string to RFC2045 (6.7) quoted-printable format * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version * Also results in same content as you started with after decoding * @see EncodeQPphp() * @access public * @param string $string the text to encode * @param integer $line_max Number of chars allowed on a line before wrapping * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function * @return string * @author Marcus Bointon */ public function EncodeQP($string, $line_max = 76, $space_conv = false) { if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3) return quoted_printable_encode($string); } $filters = stream_get_filters(); if (!in_array('convert.*', $filters)) { //Got convert stream filter? return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation } $fp = fopen('php://temp/', 'r+'); $string = preg_replace('/\\r\\n?/', $this->LE, $string); //Normalise line breaks $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE); $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params); fputs($fp, $string); rewind($fp); $out = stream_get_contents($fp); stream_filter_remove($s); $out = preg_replace('/^\\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange fclose($fp); return $out; }
/** * This function saves the attachment to the exact specified location. * * @param string $path * @return bool */ public function saveAs($path) { $dirName = dirname($path); if (file_exists($path)) { if (!is_writable($path)) { return false; } } elseif (!is_dir($dirName) || !is_writable($dirName)) { return false; } if (($filePointer = fopen($path, 'w')) == false) { return false; } switch ($this->encoding) { case 3: //base64 $streamFilter = stream_filter_append($filePointer, 'convert.base64-decode', STREAM_FILTER_WRITE); break; case 4: //quoted-printable $streamFilter = stream_filter_append($filePointer, 'convert.quoted-printable-decode', STREAM_FILTER_WRITE); break; default: $streamFilter = null; } // Fix an issue causing server to throw an error // See: https://github.com/tedious/Fetch/issues/74 for more details imap_fetchbody($this->imapStream, $this->messageId, $this->partId ?: 1, FT_UID); $result = imap_savebody($this->imapStream, $filePointer, $this->messageId, $this->partId ?: 1, FT_UID); if ($streamFilter) { stream_filter_remove($streamFilter); } fclose($filePointer); return $result; }