From 37e8b027f9f4e4922048e6ac9826291a4f9f4f07 Mon Sep 17 00:00:00 2001 From: Mikael Nordfeldth Date: Thu, 9 Jul 2015 22:29:23 +0200 Subject: [PATCH] PEAR's Mail_mimeDecode updated --- extlib/Mail/mimeDecode.php | 232 ++++++++++++++++++++++++++++++------- 1 file changed, 193 insertions(+), 39 deletions(-) diff --git a/extlib/Mail/mimeDecode.php b/extlib/Mail/mimeDecode.php index aaa870c509..a0d06942f4 100644 --- a/extlib/Mail/mimeDecode.php +++ b/extlib/Mail/mimeDecode.php @@ -52,7 +52,7 @@ * @author Sean Coates * @copyright 2003-2006 PEAR * @license http://www.opensource.org/licenses/bsd-license.php BSD License - * @version CVS: $Id: mimeDecode.php,v 1.48 2006/12/03 13:43:33 cipri Exp $ + * @version CVS: $Id: mimeDecode.php 305875 2010-12-01 07:17:10Z alan_k $ * @link http://pear.php.net/package/Mail_mime */ @@ -147,6 +147,15 @@ class Mail_mimeDecode extends PEAR */ var $_decode_headers; + /** + * Flag to determine whether to include attached messages + * as body in the returned object. Depends on $_include_bodies + * + * @var boolean + * @access private + */ + var $_rfc822_bodies; + /** * Constructor. * @@ -165,6 +174,7 @@ class Mail_mimeDecode extends PEAR $this->_body = $body; $this->_decode_bodies = false; $this->_include_bodies = true; + $this->_rfc822_bodies = false; } /** @@ -187,7 +197,7 @@ class Mail_mimeDecode extends PEAR function decode($params = null) { // determine if this method has been called statically - $isStatic = !(isset($this) && get_class($this) == __CLASS__); + $isStatic = empty($this) || !is_a($this, __CLASS__); // Have we been called statically? // If so, create an object and pass details to that. @@ -208,6 +218,8 @@ class Mail_mimeDecode extends PEAR $params['decode_bodies'] : false; $this->_decode_headers = isset($params['decode_headers']) ? $params['decode_headers'] : false; + $this->_rfc822_bodies = isset($params['rfc_822bodies']) ? + $params['rfc_822bodies'] : false; $structure = $this->_decode($this->_header, $this->_body); if ($structure === false) { @@ -235,6 +247,7 @@ class Mail_mimeDecode extends PEAR $headers = $this->_parseHeaders($headers); foreach ($headers as $value) { + $value['value'] = $this->_decode_headers ? $this->_decodeHeader($value['value']) : $value['value']; if (isset($return->headers[strtolower($value['name'])]) AND !is_array($return->headers[strtolower($value['name'])])) { $return->headers[strtolower($value['name'])] = array($return->headers[strtolower($value['name'])]); $return->headers[strtolower($value['name'])][] = $value['value']; @@ -247,8 +260,8 @@ class Mail_mimeDecode extends PEAR } } - reset($headers); - while (list($key, $value) = each($headers)) { + + foreach ($headers as $key => $value) { $headers[$key]['name'] = strtolower($headers[$key]['name']); switch ($headers[$key]['name']) { @@ -261,7 +274,7 @@ class Mail_mimeDecode extends PEAR } if (isset($content_type['other'])) { - while (list($p_name, $p_value) = each($content_type['other'])) { + foreach($content_type['other'] as $p_name => $p_value) { $return->ctype_parameters[$p_name] = $p_value; } } @@ -271,7 +284,7 @@ class Mail_mimeDecode extends PEAR $content_disposition = $this->_parseHeaderValue($headers[$key]['value']); $return->disposition = $content_disposition['value']; if (isset($content_disposition['other'])) { - while (list($p_name, $p_value) = each($content_disposition['other'])) { + foreach($content_disposition['other'] as $p_name => $p_value) { $return->d_parameters[$p_name] = $p_value; } } @@ -303,6 +316,7 @@ class Mail_mimeDecode extends PEAR case 'multipart/alternative': case 'multipart/related': case 'multipart/mixed': + case 'application/vnd.wap.multipart.related': if(!isset($content_type['other']['boundary'])){ $this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; return false; @@ -321,7 +335,11 @@ class Mail_mimeDecode extends PEAR break; case 'message/rfc822': - $obj = &new Mail_mimeDecode($body); + if ($this->_rfc822_bodies) { + $encoding = isset($content_transfer_encoding) ? $content_transfer_encoding['value'] : '7bit'; + $return->body = ($this->_decode_bodies ? $this->_decodeBody($body, $encoding) : $body); + } + $obj = new Mail_mimeDecode($body); $return->parts[] = $obj->decode(array('include_bodies' => $this->_include_bodies, 'decode_bodies' => $this->_decode_bodies, 'decode_headers' => $this->_decode_headers)); @@ -401,6 +419,11 @@ class Mail_mimeDecode extends PEAR if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) { return array($match[1], $match[2]); } + // bug #17325 - empty bodies are allowed. - we just check that at least one line + // of headers exist.. + if (count(explode("\n",$input))) { + return array($input, ''); + } $this->_error = 'Could not split header and body'; return false; } @@ -419,7 +442,12 @@ class Mail_mimeDecode extends PEAR if ($input !== '') { // Unfold the input $input = preg_replace("/\r?\n/", "\r\n", $input); + //#7065 - wrapping.. with encoded stuff.. - probably not needed, + // wrapping space should only get removed if the trailing item on previous line is a + // encoded character + $input = preg_replace("/=\r\n(\t| )+/", '=', $input); $input = preg_replace("/\r\n(\t| )+/", ' ', $input); + $headers = explode("\r\n", trim($input)); foreach ($headers as $value) { @@ -430,7 +458,7 @@ class Mail_mimeDecode extends PEAR $return[] = array( 'name' => $hdr_name, - 'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value + 'value' => $hdr_value ); } } else { @@ -454,41 +482,161 @@ class Mail_mimeDecode extends PEAR function _parseHeaderValue($input) { - if (($pos = strpos($input, ';')) !== false) { + if (($pos = strpos($input, ';')) === false) { + $input = $this->_decode_headers ? $this->_decodeHeader($input) : $input; + $return['value'] = trim($input); + return $return; + } + + - $return['value'] = trim(substr($input, 0, $pos)); - $input = trim(substr($input, $pos+1)); + $value = substr($input, 0, $pos); + $value = $this->_decode_headers ? $this->_decodeHeader($value) : $value; + $return['value'] = trim($value); + $input = trim(substr($input, $pos+1)); - if (strlen($input) > 0) { + if (!strlen($input) > 0) { + return $return; + } + // at this point input contains xxxx=".....";zzzz="...." + // since we are dealing with quoted strings, we need to handle this properly.. + $i = 0; + $l = strlen($input); + $key = ''; + $val = false; // our string - including quotes.. + $q = false; // in quote.. + $lq = ''; // last quote.. + + while ($i < $l) { + + $c = $input[$i]; + //var_dump(array('i'=>$i,'c'=>$c,'q'=>$q, 'lq'=>$lq, 'key'=>$key, 'val' =>$val)); - // This splits on a semi-colon, if there's no preceeding backslash - // Now works with quoted values; had to glue the \; breaks in PHP - // the regex is already bordering on incomprehensible - $splitRegex = '/([^;\'"]*[\'"]([^\'"]*([^\'"]*)*)[\'"][^;\'"]*|([^;]+))(;|$)/'; - preg_match_all($splitRegex, $input, $matches); - $parameters = array(); - for ($i=0; $i$val) { + $return['other'][$key] = $this->_decode_headers ? $this->_decodeHeader($val) : $val; + } + //print_r($return); return $return; } @@ -510,13 +658,19 @@ class Mail_mimeDecode extends PEAR if ($boundary == $bs_check) { $boundary = $bs_possible; } + $tmp = preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input); - $tmp = explode('--' . $boundary, $input); - - for ($i = 1; $i < count($tmp) - 1; $i++) { - $parts[] = $tmp[$i]; + $len = count($tmp) -1; + for ($i = 1; $i < $len; $i++) { + if (strlen(trim($tmp[$i]))) { + $parts[] = $tmp[$i]; + } + } + + // add the last part on if it does not end with the 'closing indicator' + if (!empty($tmp[$len]) && strlen(trim($tmp[$len])) && $tmp[$len][0] != '-') { + $parts[] = $tmp[$len]; } - return $parts; } @@ -719,7 +873,7 @@ class Mail_mimeDecode extends PEAR case "to": case "cc": case "bcc": - $to = ",".$item['value']; + $to .= ",".$item['value']; default: break; } -- 2.39.5