Commit 26838530 authored by Manfred Kutas's avatar Manfred Kutas

ZP-1051 Updated mimeDecode class to the latest version.

Released under the Affero GNU General Public License (AGPL) version 3.
parent ce01d813
...@@ -190,7 +190,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -190,7 +190,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->SendMail(): We get the new message")); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->SendMail(): We get the new message"));
$mobj = new Mail_mimeDecode($sm->mime); $mobj = new Mail_mimeDecode($sm->mime);
$message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8')); $message = $mobj->decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8'));
unset($mobj); unset($mobj);
ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->SendMail(): We get the From and To")); ZLog::Write(LOGLEVEL_DEBUG, sprintf("BackendIMAP->SendMail(): We get the From and To"));
...@@ -481,7 +481,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -481,7 +481,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
} }
$mobj = new Mail_mimeDecode($mail); $mobj = new Mail_mimeDecode($mail);
$message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8')); $message = $mobj->decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8'));
if (!isset($message->parts)) { if (!isset($message->parts)) {
throw new StatusException(sprintf("BackendIMAP->GetAttachmentData('%s'): Error, message without parts. Requesting part key: '%d'", $attname, $part), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT); throw new StatusException(sprintf("BackendIMAP->GetAttachmentData('%s'): Error, message without parts. Requesting part key: '%d'", $attname, $part), SYNC_ITEMOPERATIONSSTATUS_INVALIDATT);
...@@ -1028,7 +1028,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -1028,7 +1028,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
} }
$mobj = new Mail_mimeDecode($mail); $mobj = new Mail_mimeDecode($mail);
$message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8')); $message = $mobj->decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8'));
Utils::CheckAndFixEncoding($message->headers["subject"]); Utils::CheckAndFixEncoding($message->headers["subject"]);
Utils::CheckAndFixEncoding($message->headers["from"]); Utils::CheckAndFixEncoding($message->headers["from"]);
...@@ -1665,7 +1665,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider { ...@@ -1665,7 +1665,7 @@ class BackendIMAP extends BackendDiff implements ISearchProvider {
// Get the original calendar request, so we don't need to create it from scratch // Get the original calendar request, so we don't need to create it from scratch
$mobj = new Mail_mimeDecode($mail); $mobj = new Mail_mimeDecode($mail);
unset($mail); unset($mail);
$message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8')); $message = $mobj->decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'rfc_822bodies' => true, 'charset' => 'utf-8'));
unset($mobj); unset($mobj);
$body_part = null; $body_part = null;
......
...@@ -116,7 +116,7 @@ class BackendMaildir extends BackendDiff { ...@@ -116,7 +116,7 @@ class BackendMaildir extends BackendDiff {
// Parse e-mail // Parse e-mail
$rfc822 = file_get_contents($this->getPath() . "/$fn"); $rfc822 = file_get_contents($this->getPath() . "/$fn");
$message = Mail_mimeDecode::decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8')); $message = Mail_mimeDecode::decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8'));
$attachment = new SyncItemOperationsAttachment(); $attachment = new SyncItemOperationsAttachment();
$attachment->data = StringStreamWrapper::Open($message->parts[$part]->body); $attachment->data = StringStreamWrapper::Open($message->parts[$part]->body);
...@@ -333,7 +333,7 @@ class BackendMaildir extends BackendDiff { ...@@ -333,7 +333,7 @@ class BackendMaildir extends BackendDiff {
// Parse e-mail // Parse e-mail
$rfc822 = file_get_contents($this->getPath() . "/" . $fn); $rfc822 = file_get_contents($this->getPath() . "/" . $fn);
$message = Mail_mimeDecode::decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8')); $message = Mail_mimeDecode::decode(array('decode_headers' => 'utf-8', 'decode_bodies' => true, 'include_bodies' => true, 'input' => $rfc822, 'crlf' => "\n", 'charset' => 'utf-8'));
Utils::CheckAndFixEncoding($message->headers["subject"]); Utils::CheckAndFixEncoding($message->headers["subject"]);
Utils::CheckAndFixEncoding($message->headers["from"]); Utils::CheckAndFixEncoding($message->headers["from"]);
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
* @author Sean Coates <sean@php.net> * @author Sean Coates <sean@php.net>
* @copyright 2003-2006 PEAR <pear-group@php.net> * @copyright 2003-2006 PEAR <pear-group@php.net>
* @license http://www.opensource.org/licenses/bsd-license.php BSD License * @license http://www.opensource.org/licenses/bsd-license.php BSD License
* @version CVS: $Id: mimeDecode.php 335147 2014-10-27 08:41:39Z alan_k $ * @version CVS: $Id: mimeDecode.php 337165 2015-07-15 09:42:08Z alan_k $
* @link http://pear.php.net/package/Mail_mime * @link http://pear.php.net/package/Mail_mime
*/ */
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
* implemented automated decoding of strings from mail charset * implemented automated decoding of strings from mail charset
* *
* Reference implementation used: * Reference implementation used:
* http://download.pear.php.net/package/Mail_mimeDecode-1.5.5.tgz * http://download.pear.php.net/package/Mail_mimeDecode-1.5.6.tgz
* *
* used "old" method of checking if called statically, as this is deprecated between php 5.0.0 and 5.3.0 * used "old" method of checking if called statically, as this is deprecated between php 5.0.0 and 5.3.0
* (isStatic of decode() around line 215) * (isStatic of decode() around line 215)
...@@ -154,8 +154,8 @@ class Mail_mimeDecode ...@@ -154,8 +154,8 @@ class Mail_mimeDecode
/** /**
* Flag to determine whether to decode headers * Flag to determine whether to decode headers
* * (set to UTF8 to iconv convert headers)
* @var boolean * @var mixed
* @access private * @access private
*/ */
var $_decode_headers; var $_decode_headers;
...@@ -190,6 +190,11 @@ class Mail_mimeDecode ...@@ -190,6 +190,11 @@ class Mail_mimeDecode
$this->_include_bodies = true; $this->_include_bodies = true;
$this->_rfc822_bodies = false; $this->_rfc822_bodies = false;
} }
// BC
function Mail_mimeDecode($input)
{
$this->__construct($input);
}
/** /**
* Begins the decoding process. If called statically * Begins the decoding process. If called statically
...@@ -202,7 +207,8 @@ class Mail_mimeDecode ...@@ -202,7 +207,8 @@ class Mail_mimeDecode
* object. * object.
* decode_bodies - Whether to decode the bodies * decode_bodies - Whether to decode the bodies
* of the parts. (Transfer encoding) * of the parts. (Transfer encoding)
* decode_headers - Whether to decode headers * decode_headers - Whether to decode headers,
* - use "UTF8//IGNORE" to convert charset.
* *
* input - If called statically, this will be treated * input - If called statically, this will be treated
* as the input * as the input
...@@ -239,10 +245,12 @@ class Mail_mimeDecode ...@@ -239,10 +245,12 @@ class Mail_mimeDecode
$this->_charset = isset($params['charset']) ? $this->_charset = isset($params['charset']) ?
strtolower($params['charset']) : 'utf-8'; strtolower($params['charset']) : 'utf-8';
if (is_string($this->_decode_headers)) {
if (is_string($this->_decode_headers) && !function_exists('iconv')) { if (!function_exists('iconv')) {
$this->raiseError('header decode conversion requested, however iconv is missing'); $this->raiseError('header decode conversion requested, however iconv is missing');
} }
$this->_decode_headers = strtolower($this->_decode_headers);
}
$structure = $this->_decode($this->_header, $this->_body); $structure = $this->_decode($this->_header, $this->_body);
if ($structure === false) { if ($structure === false) {
...@@ -339,10 +347,18 @@ class Mail_mimeDecode ...@@ -339,10 +347,18 @@ class Mail_mimeDecode
break; break;
case 'multipart/signed': // PGP case 'multipart/signed': // PGP
$parts = $this->_boundarySplit($body, $content_type['other']['boundary'], true);
$return->parts['msg_body'] = $parts[0];
list($part_header, $part_body) = $this->_splitBodyHeader($parts[1]);
$return->parts['sig_hdr'] = $part_header;
$return->parts['sig_body'] = $part_body;
break;
case 'multipart/encrypted': // #190 encrypted parts will be treated as normal ones case 'multipart/encrypted': // #190 encrypted parts will be treated as normal ones
case 'multipart/parallel': case 'multipart/parallel':
case 'multipart/appledouble': // Appledouble mail case 'multipart/appledouble': // Appledouble mail
case 'multipart/report': // RFC1892 case 'multipart/report': // RFC1892
case 'multipart/signed': // PGP
case 'multipart/digest': case 'multipart/digest':
case 'multipart/alternative': case 'multipart/alternative':
case 'multipart/related': case 'multipart/related':
...@@ -385,7 +401,7 @@ class Mail_mimeDecode ...@@ -385,7 +401,7 @@ class Mail_mimeDecode
break; break;
// #190, KD 2015-06-09 - Add type for S/MIME Encrypted messages; these must have the filename set explicitly (it won't work otherwise) // #190, KD 2015-06-09 - Add type for S/MIME Encrypted messages; these must have the filename set explicitly (it won't work otherwise)
//and then falls through for the rest on purpose. // and then falls through for the rest on purpose.
case 'application/x-pkcs7-mime': case 'application/x-pkcs7-mime':
case 'application/pkcs7-mime': case 'application/pkcs7-mime':
if (!isset($content_transfer_encoding['value'])) { if (!isset($content_transfer_encoding['value'])) {
...@@ -781,7 +797,7 @@ class Mail_mimeDecode ...@@ -781,7 +797,7 @@ class Mail_mimeDecode
* @return string Decoded header value * @return string Decoded header value
* @access private * @access private
*/ */
function _decodeHeader($input) function _decodeHeader($input, $default_charset=false)
{ {
if (!$this->_decode_headers) { if (!$this->_decode_headers) {
return $input; return $input;
...@@ -789,19 +805,14 @@ class Mail_mimeDecode ...@@ -789,19 +805,14 @@ class Mail_mimeDecode
// Remove white space between encoded-words // Remove white space between encoded-words
$input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input); $input = preg_replace('/(=\?[^?]+\?(q|b)\?[^?]*\?=)(\s)+=\?/i', '\1=?', $input);
$encodedwords = false;
$charset = '';
// For each encoded-word... // For each encoded-word...
while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) { while (preg_match('/(=\?([^?]+)\?(q|b)\?([^?]*)\?=)/i', $input, $matches)) {
$encodedwords = true;
$encoded = $matches[1]; $encoded = $matches[1];
$charset = $matches[2]; $charset = strtolower($matches[2]);
$encoding = $matches[3]; $encoding = strtolower($matches[3]);
$text = $matches[4]; $text = $matches[4];
switch (strtolower($encoding)) { switch ($encoding) {
case 'b': case 'b':
$text = base64_decode($text); $text = base64_decode($text);
break; break;
...@@ -813,13 +824,16 @@ class Mail_mimeDecode ...@@ -813,13 +824,16 @@ class Mail_mimeDecode
$text = str_replace('=' . $value, chr(hexdec($value)), $text); $text = str_replace('=' . $value, chr(hexdec($value)), $text);
break; break;
} }
if (is_string($this->_decode_headers) && $charset != $this->_decode_headers) {
$text = $this->_autoconvert_encoding($text, $charset); $conv = @iconv($charset, $this->_decode_headers, $text);
$text = ($conv === false) ? $text : $conv;
}
$input = str_replace($encoded, $text, $input); $input = str_replace($encoded, $text, $input);
} }
if (!$encodedwords) { if ($default_charset && is_string($this->_decode_headers) && $charset != $this->_decode_headers) {
$input = $this->_autoconvert_encoding($input, $charset); $conv = @iconv($charset, $this->_decode_headers, $input); // TODO: shouldn't this be $default_charset ?
$input = ($conv === false) ? $input : $conv;
} }
return $input; return $input;
...@@ -846,67 +860,13 @@ class Mail_mimeDecode ...@@ -846,67 +860,13 @@ class Mail_mimeDecode
case 'base64': case 'base64':
$input = base64_decode($input); $input = base64_decode($input);
break; break;
case '7bit':
case '8bit':
default:
break;
}
return $detectCharset ? $this->_autoconvert_encoding($input, $charset) : $input;
} }
if ($detectCharset && strtolower($charset) != $this->_charset) {
/** $conv = @iconv($charset, $this->_charset, $input);
* Error handler dummy for _autoconvert_encoding $input = ($conv === false) ? $input : $conv;
*
* @param integer $errno
* @param string $errstr
* @return boolean true
* @access public static
*/
static function _iconv_notice_handler($errno, $errstr) {
return true;
} }
/** return $input;
* Autoconvert the text from any encoding. THIS WILL NEVER WORK 100%.
* Will ignore the E_NOTICE for iconv when detecting ilegal charsets
*
* @param string $input Input string to convert
* @param string $supposed_encoding Encoding that the text is possibly using
* @return string Converted string
* @access private
*/
function _autoconvert_encoding($input, $supposed_encoding = "UTF-8") {
$input_converted = $input;
if (function_exists("mb_detect_order")) {
$mb_order = array_merge(array($supposed_encoding), mb_detect_order());
set_error_handler('Mail_mimeDecode::_iconv_notice_handler');
// Default value in case of error
$detected_encoding = $supposed_encoding;
try {
$detected_encoding = mb_detect_encoding($input, $mb_order, true);
// In some cases mb_detect_encoding returns an empty string
if ($detected_encoding === false || strlen($detected_encoding) == 0) {
$detected_encoding = $supposed_encoding;
}
$input_converted = iconv($detected_encoding, $this->_charset, $input);
}
catch(Exception $ex) {
$this->raiseError($ex->getMessage());
}
restore_error_handler();
if ($input_converted === false || mb_strlen($input_converted, $this->_charset) !== mb_strlen($input, $detected_encoding)) {
ZLog::Write(LOGLEVEL_DEBUG, "Mail_mimeDecode()::_autoconvert_encoding(): Text cannot be correctly decoded, using original text. This will be ok if the part is not text, otherwise expect encoding errors");
$input_converted = $input;
}
}
return $input_converted;
} }
/** /**
...@@ -1008,7 +968,7 @@ class Mail_mimeDecode ...@@ -1008,7 +968,7 @@ class Mail_mimeDecode
/** /**
* Get all parts in the message with specified type and concatenate them together, unless the * Get all parts in the message with specified type and concatenate them together, unless the
* Content-Disposition is 'attachment', in which case the text is apparently an attachment * Content-Disposition is 'attachment', in which case the text is apparently an attachment.
* *
* @param string $message mimedecode message(part) * @param string $message mimedecode message(part)
* @param string $message message subtype * @param string $message message subtype
...@@ -1019,8 +979,9 @@ class Mail_mimeDecode ...@@ -1019,8 +979,9 @@ class Mail_mimeDecode
* @access public * @access public
*/ */
static function getBodyRecursive($message, $subtype, &$body, $replace_nr = false) { static function getBodyRecursive($message, $subtype, &$body, $replace_nr = false) {
if(!isset($message->ctype_primary)) return; // TODO: move this function into general utils
if(strcasecmp($message->ctype_primary, "text") == 0 && strcasecmp($message->ctype_secondary, $subtype) == 0 && isset($message->body)) { if (!isset($message->ctype_primary)) return;
if (strcasecmp($message->ctype_primary, "text") == 0 && strcasecmp($message->ctype_secondary, $subtype) == 0 && isset($message->body)) {
if ($replace_nr) { if ($replace_nr) {
$body .= str_replace("\n", "\r\n", str_replace("\r", "", $message->body)); $body .= str_replace("\n", "\r\n", str_replace("\r", "", $message->body));
} }
...@@ -1029,12 +990,12 @@ class Mail_mimeDecode ...@@ -1029,12 +990,12 @@ class Mail_mimeDecode
} }
} }
if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) { if (strcasecmp($message->ctype_primary,"multipart") == 0 && isset($message->parts) && is_array($message->parts)) {
foreach($message->parts as $part) { foreach($message->parts as $part) {
// Check testing/samples/m1009.txt // Check testing/samples/m1009.txt
// Content-Type: text/plain; charset=us-ascii; name="hareandtoroise.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="hareandtoroise.txt" // Content-Type: text/plain; charset=us-ascii; name="hareandtoroise.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="hareandtoroise.txt"
// We don't want to show that file text (outlook doesn't show it), so if we have content-disposition we don't apply recursivity // We don't want to show that file text (outlook doesn't show it), so if we have content-disposition we don't apply recursivity
if(!isset($part->disposition)) { if (!isset($part->disposition)) {
Mail_mimeDecode::getBodyRecursive($part, $subtype, $body, $replace_nr); Mail_mimeDecode::getBodyRecursive($part, $subtype, $body, $replace_nr);
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment