From 8e8f3b96b51fde1df953de7398b15e0f01e10777 Mon Sep 17 00:00:00 2001 From: Aleksander Machniak <alec@alec.pl> Date: Thu, 17 Jan 2013 12:47:01 -0500 Subject: [PATCH] Fix export of selected contacts from search result (#1488905) --- program/steps/mail/compose.inc | 365 ++++++++++++++++++++++++---------------------------- 1 files changed, 168 insertions(+), 197 deletions(-) diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index e57b44a..74c6d5f 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -20,10 +20,10 @@ */ // define constants for message compose mode -define('RCUBE_COMPOSE_REPLY', 0x0106); -define('RCUBE_COMPOSE_FORWARD', 0x0107); -define('RCUBE_COMPOSE_DRAFT', 0x0108); -define('RCUBE_COMPOSE_EDIT', 0x0109); +define('RCUBE_COMPOSE_REPLY', 'reply'); +define('RCUBE_COMPOSE_FORWARD', 'forward'); +define('RCUBE_COMPOSE_DRAFT', 'draft'); +define('RCUBE_COMPOSE_EDIT', 'edit'); $MESSAGE_FORM = null; $COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET); @@ -130,6 +130,7 @@ 'fileuploaderror', 'sendmessage'); $OUTPUT->set_env('compose_id', $COMPOSE['id']); +$OUTPUT->set_pagetitle(rcube_label('compose')); // add config parameters to client script if (!empty($CONFIG['drafts_mbox'])) { @@ -150,30 +151,37 @@ // get reference message and set compose mode if ($msg_uid = $COMPOSE['param']['draft_uid']) { - $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); $compose_mode = RCUBE_COMPOSE_DRAFT; + $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); } -else if ($msg_uid = $COMPOSE['param']['reply_uid']) +else if ($msg_uid = $COMPOSE['param']['reply_uid']) { $compose_mode = RCUBE_COMPOSE_REPLY; -else if ($msg_uid = $COMPOSE['param']['forward_uid']) +} +else if ($msg_uid = $COMPOSE['param']['forward_uid']) { $compose_mode = RCUBE_COMPOSE_FORWARD; -else if ($msg_uid = $COMPOSE['param']['uid']) + $COMPOSE['forward_uid'] = $msg_uid; + $COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']); +} +else if ($msg_uid = $COMPOSE['param']['uid']) { $compose_mode = RCUBE_COMPOSE_EDIT; +} +$OUTPUT->set_env('compose_mode', $compose_mode); $config_show_sig = $RCMAIL->config->get('show_sig', 1); -if ($config_show_sig == 1) +if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { + // don't add signature in draft/edit mode, we'll also not remove the old-one +} +else if ($config_show_sig == 1) $OUTPUT->set_env('show_sig', true); -else if ($config_show_sig == 2 && (empty($compose_mode) || $compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT)) +else if ($config_show_sig == 2 && empty($compose_mode)) $OUTPUT->set_env('show_sig', true); else if ($config_show_sig == 3 && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD)) $OUTPUT->set_env('show_sig', true); -else - $OUTPUT->set_env('show_sig', false); // set line length for body wrapping $LINE_LENGTH = $RCMAIL->config->get('line_length', 72); -if (!empty($msg_uid)) +if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) { // similar as in program/steps/mail/show.inc // re-set 'prefer_html' to have possibility to use html part for compose @@ -187,16 +195,13 @@ if (!empty($MESSAGE->headers->charset)) $RCMAIL->storage->set_charset($MESSAGE->headers->charset); - if ($compose_mode == RCUBE_COMPOSE_REPLY) - { + if ($compose_mode == RCUBE_COMPOSE_REPLY) { $COMPOSE['reply_uid'] = $msg_uid; $COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID; $COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID); if (!empty($COMPOSE['param']['all'])) $MESSAGE->reply_all = $COMPOSE['param']['all']; - - $OUTPUT->set_env('compose_mode', 'reply'); // Save the sent message in the same folder of the message being replied to if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox']) @@ -205,10 +210,8 @@ $COMPOSE['param']['sent_mbox'] = $sent_folder; } } - else if ($compose_mode == RCUBE_COMPOSE_DRAFT) - { - if ($MESSAGE->headers->others['x-draft-info']) - { + else if ($compose_mode == RCUBE_COMPOSE_DRAFT) { + if ($MESSAGE->headers->others['x-draft-info']) { // get reply_uid/forward_uid to flag the original message when sending $info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']); @@ -232,14 +235,6 @@ $COMPOSE['references'] = $MESSAGE->headers->references; } - else if ($compose_mode == RCUBE_COMPOSE_FORWARD) - { - $COMPOSE['forward_uid'] = $msg_uid; - $OUTPUT->set_env('compose_mode', 'forward'); - - if (!empty($COMPOSE['param']['attachment'])) - $MESSAGE->forward_attachment = true; - } } else { $MESSAGE = new stdClass(); @@ -248,18 +243,7 @@ $MESSAGE->compose = array(); // get user's identities -$MESSAGE->identities = $RCMAIL->user->list_identities(); -if (count($MESSAGE->identities)) -{ - foreach ($MESSAGE->identities as $idx => $ident) { - $ident['email'] = format_email($ident['email']); - $email = format_email(rcube_idn_to_utf8($ident['email'])); - - $MESSAGE->identities[$idx]['email_ascii'] = $ident['email']; - $MESSAGE->identities[$idx]['ident'] = format_email_recipient($ident['email'], $ident['name']); - $MESSAGE->identities[$idx]['email'] = $email; - } -} +$MESSAGE->identities = $RCMAIL->user->list_identities(null, true); // Set From field value if (!empty($_POST['_from'])) { @@ -269,83 +253,10 @@ $MESSAGE->compose['from'] = $COMPOSE['param']['from']; } else if (count($MESSAGE->identities)) { - $a_recipients = array(); - $a_names = array(); - - // extract all recipients of the reply-message - if (is_object($MESSAGE->headers) && in_array($compose_mode, array(RCUBE_COMPOSE_REPLY, RCUBE_COMPOSE_FORWARD))) - { - $a_to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, true, $MESSAGE->headers->charset); - foreach ($a_to as $addr) { - if (!empty($addr['mailto'])) { - $a_recipients[] = format_email($addr['mailto']); - $a_names[] = $addr['name']; - } - } - - if (!empty($MESSAGE->headers->cc)) { - $a_cc = rcube_mime::decode_address_list($MESSAGE->headers->cc, null, true, $MESSAGE->headers->charset); - foreach ($a_cc as $addr) { - if (!empty($addr['mailto'])) { - $a_recipients[] = format_email($addr['mailto']); - $a_names[] = $addr['name']; - } - } - } - } - - $from_idx = null; - $default_identity = null; - $return_path = $MESSAGE->headers->others['return-path']; - - // Select identity - foreach ($MESSAGE->identities as $idx => $ident) { - // save default identity ID - if ($ident['standard']) { - $default_identity = $idx; - } - - // use From header - if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { - if ($MESSAGE->headers->from == $ident['ident']) { - $from_idx = $idx; - break; - } - } - // reply to yourself - else if ($compose_mode == RCUBE_COMPOSE_REPLY && $MESSAGE->headers->from == $ident['ident']) { - $from_idx = $idx; - break; - } - // use replied message recipients - else if (($found = array_search($ident['email_ascii'], $a_recipients)) !== false) { - // match identity name, prefer default identity - if ($from_idx === null || ($a_names[$found] && $ident['name'] && $a_names[$found] == $ident['name'])) { - $from_idx = $idx; - } - } - } - - // Fallback using Return-Path - if ($from_idx === null && $return_path) { - foreach ($MESSAGE->identities as $idx => $ident) { - if (strpos($return_path, str_replace('@', '=', $ident['email_ascii']).'@') !== false) { - $from_idx = $idx; - break; - } - } - } - - // Still no ID, use default/first identity - if ($from_idx === null) { - $from_idx = $default_identity !== null ? $default_identity : key(reset($MESSAGE->identities)); - } - - $ident = $MESSAGE->identities[$from_idx]; - $from_id = $ident['identity_id']; + $ident = rcmail_identity_select($MESSAGE, $MESSAGE->identities, $compose_mode); $MESSAGE->compose['from_email'] = $ident['email']; - $MESSAGE->compose['from'] = $from_id; + $MESSAGE->compose['from'] = $ident['identity_id']; } // Set other headers @@ -412,11 +323,11 @@ else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) { // get drafted headers if ($header=='to' && !empty($MESSAGE->headers->to)) - $fvalue = $MESSAGE->get_header('to'); + $fvalue = $MESSAGE->get_header('to', true); else if ($header=='cc' && !empty($MESSAGE->headers->cc)) - $fvalue = $MESSAGE->get_header('cc'); + $fvalue = $MESSAGE->get_header('cc', true); else if ($header=='bcc' && !empty($MESSAGE->headers->bcc)) - $fvalue = $MESSAGE->get_header('bcc'); + $fvalue = $MESSAGE->get_header('bcc', true); else if ($header=='replyto' && !empty($MESSAGE->headers->others['mail-reply-to'])) $fvalue = $MESSAGE->get_header('mail-reply-to'); else if ($header=='replyto' && !empty($MESSAGE->headers->replyto)) @@ -559,7 +470,7 @@ $text = $html = $sql_arr['signature']; if ($sql_arr['html_signature']) { - $h2t = new html2text($sql_arr['signature'], false, false); + $h2t = new rcube_html2text($sql_arr['signature'], false, false); $text = trim($h2t->get_text()); } else { @@ -606,14 +517,17 @@ $html_editor = intval($RCMAIL->config->get('htmleditor')); - if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { - $useHtml = $MESSAGE->has_html_part(false); + if (isset($_POST['_is_html'])) { + $useHtml = !empty($_POST['_is_html']); + } + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + $useHtml = $MESSAGE->has_html_part(false, true); } else if ($compose_mode == RCUBE_COMPOSE_REPLY) { - $useHtml = ($html_editor == 1 || ($html_editor >= 2 && $MESSAGE->has_html_part(false))); + $useHtml = ($html_editor == 1 || ($html_editor >= 2 && $MESSAGE->has_html_part(false, true))); } else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { - $useHtml = ($html_editor == 1 || ($html_editor == 3 && $MESSAGE->has_html_part(false))); + $useHtml = ($html_editor == 1 || ($html_editor == 3 && $MESSAGE->has_html_part(false, true))); } else { $useHtml = ($html_editor == 1); @@ -637,11 +551,11 @@ $isHtml = false; } // forward as attachment - else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) { + else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) { $isHtml = rcmail_compose_editor_mode(); $body = ''; if (empty($COMPOSE['attachments'])) - rcmail_write_forward_attachment($MESSAGE); + rcmail_write_forward_attachments(); } // reply/edit/draft/forward else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || $RCMAIL->config->get('reply_mode') != -1)) { @@ -726,10 +640,15 @@ if ($isHtml) { if ($part->ctype_secondary == 'html') { } + else if ($part->ctype_secondary == 'enriched') { + $body = rcube_enriched::to_html($body); + } else { // try to remove the signature - if ($RCMAIL->config->get('strip_existing_sig', true)) { - $body = rcmail_remove_signature($body); + if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) { + if ($RCMAIL->config->get('strip_existing_sig', true)) { + $body = rcmail_remove_signature($body); + } } // add HTML formatting $body = rcmail_plain_body($body); @@ -739,12 +658,20 @@ } } else { + if ($part->ctype_secondary == 'enriched') { + $body = rcube_enriched::to_html($body); + $part->ctype_secondary = 'html'; + } + if ($part->ctype_secondary == 'html') { // use html part if it has been used for message (pre)viewing // decrease line length for quoting $len = $compose_mode == RCUBE_COMPOSE_REPLY ? $LINE_LENGTH-2 : $LINE_LENGTH; - $txt = new html2text($body, false, true, $len); + $txt = new rcube_html2text($body, false, true, $len); $body = $txt->get_text(); + } + else if ($part->ctype_secondary == 'enriched') { + $body = rcube_enriched::to_html($body); } else { if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') { @@ -752,8 +679,10 @@ } // try to remove the signature - if ($RCMAIL->config->get('strip_existing_sig', true)) { - $body = rcmail_remove_signature($body); + if ($compose_mode != RCUBE_COMPOSE_DRAFT && $compose_mode != RCUBE_COMPOSE_EDIT) { + if ($RCMAIL->config->get('strip_existing_sig', true)) { + $body = rcmail_remove_signature($body); + } } } } @@ -902,9 +831,10 @@ if (!$bodyIsHtml) { $body = preg_replace('/\r?\n/', "\n", $body); + $body = trim($body, "\n"); // soft-wrap and quote message text - $body = rcmail_wrap_and_quote(rtrim($body, "\n"), $LINE_LENGTH); + $body = rcmail_wrap_and_quote($body, $LINE_LENGTH); $prefix .= "\n"; $suffix = ''; @@ -949,8 +879,7 @@ $date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); $charset = $RCMAIL->output->get_charset(); - if (!$bodyIsHtml) - { + if (!$bodyIsHtml) { $prefix = "\n\n\n-------- " . rcube_label('originalmessage') . " --------\n"; $prefix .= rcube_label('subject') . ': ' . $MESSAGE->subject . "\n"; $prefix .= rcube_label('date') . ': ' . $date . "\n"; @@ -963,9 +892,9 @@ $prefix .= rcube_label('replyto') . ': ' . $MESSAGE->get_header('replyto') . "\n"; $prefix .= "\n"; + $body = trim($body, "\r\n"); } - else - { + else { // set is_safe flag (we need this for html body washing) rcmail_check_safe($MESSAGE); // clean up html tags @@ -1047,15 +976,23 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) { - global $RCMAIL, $COMPOSE; + global $RCMAIL, $COMPOSE, $compose_mode; $cid_map = $messages = array(); foreach ((array)$message->mime_parts as $pid => $part) { - if (($part->ctype_primary != 'message' || !$bodyIsHtml) && $part->ctype_primary != 'multipart' && - ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) - && $part->mimetype != 'application/ms-tnef' - ) { + if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { + if ($part->ctype_primary == 'message' || $part->ctype_primary == 'multipart') { + continue; + } + if ($part->mimetype == 'application/ms-tnef') { + continue; + } + // skip inline images when forwarding in plain text + if ($part->content_id && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { + continue; + } + $skip = false; if ($part->mimetype == 'message/rfc822') { $messages[] = $part->mime_id; @@ -1110,55 +1047,86 @@ return $cid_map; } -// Creates an attachment from the forwarded message -function rcmail_write_forward_attachment(&$message) +// Creates attachment(s) from the forwarded message(s) +function rcmail_write_forward_attachments() { - global $RCMAIL, $COMPOSE; + global $RCMAIL, $COMPOSE, $MESSAGE; - if (strlen($message->subject)) { - $name = mb_substr($message->subject, 0, 64) . '.eml'; + $storage = $RCMAIL->get_storage(); + $mem_limit = parse_bytes(ini_get('memory_limit')); + $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB + $names = array(); + + if ($COMPOSE['forward_uid'] == '*') { + $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); + $COMPOSE['forward_uid'] = $index->get(); } else { - $name = 'message_rfc822.eml'; + $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); } - $mem_limit = parse_bytes(ini_get('memory_limit')); - $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB - $data = $path = null; + foreach ((array)$COMPOSE['forward_uid'] as $uid) { + $message = new rcube_message($uid); - // don't load too big attachments into memory - if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) { - $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); - $path = tempnam($temp_dir, 'rcmAttmnt'); - if ($fp = fopen($path, 'w')) { - $RCMAIL->storage->get_raw_body($message->uid, $fp); - fclose($fp); - } else - return false; - } else { - $data = $RCMAIL->storage->get_raw_body($message->uid); + if (empty($message->headers)) { + continue; + } + + if (!empty($message->headers->charset)) { + $storage->set_charset($message->headers->charset); + } + + if (empty($MESSAGE->subject)) { + $MESSAGE->subject = $message->subject; + } + + // generate (unique) attachment name + $name = strlen($message->subject) ? mb_substr($message->subject, 0, 64) : 'message_rfc822'; + if (!empty($names[$name])) { + $names[$name]++; + $name .= '_' . $names[$name]; + } + $names[$name] = 1; + $name .= '.eml'; + + $data = $path = null; + + // don't load too big attachments into memory + if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) { + $temp_dir = unslashify($RCMAIL->config->get('temp_dir')); + $path = tempnam($temp_dir, 'rcmAttmnt'); + if ($fp = fopen($path, 'w')) { + $storage->get_raw_body($message->uid, $fp); + fclose($fp); + } + else { + return false; + } + } + else { + $data = $storage->get_raw_body($message->uid); + $curr_mem += $message->size; + } + + $attachment = array( + 'group' => $COMPOSE['id'], + 'name' => $name, + 'mimetype' => 'message/rfc822', + 'data' => $data, + 'path' => $path, + 'size' => $path ? filesize($path) : strlen($data), + ); + + $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment); + + if ($attachment['status']) { + unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); + $COMPOSE['attachments'][$attachment['id']] = $attachment; + } + else if ($path) { + @unlink($path); + } } - - $attachment = array( - 'group' => $COMPOSE['id'], - 'name' => $name, - 'mimetype' => 'message/rfc822', - 'data' => $data, - 'path' => $path, - 'size' => $path ? filesize($path) : strlen($data), - ); - - $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment); - - if ($attachment['status']) { - unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); - $COMPOSE['attachments'][$attachment['id']] = $attachment; - return true; - } else if ($path) { - @unlink($path); - } - - return false; } @@ -1186,16 +1154,7 @@ } $mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; - $filename = $part->filename; - if (!strlen($filename)) { - if ($mimetype == 'text/html') { - $filename = rcube_label('htmlmessage'); - } - else { - $filename = 'Part_'.$pid; - } - $filename .= '.' . $part->ctype_secondary; - } + $filename = rcmail_attachment_name($part); $attachment = array( 'group' => $COMPOSE['id'], @@ -1437,7 +1396,9 @@ $attrib['value'] = '1'; $checkbox = new html_checkbox($attrib); - if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) + if (isset($_POST['_receipt'])) + $mdn_default = $_POST['_receipt']; + else if (in_array($compose_mode, array(RCUBE_COMPOSE_DRAFT, RCUBE_COMPOSE_EDIT))) $mdn_default = (bool) $MESSAGE->headers->mdn_to; else $mdn_default = $RCMAIL->config->get('mdn_default'); @@ -1464,8 +1425,13 @@ $attrib['value'] = '1'; $checkbox = new html_checkbox($attrib); + if (isset($_POST['_dsn'])) + $dsn_value = $_POST['_dsn']; + else + $dsn_value = $RCMAIL->config->get('dsn_default'); + $out = $form_start ? "$form_start\n" : ''; - $out .= $checkbox->show($RCMAIL->config->get('dsn_default')); + $out .= $checkbox->show($dsn_value); $out .= $form_end ? "\n$form_end" : ''; return $out; @@ -1512,13 +1478,18 @@ 'folder_filter' => 'mail', 'folder_rights' => 'w', ))); - return $select->show($COMPOSE['param']['sent_mbox'], $attrib); + return $select->show(isset($_POST['_store_target']) ? $_POST['_store_target'] : $COMPOSE['param']['sent_mbox'], $attrib); } function rcmail_check_sent_folder($folder, $create=false) { global $RCMAIL; + + // we'll not save the message, so it doesn't matter + if ($RCMAIL->config->get('no_save_sent_messages')) { + return true; + } if ($RCMAIL->storage->folder_exists($folder, true)) { return true; @@ -1577,7 +1548,7 @@ 'rel' => '%s', 'onclick' => "return ".JS_OBJECT_NAME.".command('list-adresses','%s',this)"), '%s')); - foreach ($RCMAIL->get_address_sources() as $j => $source) { + foreach ($RCMAIL->get_address_sources(false, true) as $j => $source) { $id = strval(strlen($source['id']) ? $source['id'] : $j); $js_id = JQ($id); @@ -1590,7 +1561,7 @@ html_identifier($id), $class_name, $source['id'], - $js_id, (!empty($source['name']) ? Q($source['name']) : Q($id))); + $js_id, (!empty($source['name']) ? $source['name'] : $id)); } $OUTPUT->add_gui_object('addressbookslist', $attrib['id']); -- Gitblit v1.9.1