| | |
| | | |
| | | $p += array('safe' => false, 'inline_html' => true); |
| | | |
| | | // special replacements (not properly handled by washtml class) |
| | | $html_search = array( |
| | | '/(<\/nobr>)(\s+)(<nobr>)/i', // space(s) between <NOBR> |
| | | '/<title[^>]*>[^<]*<\/title>/i', // PHP bug #32547 workaround: remove title tag |
| | | '/^(\0\0\xFE\xFF|\xFF\xFE\0\0|\xFE\xFF|\xFF\xFE|\xEF\xBB\xBF)/', // byte-order mark (only outlook?) |
| | | '/<html\s[^>]+>/i', // washtml/DOMDocument cannot handle xml namespaces |
| | | ); |
| | | $html_replace = array( |
| | | '\\1'.' '.'\\3', |
| | | '', |
| | | '', |
| | | '<html>', |
| | | ); |
| | | $html = preg_replace($html_search, $html_replace, trim($html)); |
| | | |
| | | // PCRE errors handling (#1486856), should we use something like for every preg_* use? |
| | | if ($html === null && ($preg_error = preg_last_error()) != PREG_NO_ERROR) { |
| | | $errstr = "Could not clean up HTML message! PCRE Error: $preg_error."; |
| | | |
| | | if ($preg_error == PREG_BACKTRACK_LIMIT_ERROR) |
| | | $errstr .= " Consider raising pcre.backtrack_limit!"; |
| | | if ($preg_error == PREG_RECURSION_LIMIT_ERROR) |
| | | $errstr .= " Consider raising pcre.recursion_limit!"; |
| | | |
| | | raise_error(array('code' => 620, 'type' => 'php', |
| | | 'line' => __LINE__, 'file' => __FILE__, |
| | | 'message' => $errstr), true, false); |
| | | return ''; |
| | | } |
| | | |
| | | // fix (unknown/malformed) HTML tags before "wash" |
| | | $html = preg_replace_callback('/(<[\/]*)([^\s>]+)/', 'rcmail_html_tag_callback', $html); |
| | | |
| | | // charset was converted to UTF-8 in rcube_storage::get_message_part(), |
| | | // change/add charset specification in HTML accordingly, |
| | | // washtml cannot work without that |
| | |
| | | if (!$rcount) { |
| | | $html = '<head>' . $meta . '</head>' . $html; |
| | | } |
| | | |
| | | // turn relative into absolute urls |
| | | $html = rcmail_resolve_base($html); |
| | | |
| | | // clean HTML with washhtml by Frederic Motte |
| | | $wash_opts = array( |
| | |
| | | $wash_opts['html_attribs'] = $p['html_attribs']; |
| | | |
| | | // initialize HTML washer |
| | | $washer = new washtml($wash_opts); |
| | | $washer = new rcube_washtml($wash_opts); |
| | | |
| | | if (!$p['skip_washer_form_callback']) |
| | | $washer->add_callback('form', 'rcmail_washtml_callback'); |
| | |
| | | |
| | | // convert html to text/plain |
| | | if ($data['type'] == 'html' && $data['plain']) { |
| | | $txt = new html2text($data['body'], false, true); |
| | | $txt = new rcube_html2text($data['body'], false, true); |
| | | $body = $txt->get_text(); |
| | | $part->ctype_secondary = 'plain'; |
| | | } |
| | |
| | | if ($q > $quote_level) { |
| | | $body[$n] = $replacer->get_replacement($replacer->add( |
| | | str_repeat('<blockquote>', $q - $quote_level))) . $body[$n]; |
| | | $last = $n; |
| | | } |
| | | else if ($q < $quote_level) { |
| | | $body[$n] = $replacer->get_replacement($replacer->add( |
| | | str_repeat('</blockquote>', $quote_level - $q))) . $body[$n]; |
| | | $last = $n; |
| | | } |
| | | else if ($flowed) { |
| | | // previous line is flowed |
| | |
| | | |
| | | |
| | | /** |
| | | * Callback function for HTML tags fixing |
| | | */ |
| | | function rcmail_html_tag_callback($matches) |
| | | { |
| | | $tagname = $matches[2]; |
| | | |
| | | $tagname = preg_replace(array( |
| | | '/:.*$/', // Microsoft's Smart Tags <st1:xxxx> |
| | | '/[^a-z0-9_\[\]\!-]/i', // forbidden characters |
| | | ), '', $tagname); |
| | | |
| | | return $matches[1].$tagname; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * return table with message headers |
| | | */ |
| | | function rcmail_message_headers($attrib, $headers=null) |
| | | { |
| | | { |
| | | global $OUTPUT, $MESSAGE, $PRINT_MODE, $RCMAIL; |
| | | static $sa_attrib; |
| | | |
| | |
| | | $out .= html::div('message-partheaders', rcmail_message_headers(sizeof($header_attrib) ? $header_attrib : null, $part->headers)); |
| | | } |
| | | else if ($part->type == 'content') { |
| | | // unsapported |
| | | // unsupported (e.g. encrypted) |
| | | if ($part->realtype) { |
| | | if ($part->realtype == 'multipart/encrypted') { |
| | | if ($part->realtype == 'multipart/encrypted' || $part->realtype == 'application/pkcs7-mime') { |
| | | $out .= html::span('part-notice', rcube_label('encryptedmessage')); |
| | | } |
| | | continue; |
| | |
| | | html::a($show_link + array('class' => 'image-link', 'style' => sprintf('width:%dpx', $thumbnail_size)), |
| | | html::img(array( |
| | | 'class' => 'image-thumbnail', |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true) . '&_thumb=1', |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image') . '&_thumb=1', |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | 'style' => sprintf('max-width:%dpx; max-height:%dpx', $thumbnail_size, $thumbnail_size), |
| | |
| | | html::tag('legend', 'image-filename', Q($attach_prop->filename)) . |
| | | html::p(array('align' => "center"), |
| | | html::img(array( |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, true), |
| | | 'src' => $MESSAGE->get_part_url($attach_prop->mime_id, 'image'), |
| | | 'title' => $attach_prop->filename, |
| | | 'alt' => $attach_prop->filename, |
| | | ))) |
| | |
| | | ) { |
| | | return $types[$extension]; |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * Convert all relative URLs according to a <base> in HTML |
| | | */ |
| | | function rcmail_resolve_base($body) |
| | | { |
| | | // check for <base href=...> |
| | | if (preg_match('!(<base.*href=["\']?)([hftps]{3,5}://[a-z0-9/.%-]+)!i', $body, $regs)) { |
| | | $replacer = new rcube_base_replacer($regs[2]); |
| | | $body = $replacer->replace($body); |
| | | } |
| | | |
| | | return $body; |
| | | } |
| | | |
| | | |
| | |
| | | $name = $part['name']; |
| | | $mailto = $part['mailto']; |
| | | $string = $part['string']; |
| | | $valid = check_email($mailto, false); |
| | | |
| | | // phishing email prevention (#1488981), e.g. "valid@email.addr <phishing@email.addr>" |
| | | if ($name && $valid && $name != $mailto && strpos($name, '@')) { |
| | | $name = ''; |
| | | } |
| | | |
| | | // IDNA ASCII to Unicode |
| | | if ($name == $mailto) |
| | |
| | | // for printing we display all addresses |
| | | continue; |
| | | } |
| | | else if (check_email($part['mailto'], false)) { |
| | | else if ($valid) { |
| | | if ($linked) { |
| | | $address = html::a(array( |
| | | 'href' => 'mailto:'.$mailto, |
| | |
| | | if ($name) |
| | | $address .= Q($name); |
| | | if ($mailto) |
| | | $address .= (strlen($address) ? ' ' : '') . sprintf('<%s>', Q($mailto)); |
| | | $address = trim($address . ' ' . Q($name ? sprintf('<%s>', $mailto) : $mailto)); |
| | | } |
| | | |
| | | $address = html::span('adr', $address); |
| | |
| | | $part = $MESSAGE->mime_parts[$part]; |
| | | $table = new html_table(array('cols' => 3)); |
| | | |
| | | $filename = $part->filename; |
| | | if (empty($filename) && $attach_prop->mimetype == 'text/html') { |
| | | $filename = rcube_label('htmlmessage'); |
| | | } |
| | | $filename = rcmail_attachment_name($part); |
| | | |
| | | if (!empty($filename)) { |
| | | $table->add('title', Q(rcube_label('filename'))); |
| | |
| | | |
| | | return $table->show($attrib); |
| | | } |
| | | |
| | | |
| | | |
| | | function rcmail_message_part_frame($attrib) |
| | |
| | | if ($agent = $RCMAIL->config->get('useragent')) |
| | | $headers['User-Agent'] = $agent; |
| | | |
| | | if ($RCMAIL->config->get('mdn_use_from')) |
| | | $options['mdn_use_from'] = true; |
| | | |
| | | $body = rcube_label("yourmessage") . "\r\n\r\n" . |
| | | "\t" . rcube_label("to") . ': ' . rcube_mime::decode_mime_string($message->headers->to, $message->headers->charset) . "\r\n" . |
| | | "\t" . rcube_label("subject") . ': ' . $message->subject . "\r\n" . |
| | |
| | | $compose->setTXTBody(rc_wordwrap($body, 75, "\r\n")); |
| | | $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline'); |
| | | |
| | | $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file); |
| | | $sent = rcmail_deliver_message($compose, $identity['email'], $mailto, $smtp_error, $body_file, $options); |
| | | |
| | | if ($sent) |
| | | { |
| | |
| | | // application/pdf.A520491B_3BF7_494D_8855_7FAC2C6C0608 |
| | | if (preg_match('/^application\/pdf.+/', $name)) |
| | | $name = 'application/pdf'; |
| | | |
| | | // treat image/pjpeg as image/jpeg |
| | | // treat image/pjpeg (image/pjpg, image/jpg) as image/jpeg (#1489097) |
| | | else if (preg_match('/^image\/p?jpe?g$/', $name)) |
| | | $name = 'image/jpeg'; |
| | | |
| | | return $name; |
| | | } |
| | | |
| | | // return attachment filename, handle empty filename case |
| | | function rcmail_attachment_name($attachment, $display = false) |
| | | { |
| | | $filename = $attachment->filename; |
| | | |
| | | if ($filename === null || $filename === '') { |
| | | if ($attachment->mimetype == 'text/html') { |
| | | $filename = rcube_label('htmlmessage'); |
| | | } |
| | | else { |
| | | $ext = (array) rcube_mime::get_mime_extensions($attachment->mimetype); |
| | | $ext = array_shift($ext); |
| | | $filename = rcube_label('messagepart') . ' ' . $attachment->mime_id; |
| | | if ($ext) { |
| | | $filename .= '.' . $ext; |
| | | } |
| | | } |
| | | } |
| | | |
| | | $filename = preg_replace('[\r\n]', '', $filename); |
| | | |
| | | // Display smart names for some known mimetypes |
| | | if ($display) { |
| | | if (preg_match('/application\/(pgp|pkcs7)-signature/i', $attachment->mimetype)) { |
| | | $filename = rcube_label('digitalsig'); |
| | | } |
| | | } |
| | | |
| | | return $filename; |
| | | } |
| | | |
| | | function rcmail_search_filter($attrib) |
| | | { |
| | | global $OUTPUT, $CONFIG; |