From 342a75a3e06fb38283aa5339b7f6a197853897a2 Mon Sep 17 00:00:00 2001 From: Maks3w Date: Thu, 14 Jun 2012 16:23:45 +0200 Subject: [PATCH] [Mail] Replace wrap mime algorithm with the algorithm provided by Zend\Mime\Mime Replace the splitWords argument with the lineLength --- src/Header/AbstractAddressList.php | 2 +- src/Header/HeaderWrap.php | 48 +++++++----------- src/Header/Sender.php | 2 +- src/Header/Subject.php | 6 +-- test/Header/HeaderWrapTest.php | 79 ++++++++++++++++++++++++++++++ test/MessageTest.php | 31 +++--------- 6 files changed, 106 insertions(+), 62 deletions(-) create mode 100644 test/Header/HeaderWrapTest.php diff --git a/src/Header/AbstractAddressList.php b/src/Header/AbstractAddressList.php index 32316b80..76723ce3 100644 --- a/src/Header/AbstractAddressList.php +++ b/src/Header/AbstractAddressList.php @@ -146,7 +146,7 @@ public function getFieldValue() } if ('ASCII' !== $encoding) { - $name = HeaderWrap::mimeEncodeValue($name, $encoding, false); + $name = HeaderWrap::mimeEncodeValue($name, $encoding); } $emails[] = sprintf('%s <%s>', $name, $email); } diff --git a/src/Header/HeaderWrap.php b/src/Header/HeaderWrap.php index 86f57fb2..7c2dfee9 100644 --- a/src/Header/HeaderWrap.php +++ b/src/Header/HeaderWrap.php @@ -22,6 +22,7 @@ namespace Zend\Mail\Header; use Zend\Mail\Headers; +use Zend\Mime\Mime; /** * Utility class used for creating wrapped or MIME-encoded versions of header @@ -45,7 +46,7 @@ abstract class HeaderWrap public static function wrap($value, HeaderInterface $header) { if ($header instanceof UnstructuredInterface) { - return static::wrapUnstructuredHeader($value); + return static::wrapUnstructuredHeader($value, $header); } elseif ($header instanceof StructuredInterface) { return static::wrapStructuredHeader($value, $header); } @@ -56,23 +57,28 @@ public static function wrap($value, HeaderInterface $header) * Wrap an unstructured header line * * Wrap at 78 characters or before, based on whitespace. - * - * @param string $value + * + * @param string $value + * @param HeaderInterface $header * @return string */ - protected static function wrapUnstructuredHeader($value) + protected static function wrapUnstructuredHeader($value, HeaderInterface $header) { - return wordwrap($value, 78, Headers::FOLDING); + $encoding = $header->getEncoding(); + if ($encoding == 'ASCII') { + return wordwrap($value, 78, Headers::FOLDING); + } + return static::mimeEncodeValue($value, $encoding, 78); } /** * Wrap a structured header line * - * @param string $value - * @param HeaderInterface $header + * @param string $value + * @param StructuredInterface $header * @return string */ - protected static function wrapStructuredHeader($value, HeaderInterface $header) + protected static function wrapStructuredHeader($value, StructuredInterface $header) { $delimiter = $header->getDelimiter(); @@ -97,29 +103,11 @@ protected static function wrapStructuredHeader($value, HeaderInterface $header) * * @param string $value * @param string $encoding - * @param bool $splitWords Whether or not to split the $value on whitespace - * and encode each word separately. - * @return string + * @param int $lineLength maximum line-length, by default 998 + * @return string Returns the mime encode value without the last line ending */ - public static function mimeEncodeValue($value, $encoding, $splitWords = false) + public static function mimeEncodeValue($value, $encoding, $lineLength = 998) { - if ($splitWords) { - $words = array_map(function($word) use ($encoding) { - $header = iconv_mime_encode('Header', $word, array( - 'scheme' => 'Q', - 'line-length' => 78, - 'output-charset' => $encoding, - )); - return str_replace('Header: ', '', $header); - }, explode(' ', $value)); - return implode(Headers::FOLDING, $words); - } - - $header = iconv_mime_encode('Header', $value, array( - 'scheme' => 'Q', - 'line-length' => 998, - 'output-charset' => $encoding, - )); - return str_replace('Header: ', '', $header); + return Mime::encodeQuotedPrintableHeader($value, $encoding, $lineLength, Headers::EOL); } } diff --git a/src/Header/Sender.php b/src/Header/Sender.php index 8629461f..1bbdad82 100644 --- a/src/Header/Sender.php +++ b/src/Header/Sender.php @@ -103,7 +103,7 @@ public function getFieldValue() if (!empty($name)) { $encoding = $this->getEncoding(); if ('ASCII' !== $encoding) { - $name = HeaderWrap::mimeEncodeValue($name, $encoding, false); + $name = HeaderWrap::mimeEncodeValue($name, $encoding); } $email = sprintf('%s %s', $name, $email); } diff --git a/src/Header/Subject.php b/src/Header/Subject.php index 9d0f1ff8..6adeef83 100644 --- a/src/Header/Subject.php +++ b/src/Header/Subject.php @@ -82,11 +82,7 @@ public function getFieldName() */ public function getFieldValue() { - $encoding = $this->getEncoding(); - if ($encoding == 'ASCII') { - return HeaderWrap::wrap($this->subject, $this); - } - return HeaderWrap::mimeEncodeValue($this->subject, $encoding, true); + return HeaderWrap::wrap($this->subject, $this); } /** diff --git a/test/Header/HeaderWrapTest.php b/test/Header/HeaderWrapTest.php new file mode 100644 index 00000000..8abf02ed --- /dev/null +++ b/test/Header/HeaderWrapTest.php @@ -0,0 +1,79 @@ +getMock('Zend\Mail\Header\UnstructuredInterface'); + $header->expects($this->any()) + ->method('getEncoding') + ->will($this->returnValue('ASCII')); + $expected = wordwrap($string, 78, "\r\n "); + + $test = HeaderWrap::wrap($string, $header); + $this->assertEquals($expected, $test); + } + + /** + * @group ZF2-258 + */ + public function testWrapUnstructuredHeaderMime() + { + $string = str_repeat('foobarblahblahblah baz bat', 3); + $header = $this->getMock('Zend\Mail\Header\UnstructuredInterface'); + $header->expects($this->any()) + ->method('getEncoding') + ->will($this->returnValue('UTF-8')); + $expected = "=?UTF-8?Q?foobarblahblahblah=20baz=20batfoobarblahblahblah=20baz=20?=\r\n" + . " =?UTF-8?Q?batfoobarblahblahblah=20baz=20bat?="; + + $test = HeaderWrap::wrap($string, $header); + $this->assertEquals($expected, $test); + $this->assertEquals($string, iconv_mime_decode($test)); + } + + /** + * @group ZF2-359 + */ + public function testMimeEncoding() + { + $string = 'Umlauts: รค'; + $expected = '=?UTF-8?Q?Umlauts:=20=C3=A4?='; + + $test = HeaderWrap::mimeEncodeValue($string, 'UTF-8', 78); + $this->assertEquals($expected, $test); + $this->assertEquals($string, iconv_mime_decode($test, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8')); + } +} diff --git a/test/MessageTest.php b/test/MessageTest.php index 1f72db03..5a09cabb 100644 --- a/test/MessageTest.php +++ b/test/MessageTest.php @@ -617,10 +617,6 @@ public function testEncodingIsMutable() public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders() { - if (!function_exists('iconv_mime_encode')) { - $this->markTestSkipped('Encoding relies on iconv extension'); - } - $this->message->addTo('zf-devteam@zend.com', 'ZF DevTeam'); $this->message->addFrom('matthew@zend.com', "Matthew Weier O'Phinney"); $this->message->addCc('zf-contributors@lists.zend.com', 'ZF Contributors List'); @@ -630,38 +626,23 @@ public function testSettingNonAsciiEncodingForcesMimeEncodingOfSomeHeaders() $test = $this->message->headers()->toString(); - $expected = $this->encodeString('ZF DevTeam', 'UTF-8'); + $expected = '=?UTF-8?Q?ZF=20DevTeam?='; $this->assertContains($expected, $test); $this->assertContains('', $test); - $expected = $this->encodeString("Matthew Weier O'Phinney", 'UTF-8'); + $expected = "=?UTF-8?Q?Matthew=20Weier=20O'Phinney?="; $this->assertContains($expected, $test, $test); $this->assertContains('', $test); - $expected = $this->encodeString("ZF Contributors List", 'UTF-8'); + $expected = '=?UTF-8?Q?ZF=20Contributors=20List?='; $this->assertContains($expected, $test); $this->assertContains('', $test); - $expected = $this->encodeString("ZF CR Team", 'UTF-8'); + $expected = '=?UTF-8?Q?ZF=20CR=20Team?='; $this->assertContains($expected, $test); $this->assertContains('', $test); - $self = $this; - $words = array_map(function($word) use ($self) { - return $self->encodeString($word, 'UTF-8'); - }, explode(' ', 'This is a subject')); - $expected = 'Subject: ' . implode("\r\n ", $words); - $this->assertContains($expected, $test, $test); - } - - public function encodeString($string, $charset) - { - $encoded = iconv_mime_encode('Header', $string, array( - 'scheme' => 'Q', - 'output-charset' => $charset, - 'line-length' => 998, - )); - $encoded = str_replace('Header: ', '', $encoded); - return $encoded; + $expected = 'Subject: =?UTF-8?Q?This=20is=20a=20subject?='; + $this->assertContains($expected, $test); } }