Commit 59c3ea8d authored by mku's avatar mku

ZP-322 #comment Merge contribution - Mail_mimeDecode rebase to 1.5.5 #time 20m

git-svn-id: https://z-push.org/svn/z-push/trunk@1576 b7dd7b3b-3a3c-0410-9da9-bee62a6cc5b5
parent 7de261a0
...@@ -28,8 +28,8 @@ ...@@ -28,8 +28,8 @@
* - Redistributions in binary form must reproduce the above copyright * - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* - Neither the name of the authors, nor the names of its contributors * - Neither the name of the authors, nor the names of its contributors
* may be used to endorse or promote products derived from this * may be used to endorse or promote products derived from this
* software without specific prior written permission. * software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
...@@ -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 288500 2009-09-21 05:32:32Z alan_k $ * @version CVS: $Id: mimeDecode.php 305875 2010-12-01 07:17:10Z alan_k $
* @link http://pear.php.net/package/Mail_mime * @link http://pear.php.net/package/Mail_mime
*/ */
...@@ -61,11 +61,10 @@ ...@@ -61,11 +61,10 @@
* Z-Push changes * Z-Push changes
* *
* removed PEAR dependency by implementing own raiseError() * removed PEAR dependency by implementing own raiseError()
* removed deprecated referencing: $obj = &new Mail_mimeDecode($body); in _decode()
* 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.1.tgz * http://download.pear.php.net/package/Mail_mimeDecode-1.5.5.tgz
* *
*/ */
...@@ -209,10 +208,10 @@ class Mail_mimeDecode ...@@ -209,10 +208,10 @@ class Mail_mimeDecode
function decode($params = null) function decode($params = null)
{ {
// determine if this method has been called statically // 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? // Have we been called statically?
// If so, create an object and pass details to that. // If so, create an object and pass details to that.
if ($isStatic AND isset($params['input'])) { if ($isStatic AND isset($params['input'])) {
$obj = new Mail_mimeDecode($params['input']); $obj = new Mail_mimeDecode($params['input']);
...@@ -225,13 +224,13 @@ class Mail_mimeDecode ...@@ -225,13 +224,13 @@ class Mail_mimeDecode
// Called via an object // Called via an object
} else { } else {
$this->_include_bodies = isset($params['include_bodies']) ? $this->_include_bodies = isset($params['include_bodies']) ?
$params['include_bodies'] : false; $params['include_bodies'] : false;
$this->_decode_bodies = isset($params['decode_bodies']) ? $this->_decode_bodies = isset($params['decode_bodies']) ?
$params['decode_bodies'] : false; $params['decode_bodies'] : false;
$this->_decode_headers = isset($params['decode_headers']) ? $this->_decode_headers = isset($params['decode_headers']) ?
$params['decode_headers'] : false; $params['decode_headers'] : false;
$this->_rfc822_bodies = isset($params['rfc_822bodies']) ? $this->_rfc822_bodies = isset($params['rfc_822bodies']) ?
$params['rfc_822bodies'] : false; $params['rfc_822bodies'] : false;
$this->_charset = isset($params['charset']) ? $this->_charset = isset($params['charset']) ?
strtolower($params['charset']) : 'utf-8'; strtolower($params['charset']) : 'utf-8';
...@@ -261,6 +260,7 @@ class Mail_mimeDecode ...@@ -261,6 +260,7 @@ class Mail_mimeDecode
$headers = $this->_parseHeaders($headers); $headers = $this->_parseHeaders($headers);
foreach ($headers as $value) { 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'])])) { 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'])] = array($return->headers[strtolower($value['name'])]);
$return->headers[strtolower($value['name'])][] = $value['value']; $return->headers[strtolower($value['name'])][] = $value['value'];
...@@ -273,8 +273,8 @@ class Mail_mimeDecode ...@@ -273,8 +273,8 @@ class Mail_mimeDecode
} }
} }
reset($headers);
while (list($key, $value) = each($headers)) { foreach ($headers as $key => $value) {
$headers[$key]['name'] = strtolower($headers[$key]['name']); $headers[$key]['name'] = strtolower($headers[$key]['name']);
switch ($headers[$key]['name']) { switch ($headers[$key]['name']) {
...@@ -287,7 +287,7 @@ class Mail_mimeDecode ...@@ -287,7 +287,7 @@ class Mail_mimeDecode
} }
if (isset($content_type['other'])) { 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; $return->ctype_parameters[$p_name] = $p_value;
} }
} }
...@@ -297,7 +297,7 @@ class Mail_mimeDecode ...@@ -297,7 +297,7 @@ class Mail_mimeDecode
$content_disposition = $this->_parseHeaderValue($headers[$key]['value']); $content_disposition = $this->_parseHeaderValue($headers[$key]['value']);
$return->disposition = $content_disposition['value']; $return->disposition = $content_disposition['value'];
if (isset($content_disposition['other'])) { 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; $return->d_parameters[$p_name] = $p_value;
} }
} }
...@@ -331,6 +331,7 @@ class Mail_mimeDecode ...@@ -331,6 +331,7 @@ class Mail_mimeDecode
case 'multipart/alternative': case 'multipart/alternative':
case 'multipart/related': case 'multipart/related':
case 'multipart/mixed': case 'multipart/mixed':
case 'application/vnd.wap.multipart.related':
if(!isset($content_type['other']['boundary'])){ if(!isset($content_type['other']['boundary'])){
$this->_error = 'No boundary found for ' . $content_type['value'] . ' part'; $this->_error = 'No boundary found for ' . $content_type['value'] . ' part';
return false; return false;
...@@ -437,6 +438,11 @@ class Mail_mimeDecode ...@@ -437,6 +438,11 @@ class Mail_mimeDecode
if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) { if (preg_match("/^(.*?)\r?\n\r?\n(.*)/s", $input, $match)) {
return array($match[1], $match[2]); 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'; $this->_error = 'Could not split header and body';
return false; return false;
} }
...@@ -455,7 +461,12 @@ class Mail_mimeDecode ...@@ -455,7 +461,12 @@ class Mail_mimeDecode
if ($input !== '') { if ($input !== '') {
// Unfold the input // Unfold the input
$input = preg_replace("/\r?\n/", "\r\n", $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); $input = preg_replace("/\r\n(\t| )+/", ' ', $input);
$headers = explode("\r\n", trim($input)); $headers = explode("\r\n", trim($input));
foreach ($headers as $value) { foreach ($headers as $value) {
...@@ -466,7 +477,7 @@ class Mail_mimeDecode ...@@ -466,7 +477,7 @@ class Mail_mimeDecode
$return[] = array( $return[] = array(
'name' => $hdr_name, 'name' => $hdr_name,
'value' => $this->_decode_headers ? $this->_decodeHeader($hdr_value) : $hdr_value 'value' => $hdr_value
); );
} }
} else { } else {
...@@ -490,44 +501,161 @@ class Mail_mimeDecode ...@@ -490,44 +501,161 @@ class Mail_mimeDecode
function _parseHeaderValue($input) 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));
if (strlen($input) > 0) {
// This splits on a semi-colon, if there's no preceeding backslash $value = substr($input, 0, $pos);
// Now works with quoted values; had to glue the \; breaks in PHP $value = $this->_decode_headers ? $this->_decodeHeader($value) : $value;
// the regex is already bordering on incomprehensible $return['value'] = trim($value);
//$splitRegex = '/([^;\'"]*[\'"]([^\'"]*([^\'"]*)*)[\'"][^;\'"]*|([^;]+))(;|$)/'; $input = trim(substr($input, $pos+1));
// simplyfied RegEx - Nokia Mail2 sends boundaries containing ' which break the above regex
$splitRegex = '/([^;\'"]*[\'"]([^\'"]*)[\'"][^;\'"]*|([^;]+))(;|$)/';
preg_match_all($splitRegex, $input, $matches);
$parameters = array(); if (!strlen($input) > 0) {
for ($i=0; $i<count($matches[0]); $i++) { return $return;
$param = $matches[0][$i]; }
while (substr($param, -2) == '\;') { // at this point input contains xxxx=".....";zzzz="...."
$param .= $matches[0][++$i]; // 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));
$escaped = false;
if ($c == '\\') {
$i++;
if ($i == $l-1) { // end of string.
break;
}
$escaped = true;
$c = $input[$i];
}
// state - in key..
if ($val === false) {
if (!$escaped && $c == '=') {
$val = '';
$key = trim($key);
$i++;
continue;
}
if (!$escaped && $c == ';') {
if ($key) { // a key without a value..
$key= trim($key);
$return['other'][$key] = '';
$return['other'][strtolower($key)] = '';
}
$key = '';
}
$key .= $c;
$i++;
continue;
}
// state - in value.. (as $val is set..)
if ($q === false) {
// not in quote yet.
if ((!strlen($val) || $lq !== false) && $c == ' ' || $c == "\t") {
$i++;
continue; // skip leading spaces after '=' or after '"'
}
if (!$escaped && ($c == '"' || $c == "'")) {
// start quoted area..
$q = $c;
// in theory should not happen raw text in value part..
// but we will handle it as a merged part of the string..
$val = !strlen(trim($val)) ? '' : trim($val);
$i++;
continue;
}
// got end....
if (!$escaped && $c == ';') {
$val = trim($val);
$added = false;
if (preg_match('/\*[0-9]+$/', $key)) {
// this is the extended aaa*0=...;aaa*1=.... code
// it assumes the pieces arrive in order, and are valid...
$key = preg_replace('/\*[0-9]+$/', '', $key);
if (isset($return['other'][$key])) {
$return['other'][$key] .= $val;
if (strtolower($key) != $key) {
$return['other'][strtolower($key)] .= $val;
}
$added = true;
}
// continue and use standard setters..
} }
$parameters[] = $param; if (!$added) {
$return['other'][$key] = $val;
$return['other'][strtolower($key)] = $val;
}
$val = false;
$key = '';
$lq = false;
$i++;
continue;
} }
for ($i = 0; $i < count($parameters); $i++) { $val .= $c;
$param_name = trim(substr($parameters[$i], 0, $pos = strpos($parameters[$i], '=')), "'\";\t\\ "); $i++;
$param_value = trim(str_replace('\;', ';', substr($parameters[$i], $pos + 1)), "'\";\t\\ "); continue;
if (!empty($param_value[0]) && $param_value[0] == '"') { }
$param_value = substr($param_value, 1, -1);
// state - in quote..
if (!$escaped && $c == $q) { // potential exit state..
// end of quoted string..
$lq = $q;
$q = false;
$i++;
continue;
}
// normal char inside of quoted string..
$val.= $c;
$i++;
}
// do we have anything left..
if (strlen(trim($key)) || $val !== false) {
$val = trim($val);
$added = false;
if ($val !== false && preg_match('/\*[0-9]+$/', $key)) {
// no dupes due to our crazy regexp.
$key = preg_replace('/\*[0-9]+$/', '', $key);
if (isset($return['other'][$key])) {
$return['other'][$key] .= $val;
if (strtolower($key) != $key) {
$return['other'][strtolower($key)] .= $val;
} }
$return['other'][$param_name] = $param_value; $added = true;
$return['other'][strtolower($param_name)] = $param_value;
} }
// continue and use standard setters..
}
if (!$added) {
$return['other'][$key] = $val;
$return['other'][strtolower($key)] = $val;
} }
} else {
$return['value'] = trim($input);
} }
// decode values.
foreach($return['other'] as $key =>$val) {
$return['other'][$key] = $this->_decode_headers ? $this->_decodeHeader($val) : $val;
}
//print_r($return);
return $return; return $return;
} }
...@@ -549,13 +677,19 @@ class Mail_mimeDecode ...@@ -549,13 +677,19 @@ class Mail_mimeDecode
if ($boundary == $bs_check) { if ($boundary == $bs_check) {
$boundary = $bs_possible; $boundary = $bs_possible;
} }
$tmp = preg_split("/--".preg_quote($boundary, '/')."((?=\s)|--)/", $input);
$tmp = explode('--' . $boundary, $input); $len = count($tmp) -1;
for ($i = 1; $i < $len; $i++) {
for ($i = 1; $i < count($tmp) - 1; $i++) { if (strlen(trim($tmp[$i]))) {
$parts[] = $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; return $parts;
} }
...@@ -648,7 +782,7 @@ class Mail_mimeDecode ...@@ -648,7 +782,7 @@ class Mail_mimeDecode
$input = preg_replace("/=\r?\n/", '', $input); $input = preg_replace("/=\r?\n/", '', $input);
// Replace encoded characters // Replace encoded characters
$input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input); $input = preg_replace('/=([a-f0-9]{2})/ie', "chr(hexdec('\\1'))", $input);
return $input; return $input;
} }
...@@ -730,7 +864,7 @@ class Mail_mimeDecode ...@@ -730,7 +864,7 @@ class Mail_mimeDecode
/** /**
* getSendArray() returns the arguments required for Mail::send() * getSendArray() returns the arguments required for Mail::send()
* used to build the arguments for a mail::send() call * used to build the arguments for a mail::send() call
* *
* Usage: * Usage:
* $mailtext = Full email (for example generated by a template) * $mailtext = Full email (for example generated by a template)
...@@ -772,7 +906,7 @@ class Mail_mimeDecode ...@@ -772,7 +906,7 @@ class Mail_mimeDecode
} }
$to = substr($to,1); $to = substr($to,1);
return array($to,$header,$this->_body); return array($to,$header,$this->_body);
} }
/** /**
* Returns a xml copy of the output of * Returns a xml copy of the output of
......
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