From 4f69328132beae439d1aecb6d35d55392e480eca Mon Sep 17 00:00:00 2001 From: alecpl Date: Mon, 12 Oct 2009 10:37:49 +0000 Subject: - Partially fixed "empty body" issue by showing raw body of malformed message (#1486166) --- CHANGELOG | 1 + program/include/rcube_imap.php | 20 ++++--- program/steps/mail/func.inc | 117 +++++++++++++++++++++++------------------ 3 files changed, 75 insertions(+), 63 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 297582248..ce6e9f381 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,6 +1,7 @@ CHANGELOG RoundCube Webmail =========================== +- Partially fixed "empty body" issue by showing raw body of malformed message (#1486166) - Fix importing/sending to email address with whitespace (#1486214) - Added XIMSS (CommuniGate) driver for Password plugin - Fix newly attached files are not saved in drafts w/o editing any text (#1486202) diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php index 9ca1167ee..533f94177 100644 --- a/program/include/rcube_imap.php +++ b/program/include/rcube_imap.php @@ -1226,17 +1226,15 @@ class rcube_imap else $this->struct_charset = $this->_structure_charset($structure); - /* - @TODO: here we can recognize malformed BODYSTRUCTURE and parse - the message in other way to create our own message structure. - Example of structure for malformed MIME message: - ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 2154 70 NIL NIL NIL) - - if ($headers->ctype != 'text/plain' - && !is_array($structure[0]) && $structure[0] == 'text' - && !is_array($structure[1]) && $structure[1] == 'plain') - { } - */ + // Here we can recognize malformed BODYSTRUCTURE and + // 1. [@TODO] parse the message in other way to create our own message structure + // 2. or just show the raw message body. + // Example of structure for malformed MIME message: + // ("text" "plain" ("charset" "us-ascii") NIL NIL "7bit" 2154 70 NIL NIL NIL) + if ($headers->ctype && $headers->ctype != 'text/plain' + && $structure[0] == 'text' && $structure[1] == 'plain') { + return false; + } $struct = &$this->_structure_part($structure); $struct->headers = get_object_vars($headers); diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 38b3acfc5..b220edaac 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -785,64 +785,76 @@ function rcmail_print_body($part, $p = array()) unset($data['body']); // plaintext postprocessing - if ($part->ctype_secondary == 'plain') { - // make links and email-addresses clickable - $replacements = new rcube_string_replacer; - - // search for patterns like links and e-mail addresses - $body = preg_replace_callback($replacements->link_pattern, array($replacements, 'link_callback'), $body); - $body = preg_replace_callback($replacements->mailto_pattern, array($replacements, 'mailto_callback'), $body); - - // split body into single lines - $a_lines = preg_split('/\r?\n/', $body); - $q_lines = array(); - $quote_level = 0; - - // find/mark quoted lines... - for ($n=0, $cnt=count($a_lines); $n < $cnt; $n++) { - $q = 0; - - if ($a_lines[$n][0] == '>' && preg_match('/^(>+\s*)+/', $a_lines[$n], $regs)) { - $q = strlen(preg_replace('/\s/', '', $regs[0])); - $a_lines[$n] = substr($a_lines[$n], strlen($regs[0])); - - if ($q > $quote_level) - $q_lines[$n]['quote'] = $q - $quote_level; - else if ($q < $quote_level) - $q_lines[$n]['endquote'] = $quote_level - $q; - } - else if ($quote_level > 0) - $q_lines[$n]['endquote'] = $quote_level; + if ($part->ctype_secondary == 'plain') + $body = rcmail_plain_body($body); - $quote_level = $q; - } - - // quote plain text - $body = Q(join("\n", $a_lines), 'replace', false); + // allow post-processing of the message body + $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data); - // colorize signature - if (($sp = strrpos($body, '-- ')) !== false) - if (($sp == 0 || $body[$sp-1] == "\n") && $body[$sp+3] == "\n") { - $body = substr($body, 0, max(0, $sp)) - .''.substr($body, $sp).''; - } + return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']); +} - // colorize quoted lines - $a_lines = preg_split('/\n/', $body); - foreach ($q_lines as $i => $q) - if ($q['quote']) - $a_lines[$i] = str_repeat('
', $q['quote']) . $a_lines[$i]; - else if ($q['endquote']) - $a_lines[$i] = str_repeat('
', $q['endquote']) . $a_lines[$i]; +/** + * Handle links and citation marks in plain text message + * + * @param string Plain text string + * @return string Formatted HTML string + */ +function rcmail_plain_body($body) +{ + // make links and email-addresses clickable + $replacements = new rcube_string_replacer; + + // search for patterns like links and e-mail addresses + $body = preg_replace_callback($replacements->link_pattern, array($replacements, 'link_callback'), $body); + $body = preg_replace_callback($replacements->mailto_pattern, array($replacements, 'mailto_callback'), $body); + + // split body into single lines + $a_lines = preg_split('/\r?\n/', $body); + $q_lines = array(); + $quote_level = 0; + + // find/mark quoted lines... + for ($n=0, $cnt=count($a_lines); $n < $cnt; $n++) { + $q = 0; + + if ($a_lines[$n][0] == '>' && preg_match('/^(>+\s*)+/', $a_lines[$n], $regs)) { + $q = strlen(preg_replace('/\s/', '', $regs[0])); + $a_lines[$n] = substr($a_lines[$n], strlen($regs[0])); + + if ($q > $quote_level) + $q_lines[$n]['quote'] = $q - $quote_level; + else if ($q < $quote_level) + $q_lines[$n]['endquote'] = $quote_level - $q; + } + else if ($quote_level > 0) + $q_lines[$n]['endquote'] = $quote_level; - // insert the links for urls and mailtos - $body = $replacements->resolve(join("\n", $a_lines)); + $quote_level = $q; } - // allow post-processing of the message body - $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body) + $data); + // quote plain text + $body = Q(join("\n", $a_lines), 'replace', false); - return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']); + // colorize signature + if (($sp = strrpos($body, '-- ')) !== false) + if (($sp == 0 || $body[$sp-1] == "\n") && $body[$sp+3] == "\n") { + $body = substr($body, 0, max(0, $sp)) + .''.substr($body, $sp).''; + } + + // colorize quoted lines + $a_lines = preg_split('/\n/', $body); + foreach ($q_lines as $i => $q) + if ($q['quote']) + $a_lines[$i] = str_repeat('
', $q['quote']) . $a_lines[$i]; + else if ($q['endquote']) + $a_lines[$i] = str_repeat('
', $q['endquote']) . $a_lines[$i]; + + // insert the links for urls and mailtos + $body = $replacements->resolve(join("\n", $a_lines)); + + return $body; } @@ -1027,7 +1039,8 @@ function rcmail_message_body($attrib) } } else - $out .= html::div('message-part', html::tag('pre', array(), Q($MESSAGE->body))); + $out .= html::div('message-part', html::tag('pre', array(), + rcmail_plain_body(Q($MESSAGE->body, 'strict', false)))); $ctype_primary = strtolower($MESSAGE->structure->ctype_primary); $ctype_secondary = strtolower($MESSAGE->structure->ctype_secondary); -- cgit v1.2.3