From: Michael M Slusarz Date: Fri, 19 Nov 2010 21:36:36 +0000 (-0700) Subject: Bug #8747: Add workaround for borken PHP quoted-printable decoding X-Git-Url: https://git.internetallee.de/?a=commitdiff_plain;h=48370ce4d8dfbacf3c92b29a4d401c78187c13a6;p=horde.git Bug #8747: Add workaround for borken PHP quoted-printable decoding --- diff --git a/framework/Mime/lib/Horde/Mime/Part.php b/framework/Mime/lib/Horde/Mime/Part.php index 3d8f152f8..80d675e51 100644 --- a/framework/Mime/lib/Horde/Mime/Part.php +++ b/framework/Mime/lib/Horde/Mime/Part.php @@ -449,10 +449,26 @@ class Horde_Mime_Part implements ArrayAccess, Countable if (ftell($fp)) { switch ($encoding) { case 'base64': - return $this->_writeStream($fp, array('filter' => 'convert.base64-decode')); + return $this->_writeStream($fp, array( + 'filter' => array( + 'convert.base64-decode' => array() + ) + )); case 'quoted-printable': - return $this->_writeStream($fp, array('filter' => 'convert.quoted-printable-decode')); + try { + $stream = $this->_writeStream($fp, array( + 'error' => true, + 'filter' => array( + 'convert.quoted-printable-decode' => array() + ) + )); + } catch (ErrorException $e) { + // Workaround for Horde Bug #8747 + rewind($fp); + $stream = $this->_writeStream(quoted_printable_decode(stream_get_contents($fp))); + } + return $stream; case 'uuencode': case 'x-uuencode': @@ -481,11 +497,25 @@ class Horde_Mime_Part implements ArrayAccess, Countable switch ($encoding) { case 'base64': /* Base64 Encoding: See RFC 2045, section 6.8 */ - return $this->_writeStream($fp, array('filter' => 'convert.base64-encode', 'params' => array('line-length' => 76, 'line-break-chars' => $this->getEOL()))); + return $this->_writeStream($fp, array( + 'filter' => array( + 'convert.base64-encode' => array( + 'line-break-chars' => $this->getEOL(), + 'line-length' => 76 + ) + ) + )); case 'quoted-printable': /* Quoted-Printable Encoding: See RFC 2045, section 6.7 */ - return $this->_writeStream($fp, array('filter' => 'convert.quoted-printable-encode', 'params' => array('line-length' => 76, 'line-break-chars' => $this->getEOL()))); + return $this->_writeStream($fp, array( + 'filter' => array( + 'convert.quoted-printable-encode' => array( + 'line-break-chars' => $this->getEOL(), + 'line-length' => 76 + ) + ) + )); default: $this->_temp['transferEncodeClose'] = false; @@ -1590,12 +1620,16 @@ class Horde_Mime_Part implements ArrayAccess, Countable * a string. * @param array $options Additional options: *
-     * 'filter - (string) A filter to apply to the string.
-     * 'fp' - (resource) Use this stream instead of creating a new one.
-     * 'params' - (array)  Any params needed by the filter.
+     * error - (boolean) Catch errors when writing to the stream. Throw an
+     *         ErrorException if an error is found.
+     *         DEFAULT: false
+     * filter - (array) Filter(s) to apply to the string. Keys are the
+     *          filter names, values are filter params.
+     * fp - (resource) Use this stream instead of creating a new one.
      * 
* * @return resource The stream resource. + * @throws ErrorException */ protected function _writeStream($data, $options = array()) { @@ -1611,32 +1645,66 @@ class Horde_Mime_Part implements ArrayAccess, Countable } if (!empty($options['filter'])) { - $append_filter = stream_filter_append($fp, $options['filter'], STREAM_FILTER_WRITE, empty($options['params']) ? array() : $options['params']); + $append_filter = array(); + foreach ($options['filter'] as $key => $val) { + $append_filter[] = stream_filter_append($fp, $key, STREAM_FILTER_WRITE, $val); + } } - reset($data); - while (list(,$d) = each($data)) { - if (is_resource($d)) { - rewind($d); - stream_copy_to_stream($d, $fp); - } else { - $len = strlen($d); - $i = 0; - while ($i < $len) { - fwrite($fp, substr($d, $i, 8192)); - $i += 8192; + if (!empty($options['error'])) { + set_error_handler(array($this, '_writeStreamErrorHandler')); + $error = null; + } + + try { + reset($data); + while (list(,$d) = each($data)) { + if (is_resource($d)) { + rewind($d); + @stream_copy_to_stream($d, $fp); + } else { + $len = strlen($d); + $i = 0; + while ($i < $len) { + fwrite($fp, substr($d, $i, 8192)); + $i += 8192; + } } } + } catch (ErrorException $e) { + $error = $e; } if (!empty($options['filter'])) { - stream_filter_remove($append_filter); + foreach ($append_filter as $val) { + stream_filter_remove($val); + } + } + + if (!empty($options['error'])) { + restore_error_handler(); + if ($error) { + throw $error; + } } return $fp; } /** + * Error handler for _writeStream(). + * + * @param integer $errno Error code. + * @param string $errstr Error text. + * + * @throws ErrorException + */ + protected function _writeStreamErrorHandler($errno, $errstr) + { + throw new ErrorException($errstr, $errno); + } + + /** * Read data from a stream. * * @param resource $fp An active stream. diff --git a/framework/Mime/package.xml b/framework/Mime/package.xml index 72595d36d..51c74b552 100644 --- a/framework/Mime/package.xml +++ b/framework/Mime/package.xml @@ -27,7 +27,8 @@ alpha LGPL - * Honor the Content-Disposition 'size' parameter (RFC 2183 [2.7]). + * Add workaround for Horde Bug #8747. + * Honor the Content-Disposition 'size' parameter (RFC 2183 [2.7]). * Converted tests to PHPUnit. * Moved viewer code to horde/Mime_Viewer package. * Removed Webcpp and Enscript viewers. Source code highlighting is now