diff options
Diffstat (limited to 'program/steps')
-rw-r--r-- | program/steps/mail/compose.inc | 2490 |
1 files changed, 1260 insertions, 1230 deletions
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index ce70819fd..8303944a9 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -5,7 +5,7 @@ | program/steps/mail/compose.inc | | | | This file is part of the Roundcube Webmail client | - | Copyright (C) 2005-2012, The Roundcube Dev Team | + | Copyright (C) 2005-2013, The Roundcube Dev Team | | | | Licensed under the GNU General Public License version 3 or | | any later version with exceptions for skins & plugins. | @@ -35,73 +35,74 @@ if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID]) // give replicated session storage some time to synchronize $retries = 0; while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) { - usleep(500000); - $RCMAIL->session->reload(); - if ($_SESSION['compose_data_'.$COMPOSE_ID]) - $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; + usleep(500000); + $RCMAIL->session->reload(); + if ($_SESSION['compose_data_'.$COMPOSE_ID]) { + $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; + } } // Nothing below is called during message composition, only at "new/forward/reply/draft" initialization or // if a compose-ID is given (i.e. when the compose step is opened in a new window/tab). -if (!is_array($COMPOSE)) -{ - // Infinite redirect prevention in case of broken session (#1487028) - if ($COMPOSE_ID) - rcube::raise_error(array('code' => 500, 'type' => 'php', - 'file' => __FILE__, 'line' => __LINE__, - 'message' => "Invalid compose ID"), true, true); - - $COMPOSE_ID = uniqid(mt_rand()); - $_SESSION['compose_data_'.$COMPOSE_ID] = array( - 'id' => $COMPOSE_ID, - 'param' => rcube_utils::request2param(rcube_utils::INPUT_GET, 'task|action', true), - 'mailbox' => $RCMAIL->storage->get_folder(), - ); - $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; +if (!is_array($COMPOSE)) { + // Infinite redirect prevention in case of broken session (#1487028) + if ($COMPOSE_ID) { + rcube::raise_error(array('code' => 500, 'type' => 'php', + 'file' => __FILE__, 'line' => __LINE__, + 'message' => "Invalid compose ID"), true, true); + } - rcmail_process_compose_params($COMPOSE); - - // add attachments listed by message_compose hook - if (is_array($plugin['attachments'])) { - foreach ($plugin['attachments'] as $attach) { - // we have structured data - if (is_array($attach)) { - $attachment = $attach; - } - // only a file path is given - else { - $filename = basename($attach); - $attachment = array( - 'group' => $COMPOSE_ID, - 'name' => $filename, - 'mimetype' => rcube_mime::file_content_type($attach, $filename), - 'path' => $attach, - ); - } - - // save attachment if valid - if (($attachment['data'] && $attachment['name']) || ($attachment['path'] && file_exists($attachment['path']))) { - $attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); - } - - if ($attachment['status'] && !$attachment['abort']) { - unset($attachment['data'], $attachment['status'], $attachment['abort']); - $COMPOSE['attachments'][$attachment['id']] = $attachment; - } - } - } - - // check if folder for saving sent messages exists and is subscribed (#1486802) - if ($sent_folder = $COMPOSE['param']['sent_mbox']) { - rcmail_check_sent_folder($sent_folder, true); - } - - // redirect to a unique URL with all parameters stored in session - $OUTPUT->redirect(array( - '_action' => 'compose', - '_id' => $COMPOSE['id'], - '_search' => $_REQUEST['_search'], - )); + $COMPOSE_ID = uniqid(mt_rand()); + $_SESSION['compose_data_'.$COMPOSE_ID] = array( + 'id' => $COMPOSE_ID, + 'param' => rcube_utils::request2param(rcube_utils::INPUT_GET, 'task|action', true), + 'mailbox' => $RCMAIL->storage->get_folder(), + ); + $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID]; + + rcmail_process_compose_params($COMPOSE); + + // add attachments listed by message_compose hook + if (is_array($plugin['attachments'])) { + foreach ($plugin['attachments'] as $attach) { + // we have structured data + if (is_array($attach)) { + $attachment = $attach; + } + // only a file path is given + else { + $filename = basename($attach); + $attachment = array( + 'group' => $COMPOSE_ID, + 'name' => $filename, + 'mimetype' => rcube_mime::file_content_type($attach, $filename), + 'path' => $attach, + ); + } + + // save attachment if valid + if (($attachment['data'] && $attachment['name']) || ($attachment['path'] && file_exists($attachment['path']))) { + $attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); + } + + if ($attachment['status'] && !$attachment['abort']) { + unset($attachment['data'], $attachment['status'], $attachment['abort']); + $COMPOSE['attachments'][$attachment['id']] = $attachment; + } + } + } + + // check if folder for saving sent messages exists and is subscribed (#1486802) + if ($sent_folder = $COMPOSE['param']['sent_mbox']) { + rcmail_check_sent_folder($sent_folder, true); + } + + // redirect to a unique URL with all parameters stored in session + $OUTPUT->redirect(array( + '_action' => 'compose', + '_id' => $COMPOSE['id'], + '_search' => $_REQUEST['_search'], + )); } @@ -112,47 +113,47 @@ $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubj 'fileuploaderror', 'sendmessage', 'savenewresponse', 'responsename', 'responsetext', 'save', 'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore'); +$OUTPUT->set_pagetitle($RCMAIL->gettext('compose')); + $OUTPUT->set_env('compose_id', $COMPOSE['id']); $OUTPUT->set_env('session_id', session_id()); -$OUTPUT->set_pagetitle($RCMAIL->gettext('compose')); +$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); +$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); +$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); // add config parameters to client script if (!empty($CONFIG['drafts_mbox'])) { - $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']); - $OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']); + $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']); + $OUTPUT->set_env('draft_autosave', $CONFIG['draft_autosave']); } -// set current mailbox in client environment -$OUTPUT->set_env('mailbox', $RCMAIL->storage->get_folder()); -$OUTPUT->set_env('top_posting', intval($RCMAIL->config->get('reply_mode')) > 0); -$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ','))); // default font for HTML editor $font = rcmail::font_defs($RCMAIL->config->get('default_font')); if ($font && !is_array($font)) { - $OUTPUT->set_env('default_font', $font); + $OUTPUT->set_env('default_font', $font); } // default font size for HTML editor if ($font_size = $RCMAIL->config->get('default_font_size')) { - $OUTPUT->set_env('default_font_size', $font_size); + $OUTPUT->set_env('default_font_size', $font_size); } // get reference message and set compose mode if ($msg_uid = $COMPOSE['param']['draft_uid']) { - $compose_mode = RCUBE_COMPOSE_DRAFT; - $OUTPUT->set_env('draft_id', $msg_uid); - $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); + $compose_mode = RCUBE_COMPOSE_DRAFT; + $OUTPUT->set_env('draft_id', $msg_uid); + $RCMAIL->storage->set_folder($CONFIG['drafts_mbox']); } else if ($msg_uid = $COMPOSE['param']['reply_uid']) { - $compose_mode = RCUBE_COMPOSE_REPLY; + $compose_mode = RCUBE_COMPOSE_REPLY; } else if ($msg_uid = $COMPOSE['param']['forward_uid']) { - $compose_mode = RCUBE_COMPOSE_FORWARD; - $COMPOSE['forward_uid'] = $msg_uid; - $COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']); + $compose_mode = RCUBE_COMPOSE_FORWARD; + $COMPOSE['forward_uid'] = $msg_uid; + $COMPOSE['as_attachment'] = !empty($COMPOSE['param']['attachment']); } else if ($msg_uid = $COMPOSE['param']['uid']) { - $compose_mode = RCUBE_COMPOSE_EDIT; + $compose_mode = RCUBE_COMPOSE_EDIT; } $COMPOSE['mode'] = $compose_mode; @@ -160,105 +161,110 @@ $OUTPUT->set_env('compose_mode', $compose_mode); $config_show_sig = $RCMAIL->config->get('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 - // but only on page display, later we should be able to change identity/sig (#1489229) - if ($config_show_sig == 1 || $config_show_sig == 2) - $OUTPUT->set_env('show_sig_later', true); + // don't add signature in draft/edit mode, we'll also not remove the old-one + // but only on page display, later we should be able to change identity/sig (#1489229) + if ($config_show_sig == 1 || $config_show_sig == 2) { + $OUTPUT->set_env('show_sig_later', true); + } } else if ($config_show_sig == 1) - $OUTPUT->set_env('show_sig', true); + $OUTPUT->set_env('show_sig', true); else if ($config_show_sig == 2 && empty($compose_mode)) - $OUTPUT->set_env('show_sig', true); + $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); + $OUTPUT->set_env('show_sig', true); // set line length for body wrapping $LINE_LENGTH = $RCMAIL->config->get('line_length', 72); -if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) -{ - $mbox_name = $RCMAIL->storage->get_folder(); - - // set format before rcube_message construction - // use the same format as for the message view - if (isset($_SESSION['msg_formats'][$mbox_name.':'.$msg_uid])) { - $RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$msg_uid]); - } - else { - $prefer_html = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT; - $RCMAIL->config->set('prefer_html', $prefer_html); - } - - $MESSAGE = new rcube_message($msg_uid); - - // make sure message is marked as read - if ($MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN'])) - $RCMAIL->storage->set_flag($msg_uid, 'SEEN'); - - if (!empty($MESSAGE->headers->charset)) - $RCMAIL->storage->set_charset($MESSAGE->headers->charset); - - if (!$MESSAGE->headers) { - // error - } - else 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']; - - // 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']) - && rcmail_check_sent_folder($sent_folder, false) - ) { - $COMPOSE['param']['sent_mbox'] = $sent_folder; +if (!empty($msg_uid) && empty($COMPOSE['as_attachment'])) { + $mbox_name = $RCMAIL->storage->get_folder(); + + // set format before rcube_message construction + // use the same format as for the message view + if (isset($_SESSION['msg_formats'][$mbox_name.':'.$msg_uid])) { + $RCMAIL->config->set('prefer_html', $_SESSION['msg_formats'][$mbox_name.':'.$msg_uid]); + } + else { + $prefer_html = $CONFIG['prefer_html'] || $CONFIG['htmleditor'] || $compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT; + $RCMAIL->config->set('prefer_html', $prefer_html); + } + + $MESSAGE = new rcube_message($msg_uid); + + // make sure message is marked as read + if ($MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN'])) { + $RCMAIL->storage->set_flag($msg_uid, 'SEEN'); } - } - else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { - if ($compose_mode == RCUBE_COMPOSE_DRAFT) { - if ($draft_info = $MESSAGE->headers->get('x-draft-info')) { - // get reply_uid/forward_uid to flag the original message when sending - $info = rcmail_draftinfo_decode($draft_info); - if ($info['type'] == 'reply') - $COMPOSE['reply_uid'] = $info['uid']; - else if ($info['type'] == 'forward') - $COMPOSE['forward_uid'] = $info['uid']; + if (!empty($MESSAGE->headers->charset)) { + $RCMAIL->storage->set_charset($MESSAGE->headers->charset); + } + + if (!$MESSAGE->headers) { + // error + } + else 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); - $COMPOSE['mailbox'] = $info['folder']; + if (!empty($COMPOSE['param']['all'])) { + $MESSAGE->reply_all = $COMPOSE['param']['all']; + } // Save the sent message in the same folder of the message being replied to - if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder']) - && rcmail_check_sent_folder($sent_folder, false) + if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox']) + && rcmail_check_sent_folder($sent_folder, false) ) { - $COMPOSE['param']['sent_mbox'] = $sent_folder; + $COMPOSE['param']['sent_mbox'] = $sent_folder; } - } + } + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + if ($compose_mode == RCUBE_COMPOSE_DRAFT) { + if ($draft_info = $MESSAGE->headers->get('x-draft-info')) { + // get reply_uid/forward_uid to flag the original message when sending + $info = rcmail_draftinfo_decode($draft_info); + + if ($info['type'] == 'reply') + $COMPOSE['reply_uid'] = $info['uid']; + else if ($info['type'] == 'forward') + $COMPOSE['forward_uid'] = $info['uid']; + + $COMPOSE['mailbox'] = $info['folder']; + + // Save the sent message in the same folder of the message being replied to + if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $info['folder']) + && rcmail_check_sent_folder($sent_folder, false) + ) { + $COMPOSE['param']['sent_mbox'] = $sent_folder; + } + } - $COMPOSE['param']['message-id'] = $MESSAGE->headers->get('message-id'); + $COMPOSE['param']['message-id'] = $MESSAGE->headers->get('message-id'); - // use message UID as draft_id - $OUTPUT->set_env('draft_id', $msg_uid); - } + // use message UID as draft_id + $OUTPUT->set_env('draft_id', $msg_uid); + } - if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) - $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>'; + if ($in_reply_to = $MESSAGE->headers->get('in-reply-to')) { + $COMPOSE['reply_msgid'] = '<' . $in_reply_to . '>'; + } - $COMPOSE['references'] = $MESSAGE->headers->references; - } + $COMPOSE['references'] = $MESSAGE->headers->references; + } } else { - $MESSAGE = new stdClass(); - - // apply mailto: URL parameters - if (!empty($COMPOSE['param']['in-reply-to'])) { - $COMPOSE['reply_msgid'] = '<' . $COMPOSE['param']['in-reply-to'] . '>'; - } - if (!empty($COMPOSE['param']['references'])) { - $COMPOSE['references'] = $COMPOSE['param']['references']; - } + $MESSAGE = new stdClass(); + + // apply mailto: URL parameters + if (!empty($COMPOSE['param']['in-reply-to'])) { + $COMPOSE['reply_msgid'] = '<' . $COMPOSE['param']['in-reply-to'] . '>'; + } + + if (!empty($COMPOSE['param']['references'])) { + $COMPOSE['references'] = $COMPOSE['param']['references']; + } } $MESSAGE->compose = array(); @@ -268,16 +274,16 @@ $MESSAGE->identities = $RCMAIL->user->list_identities(null, true); // Set From field value if (!empty($_POST['_from'])) { - $MESSAGE->compose['from'] = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST); + $MESSAGE->compose['from'] = rcube_utils::get_input_value('_from', rcube_utils::INPUT_POST); } else if (!empty($COMPOSE['param']['from'])) { - $MESSAGE->compose['from'] = $COMPOSE['param']['from']; + $MESSAGE->compose['from'] = $COMPOSE['param']['from']; } else if (count($MESSAGE->identities)) { - $ident = rcmail_identity_select($MESSAGE, $MESSAGE->identities, $compose_mode); + $ident = rcmail_identity_select($MESSAGE, $MESSAGE->identities, $compose_mode); - $MESSAGE->compose['from_email'] = $ident['email']; - $MESSAGE->compose['from'] = $ident['identity_id']; + $MESSAGE->compose['from_email'] = $ident['email']; + $MESSAGE->compose['from'] = $ident['identity_id']; } // Set other headers @@ -286,124 +292,123 @@ $parts = array('to', 'cc', 'bcc', 'replyto', 'followupto'); $separator = trim($RCMAIL->config->get('recipients_separator', ',')) . ' '; foreach ($parts as $header) { - $fvalue = ''; - $decode_header = true; - - // we have a set of recipients stored is session - if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto']) - && $_SESSION['mailto'][$mailto_id] - ) { - $fvalue = urldecode($_SESSION['mailto'][$mailto_id]); - $decode_header = false; - - // make session to not grow up too much - unset($_SESSION['mailto'][$mailto_id]); - $COMPOSE['param']['to'] = $fvalue; - } - else if (!empty($_POST['_'.$header])) { - $fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE); - } - else if (!empty($COMPOSE['param'][$header])) { - $fvalue = $COMPOSE['param'][$header]; - } - else if ($compose_mode == RCUBE_COMPOSE_REPLY) { - // get recipent address(es) out of the message headers - if ($header == 'to') { - $mailfollowup = $MESSAGE->headers->others['mail-followup-to']; - $mailreplyto = $MESSAGE->headers->others['mail-reply-to']; - - // Reply to mailing list... - if ($MESSAGE->reply_all == 'list' && $mailfollowup) - $fvalue = $mailfollowup; - else if ($MESSAGE->reply_all == 'list' - && preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m)) - $fvalue = $m[1]; - // Reply to... - else if ($MESSAGE->reply_all && $mailfollowup) - $fvalue = $mailfollowup; - else if ($mailreplyto) - $fvalue = $mailreplyto; - else if (!empty($MESSAGE->headers->replyto)) - $fvalue = $MESSAGE->headers->replyto; - else if (!empty($MESSAGE->headers->from)) - $fvalue = $MESSAGE->headers->from; - - // Reply to message sent by yourself (#1487074, #1489230) - if (!empty($ident) && in_array($ident['ident'], array($fvalue, $MESSAGE->headers->from))) { - $fvalue = $MESSAGE->headers->to; - } - } - // add recipient of original message if reply to all - else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') { - if ($v = $MESSAGE->headers->to) - $fvalue .= $v; - if ($v = $MESSAGE->headers->cc) - $fvalue .= (!empty($fvalue) ? $separator : '') . $v; - // Use Sender header (#1489011) - if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false) - $fvalue .= (!empty($fvalue) ? $separator : '') . $v; - - // When To: and Reply-To: are the same we add From: address to the list (#1489037) - if ($v = $MESSAGE->headers->from) { - $from = rcube_mime::decode_address_list($v, null, false, $MESSAGE->headers->charset, true); - $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $MESSAGE->headers->charset, true); - $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $MESSAGE->headers->charset, true); - - if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { - $fvalue .= (!empty($fvalue) ? $separator : '') . $v; - } - } - } - } - 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', true); - else if ($header=='cc' && !empty($MESSAGE->headers->cc)) - $fvalue = $MESSAGE->get_header('cc', true); - else if ($header=='bcc' && !empty($MESSAGE->headers->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)) - $fvalue = $MESSAGE->get_header('reply-to'); - else if ($header=='followupto' && !empty($MESSAGE->headers->others['mail-followup-to'])) - $fvalue = $MESSAGE->get_header('mail-followup-to'); - } - - // split recipients and put them back together in a unique way - if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) { - $to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $MESSAGE->headers->charset); - $fvalue = array(); - - foreach ($to_addresses as $addr_part) { - if (empty($addr_part['mailto'])) - continue; - - $mailto = format_email(rcube_utils::idn_to_utf8($addr_part['mailto'])); - - if (!in_array($mailto, $a_recipients) - && ( - $header == 'to' - || $compose_mode != RCUBE_COMPOSE_REPLY - || empty($MESSAGE->compose['from_email']) - || $mailto != $MESSAGE->compose['from_email'] - ) - ) { - if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) - $string = format_email_recipient($mailto, $addr_part['name']); - else - $string = $mailto; + $fvalue = ''; + $decode_header = true; + + // we have a set of recipients stored is session + if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto']) + && $_SESSION['mailto'][$mailto_id] + ) { + $fvalue = urldecode($_SESSION['mailto'][$mailto_id]); + $decode_header = false; - $fvalue[] = $string; - $a_recipients[] = $addr_part['mailto']; - } + // make session to not grow up too much + unset($_SESSION['mailto'][$mailto_id]); + $COMPOSE['param']['to'] = $fvalue; } + else if (!empty($_POST['_'.$header])) { + $fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE); + } + else if (!empty($COMPOSE['param'][$header])) { + $fvalue = $COMPOSE['param'][$header]; + } + else if ($compose_mode == RCUBE_COMPOSE_REPLY) { + // get recipent address(es) out of the message headers + if ($header == 'to') { + $mailfollowup = $MESSAGE->headers->others['mail-followup-to']; + $mailreplyto = $MESSAGE->headers->others['mail-reply-to']; + + // Reply to mailing list... + if ($MESSAGE->reply_all == 'list' && $mailfollowup) + $fvalue = $mailfollowup; + else if ($MESSAGE->reply_all == 'list' + && preg_match('/<mailto:([^>]+)>/i', $MESSAGE->headers->others['list-post'], $m)) + $fvalue = $m[1]; + // Reply to... + else if ($MESSAGE->reply_all && $mailfollowup) + $fvalue = $mailfollowup; + else if ($mailreplyto) + $fvalue = $mailreplyto; + else if (!empty($MESSAGE->headers->replyto)) + $fvalue = $MESSAGE->headers->replyto; + else if (!empty($MESSAGE->headers->from)) + $fvalue = $MESSAGE->headers->from; + + // Reply to message sent by yourself (#1487074, #1489230) + if (!empty($ident) && in_array($ident['ident'], array($fvalue, $MESSAGE->headers->from))) { + $fvalue = $MESSAGE->headers->to; + } + } + // add recipient of original message if reply to all + else if ($header == 'cc' && !empty($MESSAGE->reply_all) && $MESSAGE->reply_all != 'list') { + if ($v = $MESSAGE->headers->to) + $fvalue .= $v; + if ($v = $MESSAGE->headers->cc) + $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + // Use Sender header (#1489011) + if (($v = $MESSAGE->headers->get('Sender', false)) && strpos($v, '-bounces@') === false) + $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + + // When To: and Reply-To: are the same we add From: address to the list (#1489037) + if ($v = $MESSAGE->headers->from) { + $from = rcube_mime::decode_address_list($v, null, false, $MESSAGE->headers->charset, true); + $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $MESSAGE->headers->charset, true); + $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $MESSAGE->headers->charset, true); + + if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { + $fvalue .= (!empty($fvalue) ? $separator : '') . $v; + } + } + } + } + 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', true); + else if ($header=='cc' && !empty($MESSAGE->headers->cc)) + $fvalue = $MESSAGE->get_header('cc', true); + else if ($header=='bcc' && !empty($MESSAGE->headers->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)) + $fvalue = $MESSAGE->get_header('reply-to'); + else if ($header=='followupto' && !empty($MESSAGE->headers->others['mail-followup-to'])) + $fvalue = $MESSAGE->get_header('mail-followup-to'); + } + + // split recipients and put them back together in a unique way + if (!empty($fvalue) && in_array($header, array('to', 'cc', 'bcc'))) { + $to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $MESSAGE->headers->charset); + $fvalue = array(); - $fvalue = implode($separator, $fvalue); - } + foreach ($to_addresses as $addr_part) { + if (empty($addr_part['mailto'])) { + continue; + } + + $mailto = format_email(rcube_utils::idn_to_utf8($addr_part['mailto'])); + + if (!in_array($mailto, $a_recipients) + && ($header == 'to' + || $compose_mode != RCUBE_COMPOSE_REPLY + || empty($MESSAGE->compose['from_email']) + || $mailto != $MESSAGE->compose['from_email']) + ) { + if ($addr_part['name'] && $addr_part['mailto'] != $addr_part['name']) + $string = format_email_recipient($mailto, $addr_part['name']); + else + $string = $mailto; + + $fvalue[] = $string; + $a_recipients[] = $addr_part['mailto']; + } + } + + $fvalue = implode($separator, $fvalue); + } - $MESSAGE->compose[$header] = $fvalue; + $MESSAGE->compose[$header] = $fvalue; } unset($a_recipients); @@ -411,327 +416,354 @@ unset($a_recipients); $MESSAGE_BODY = rcmail_prepare_message_body(); +// register UI objects +$OUTPUT->add_handlers(array( + 'composeheaders' => 'rcmail_compose_headers', + 'composesubject' => 'rcmail_compose_subject', + 'composebody' => 'rcmail_compose_body', + 'composeattachmentlist' => 'rcmail_compose_attachment_list', + 'composeattachmentform' => 'rcmail_compose_attachment_form', + 'composeattachment' => 'rcmail_compose_attachment_field', + 'filedroparea' => 'compose_file_drop_area', + 'priorityselector' => 'rcmail_priority_selector', + 'editorselector' => 'rcmail_editor_selector', + 'receiptcheckbox' => 'rcmail_receipt_checkbox', + 'dsncheckbox' => 'rcmail_dsn_checkbox', + 'storetarget' => 'rcmail_store_target_selection', + 'addressbooks' => 'rcmail_addressbook_list', + 'addresslist' => 'rcmail_contacts_list', + 'responseslist' => 'rcmail_compose_responses_list', +)); + +$OUTPUT->send('compose'); + + /****** compose mode functions ********/ // process compose request parameters function rcmail_process_compose_params(&$COMPOSE) { - if ($COMPOSE['param']['to']) { - $mailto = explode('?', $COMPOSE['param']['to'], 2); + if ($COMPOSE['param']['to']) { + $mailto = explode('?', $COMPOSE['param']['to'], 2); - // #1486037: remove "mailto:" prefix - $COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $mailto[0]); + // #1486037: remove "mailto:" prefix + $COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $mailto[0]); - // Supported case-insensitive tokens in mailto URL - $url_tokens = array('to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'body'); + // Supported case-insensitive tokens in mailto URL + $url_tokens = array('to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'body'); - if (!empty($mailto[1])) { - parse_str($mailto[1], $query); - foreach ($query as $f => $val) { - if (($key = array_search(strtolower($f), $url_tokens)) !== false) { - $f = $url_tokens[$key]; - } + if (!empty($mailto[1])) { + parse_str($mailto[1], $query); + foreach ($query as $f => $val) { + if (($key = array_search(strtolower($f), $url_tokens)) !== false) { + $f = $url_tokens[$key]; + } - // merge mailto: addresses with addresses from 'to' parameter - if ($f == 'to' && !empty($COMPOSE['param']['to'])) { - $to_addresses = rcube_mime::decode_address_list($COMPOSE['param']['to'], null, true, null, true); - $add_addresses = rcube_mime::decode_address_list($val, null, true); - foreach ($add_addresses as $addr) { - if (!in_array($addr['mailto'], $to_addresses)) { - $to_addresses[] = $addr['mailto']; - $COMPOSE['param']['to'] = (!empty($to_addresses) ? ', ' : '') . $addr['string']; + // merge mailto: addresses with addresses from 'to' parameter + if ($f == 'to' && !empty($COMPOSE['param']['to'])) { + $to_addresses = rcube_mime::decode_address_list($COMPOSE['param']['to'], null, true, null, true); + $add_addresses = rcube_mime::decode_address_list($val, null, true); + + foreach ($add_addresses as $addr) { + if (!in_array($addr['mailto'], $to_addresses)) { + $to_addresses[] = $addr['mailto']; + $COMPOSE['param']['to'] = (!empty($to_addresses) ? ', ' : '') . $addr['string']; + } + } + } + else { + $COMPOSE['param'][$f] = $val; + } } - } - } - else { - $COMPOSE['param'][$f] = $val; } - } } - } - // clean HTML message body which can be submitted by URL - if ($COMPOSE['param']['body']) { - $COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], array('safe' => false, 'inline_html' => true), array()); - } + // clean HTML message body which can be submitted by URL + if (!empty($COMPOSE['param']['body'])) { + $COMPOSE['param']['body'] = rcmail_wash_html($COMPOSE['param']['body'], array('safe' => false, 'inline_html' => true), array()); + } - $RCMAIL = rcmail::get_instance(); + $RCMAIL = rcmail::get_instance(); - // select folder where to save the sent message - $COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox'); + // select folder where to save the sent message + $COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox'); - // pipe compose parameters thru plugins - $plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE); - $COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']); + // pipe compose parameters thru plugins + $plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE); + $COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']); } function rcmail_compose_headers($attrib) { - global $RCMAIL, $MESSAGE; + global $RCMAIL, $MESSAGE; - list($form_start,) = get_form_tags($attrib); + list($form_start,) = get_form_tags($attrib); - $out = ''; - $part = strtolower($attrib['part']); + $out = ''; + $part = strtolower($attrib['part']); - switch ($part) - { + switch ($part) { case 'from': - return $form_start . rcmail_compose_header_from($attrib); + return $form_start . rcmail_compose_header_from($attrib); case 'to': case 'cc': case 'bcc': - $fname = '_' . $part; - $header = $param = $part; + $fname = '_' . $part; + $header = $param = $part; - $allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex'); - $field_type = 'html_textarea'; - break; + $allow_attrib = array('id', 'class', 'style', 'cols', 'rows', 'tabindex'); + $field_type = 'html_textarea'; + break; case 'replyto': case 'reply-to': - $fname = '_replyto'; - $param = 'replyto'; - $header = 'reply-to'; + $fname = '_replyto'; + $param = 'replyto'; + $header = 'reply-to'; case 'followupto': case 'followup-to': - if (!$fname) { - $fname = '_followupto'; - $param = 'followupto'; - $header = 'mail-followup-to'; - } - - $allow_attrib = array('id', 'class', 'style', 'size', 'tabindex'); - $field_type = 'html_inputfield'; - break; - } - - if ($fname && $field_type) - { - // pass the following attributes to the form class - $field_attrib = array('name' => $fname, 'spellcheck' => 'false'); - foreach ($attrib as $attr => $value) - if (in_array($attr, $allow_attrib)) - $field_attrib[$attr] = $value; + if (!$fname) { + $fname = '_followupto'; + $param = 'followupto'; + $header = 'mail-followup-to'; + } + + $allow_attrib = array('id', 'class', 'style', 'size', 'tabindex'); + $field_type = 'html_inputfield'; + break; + } + + if ($fname && $field_type) { + // pass the following attributes to the form class + $field_attrib = array('name' => $fname, 'spellcheck' => 'false'); + foreach ($attrib as $attr => $value) { + if (in_array($attr, $allow_attrib)) { + $field_attrib[$attr] = $value; + } + } - // create teaxtarea object - $input = new $field_type($field_attrib); - $out = $input->show($MESSAGE->compose[$param]); - } + // create teaxtarea object + $input = new $field_type($field_attrib); + $out = $input->show($MESSAGE->compose[$param]); + } - if ($form_start) - $out = $form_start.$out; + if ($form_start) { + $out = $form_start . $out; + } - // configure autocompletion - $RCMAIL->autocomplete_init(); + // configure autocompletion + $RCMAIL->autocomplete_init(); - return $out; + return $out; } function rcmail_compose_header_from($attrib) { - global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode; - - // pass the following attributes to the form class - $field_attrib = array('name' => '_from'); - foreach ($attrib as $attr => $value) - if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) - $field_attrib[$attr] = $value; - - if (count($MESSAGE->identities)) - { - $a_signatures = array(); - $identities = array(); - $separator = intval($RCMAIL->config->get('reply_mode')) > 0 - && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- '; - - $field_attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.".change_identity(this)"; - $select_from = new html_select($field_attrib); - - // create SELECT element - foreach ($MESSAGE->identities as $sql_arr) - { - $identity_id = $sql_arr['identity_id']; - $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id); - - // add signature to array - if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig'])) - { - $text = $html = $sql_arr['signature']; - - if ($sql_arr['html_signature']) { - $h2t = new rcube_html2text($sql_arr['signature'], false, false); - $text = trim($h2t->get_text()); - } - else { - $html = htmlentities($html, ENT_NOQUOTES, RCUBE_CHARSET); - } + global $MESSAGE, $OUTPUT, $RCMAIL, $COMPOSE, $compose_mode; - if (!preg_match('/^--[ -]\r?\n/m', $text)) { - $text = $separator . "\n" . $text; - $html = $separator . "<br>" . $html; + // pass the following attributes to the form class + $field_attrib = array('name' => '_from'); + foreach ($attrib as $attr => $value) { + if (in_array($attr, array('id', 'class', 'style', 'size', 'tabindex'))) { + $field_attrib[$attr] = $value; } + } + + if (count($MESSAGE->identities)) { + $a_signatures = array(); + $identities = array(); + $separator = intval($RCMAIL->config->get('reply_mode')) > 0 + && ($compose_mode == RCUBE_COMPOSE_REPLY || $compose_mode == RCUBE_COMPOSE_FORWARD) ? '---' : '-- '; + + $field_attrib['onchange'] = rcmail_output::JS_OBJECT_NAME.".change_identity(this)"; + $select_from = new html_select($field_attrib); + + // create SELECT element + foreach ($MESSAGE->identities as $sql_arr) { + $identity_id = $sql_arr['identity_id']; + $select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id); - if (!$sql_arr['html_signature']) { - $html = "<pre>" . $html . "</pre>"; + // add signature to array + if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig'])) { + $text = $html = $sql_arr['signature']; + + if ($sql_arr['html_signature']) { + $h2t = new rcube_html2text($sql_arr['signature'], false, false); + $text = trim($h2t->get_text()); + } + else { + $html = htmlentities($html, ENT_NOQUOTES, RCUBE_CHARSET); + } + + if (!preg_match('/^--[ -]\r?\n/m', $text)) { + $text = $separator . "\n" . $text; + $html = $separator . "<br>" . $html; + } + + if (!$sql_arr['html_signature']) { + $html = "<pre>" . $html . "</pre>"; + } + + $a_signatures[$identity_id]['text'] = $text; + $a_signatures[$identity_id]['html'] = $html; + } + + // add bcc and reply-to + if (!empty($sql_arr['reply-to'])) { + $identities[$identity_id]['replyto'] = $sql_arr['reply-to']; + } + if (!empty($sql_arr['bcc'])) { + $identities[$identity_id]['bcc'] = $sql_arr['bcc']; + } } - $a_signatures[$identity_id]['text'] = $text; - $a_signatures[$identity_id]['html'] = $html; - } - - // add bcc and reply-to - if (!empty($sql_arr['reply-to'])) { - $identities[$identity_id]['replyto'] = $sql_arr['reply-to']; - } - if (!empty($sql_arr['bcc'])) { - $identities[$identity_id]['bcc'] = $sql_arr['bcc']; - } - } - - $out = $select_from->show($MESSAGE->compose['from']); - - // add signatures to client - $OUTPUT->set_env('signatures', $a_signatures); - $OUTPUT->set_env('identities', $identities); - } - // no identities, display text input field - else { - $field_attrib['class'] = 'from_address'; - $input_from = new html_inputfield($field_attrib); - $out = $input_from->show($MESSAGE->compose['from']); - } - - return $out; + $out = $select_from->show($MESSAGE->compose['from']); + + // add signatures to client + $OUTPUT->set_env('signatures', $a_signatures); + $OUTPUT->set_env('identities', $identities); + } + // no identities, display text input field + else { + $field_attrib['class'] = 'from_address'; + $input_from = new html_inputfield($field_attrib); + $out = $input_from->show($MESSAGE->compose['from']); + } + + return $out; } function rcmail_compose_editor_mode() { - global $RCMAIL, $compose_mode; - static $useHtml; + global $RCMAIL, $compose_mode; + static $useHtml; - if ($useHtml !== null) - return $useHtml; + if ($useHtml !== null) { + return $useHtml; + } + + $html_editor = intval($RCMAIL->config->get('htmleditor')); + + if (isset($_POST['_is_html'])) { + $useHtml = !empty($_POST['_is_html']); + } + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + $useHtml = rcmail_message_is_html(); + } + else if ($compose_mode == RCUBE_COMPOSE_REPLY) { + $useHtml = ($html_editor == 1 || ($html_editor >= 2 && rcmail_message_is_html())); + } + else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { + $useHtml = ($html_editor == 1 || ($html_editor == 3 && rcmail_message_is_html())); + } + else { + $useHtml = ($html_editor == 1); + } - $html_editor = intval($RCMAIL->config->get('htmleditor')); - - if (isset($_POST['_is_html'])) { - $useHtml = !empty($_POST['_is_html']); - } - else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { - $useHtml = rcmail_message_is_html(); - } - else if ($compose_mode == RCUBE_COMPOSE_REPLY) { - $useHtml = ($html_editor == 1 || ($html_editor >= 2 && rcmail_message_is_html())); - } - else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { - $useHtml = ($html_editor == 1 || ($html_editor == 3 && rcmail_message_is_html())); - } - else { - $useHtml = ($html_editor == 1); - } - - return $useHtml; + return $useHtml; } function rcmail_message_is_html() { global $RCMAIL, $MESSAGE; + return $RCMAIL->config->get('prefer_html') && ($MESSAGE instanceof rcube_message) && $MESSAGE->has_html_part(true); } function rcmail_prepare_message_body() { - global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE; - - // use posted message body - if (!empty($_POST['_message'])) { - $body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, true); - $isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST); - } - else if ($COMPOSE['param']['body']) { - $body = $COMPOSE['param']['body']; - $isHtml = (bool) $COMPOSE['param']['html']; - } - // forward as attachment - else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) { - $isHtml = rcmail_compose_editor_mode(); - $body = ''; - rcmail_write_forward_attachments(); - } - // reply/edit/draft/forward - else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) { - $isHtml = rcmail_compose_editor_mode(); - $messages = array(); + global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $HTML_MODE; - if (!empty($MESSAGE->parts)) { - // collect IDs of message/rfc822 parts - if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { - foreach ($MESSAGE->attachments as $part) { - if ($part->mimetype == 'message/rfc822') { - $messages[] = $part->mime_id; - } - } - } + // use posted message body + if (!empty($_POST['_message'])) { + $body = rcube_utils::get_input_value('_message', rcube_utils::INPUT_POST, true); + $isHtml = (bool) rcube_utils::get_input_value('_is_html', rcube_utils::INPUT_POST); + } + else if ($COMPOSE['param']['body']) { + $body = $COMPOSE['param']['body']; + $isHtml = (bool) $COMPOSE['param']['html']; + } + // forward as attachment + else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $COMPOSE['as_attachment']) { + $isHtml = rcmail_compose_editor_mode(); + $body = ''; - foreach ($MESSAGE->parts as $part) { - // skip no-content and attachment parts (#1488557) - if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) { - continue; - } + rcmail_write_forward_attachments(); + } + // reply/edit/draft/forward + else if ($compose_mode && ($compose_mode != RCUBE_COMPOSE_REPLY || intval($RCMAIL->config->get('reply_mode')) != -1)) { + $isHtml = rcmail_compose_editor_mode(); + $messages = array(); + + if (!empty($MESSAGE->parts)) { + // collect IDs of message/rfc822 parts + if ($compose_mode == RCUBE_COMPOSE_EDIT || $compose_mode == RCUBE_COMPOSE_DRAFT) { + foreach ($MESSAGE->attachments as $part) { + if ($part->mimetype == 'message/rfc822') { + $messages[] = $part->mime_id; + } + } + } - // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode - foreach ($messages as $mimeid) { - if (strpos($part->mime_id, $mimeid . '.') === 0) { - continue 2; - } + foreach ($MESSAGE->parts as $part) { + // skip no-content and attachment parts (#1488557) + if ($part->type != 'content' || !$part->size || $MESSAGE->is_attachment($part)) { + continue; + } + + // skip all content parts inside the message/rfc822 part in DRAFT/EDIT mode + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; + } + } + + if ($part_body = rcmail_compose_part_body($part, $isHtml)) { + $body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body; + } + } } + else { + $body = rcmail_compose_part_body($MESSAGE, $isHtml); + } + + // compose reply-body + if ($compose_mode == RCUBE_COMPOSE_REPLY) + $body = rcmail_create_reply_body($body, $isHtml); + // forward message body inline + else if ($compose_mode == RCUBE_COMPOSE_FORWARD) + $body = rcmail_create_forward_body($body, $isHtml); + // load draft message body + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) + $body = rcmail_create_draft_body($body, $isHtml); + } + else { // new message + $isHtml = rcmail_compose_editor_mode(); + } + + $plugin = $RCMAIL->plugins->exec_hook('message_compose_body', + array('body' => $body, 'html' => $isHtml, 'mode' => $compose_mode)); - if ($part_body = rcmail_compose_part_body($part, $isHtml)) { - $body .= ($body ? ($isHtml ? '<br/>' : "\n") : '') . $part_body; + $body = $plugin['body']; + unset($plugin); + + // add blocked.gif attachment (#1486516) + if ($isHtml && preg_match('#<img src="\./program/resources/blocked\.gif"#', $body)) { + if ($attachment = rcmail_save_image('program/resources/blocked.gif', 'image/gif')) { + $COMPOSE['attachments'][$attachment['id']] = $attachment; + $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', + $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); + $body = preg_replace('#\./program/resources/blocked\.gif#', $url, $body); } - } } - else { - $body = rcmail_compose_part_body($MESSAGE, $isHtml); - } - - // compose reply-body - if ($compose_mode == RCUBE_COMPOSE_REPLY) - $body = rcmail_create_reply_body($body, $isHtml); - // forward message body inline - else if ($compose_mode == RCUBE_COMPOSE_FORWARD) - $body = rcmail_create_forward_body($body, $isHtml); - // load draft message body - else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) - $body = rcmail_create_draft_body($body, $isHtml); - } - else { // new message - $isHtml = rcmail_compose_editor_mode(); - } - - $plugin = $RCMAIL->plugins->exec_hook('message_compose_body', - array('body' => $body, 'html' => $isHtml, 'mode' => $compose_mode)); - $body = $plugin['body']; - unset($plugin); - - // add blocked.gif attachment (#1486516) - if ($isHtml && preg_match('#<img src="\./program/resources/blocked\.gif"#', $body)) { - if ($attachment = rcmail_save_image('program/resources/blocked.gif', 'image/gif')) { - $COMPOSE['attachments'][$attachment['id']] = $attachment; - $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', - $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); - $body = preg_replace('#\./program/resources/blocked\.gif#', $url, $body); - } - } - - $HTML_MODE = $isHtml; - - return $body; + + $HTML_MODE = $isHtml; + + return $body; } function rcmail_compose_part_body($part, $isHtml = false) @@ -817,882 +849,902 @@ function rcmail_compose_part_body($part, $isHtml = false) function rcmail_compose_body($attrib) { - global $RCMAIL, $CONFIG, $OUTPUT, $HTML_MODE, $MESSAGE_BODY; - - list($form_start, $form_end) = get_form_tags($attrib); - unset($attrib['form']); - - if (empty($attrib['id'])) - $attrib['id'] = 'rcmComposeBody'; - - $attrib['name'] = '_message'; - - $isHtml = $HTML_MODE; - - $out = $form_start ? "$form_start\n" : ''; - - $saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $RCMAIL->output->get_env('draft_id'))); - $out .= $saveid->show(); - - $drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes')); - $out .= $drafttoggle->show(); - - $msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml?"1":"0"))); - $out .= $msgtype->show(); - - $framed = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); - $out .= $framed->show(); - - // If desired, set this textarea to be editable by TinyMCE - if ($isHtml) { - $MESSAGE_BODY = htmlentities($MESSAGE_BODY, ENT_NOQUOTES, RCUBE_CHARSET); - $attrib['class'] = 'mce_editor'; - $attrib['is_escaped'] = true; - $textarea = new html_textarea($attrib); - $out .= $textarea->show($MESSAGE_BODY); - } - else { - $textarea = new html_textarea($attrib); - $out .= $textarea->show(''); - // quote plain text, inject into textarea - $table = get_html_translation_table(HTML_SPECIALCHARS); - $MESSAGE_BODY = strtr($MESSAGE_BODY, $table); - $out = substr($out, 0, -11) . $MESSAGE_BODY . '</textarea>'; - } - - $out .= $form_end ? "\n$form_end" : ''; - - $OUTPUT->set_env('composebody', $attrib['id']); - - // include HTML editor - $RCMAIL->html_editor(); - - // Set language list - if (!empty($CONFIG['enable_spellcheck'])) { - $engine = new rcube_spellchecker(); - $dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary'); - $spellcheck_langs = $engine->languages(); - $lang = $_SESSION['language']; - - // if not found in the list, try with two-letter code - if (!$spellcheck_langs[$lang]) - $lang = strtolower(substr($lang, 0, 2)); - - if (!$spellcheck_langs[$lang]) - $lang = 'en'; - - $OUTPUT->set_env('spell_langs', $spellcheck_langs); - $OUTPUT->set_env('spell_lang', $lang); - - $editor_lang_set = array(); - foreach ($spellcheck_langs as $key => $name) { - $editor_lang_set[] = ($key == $lang ? '+' : '') . rcube::JQ($name).'='.rcube::JQ($key); - } - - // include GoogieSpell - $OUTPUT->include_script('googiespell.js'); - $OUTPUT->add_script(sprintf( - "var googie = new GoogieSpell('%s/images/googiespell/','%s&lang=', %s);\n". - "googie.lang_chck_spell = \"%s\";\n". - "googie.lang_rsm_edt = \"%s\";\n". - "googie.lang_close = \"%s\";\n". - "googie.lang_revert = \"%s\";\n". - "googie.lang_no_error_found = \"%s\";\n". - "googie.lang_learn_word = \"%s\";\n". - "googie.setLanguages(%s);\n". - "googie.setCurrentLanguage('%s');\n". - "googie.setDecoration(false);\n". - "googie.decorateTextarea('%s');\n". - "%s.set_env('spellcheck', googie);", - $RCMAIL->output->get_skin_path(), - $RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)), - !empty($dictionary) ? 'true' : 'false', - rcube::JQ(rcube::Q($RCMAIL->gettext('checkspelling'))), - rcube::JQ(rcube::Q($RCMAIL->gettext('resumeediting'))), - rcube::JQ(rcube::Q($RCMAIL->gettext('close'))), - rcube::JQ(rcube::Q($RCMAIL->gettext('revertto'))), - rcube::JQ(rcube::Q($RCMAIL->gettext('nospellerrors'))), - rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))), - rcube_output::json_serialize($spellcheck_langs), - $lang, - $attrib['id'], - rcmail_output::JS_OBJECT_NAME), 'foot'); - - $OUTPUT->add_label('checking'); - $OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set)); - } - - $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>'; - - return $out; + global $RCMAIL, $CONFIG, $OUTPUT, $HTML_MODE, $MESSAGE_BODY; + + list($form_start, $form_end) = get_form_tags($attrib); + unset($attrib['form']); + + if (empty($attrib['id'])) + $attrib['id'] = 'rcmComposeBody'; + + $attrib['name'] = '_message'; + + $isHtml = $HTML_MODE; + + $out = $form_start ? "$form_start\n" : ''; + + $saveid = new html_hiddenfield(array('name' => '_draft_saveid', 'value' => $RCMAIL->output->get_env('draft_id'))); + $out .= $saveid->show(); + + $drafttoggle = new html_hiddenfield(array('name' => '_draft', 'value' => 'yes')); + $out .= $drafttoggle->show(); + + $msgtype = new html_hiddenfield(array('name' => '_is_html', 'value' => ($isHtml ? "1" : "0"))); + $out .= $msgtype->show(); + + $framed = new html_hiddenfield(array('name' => '_framed', 'value' => '1')); + $out .= $framed->show(); + + // If desired, set this textarea to be editable by TinyMCE + if ($isHtml) { + $MESSAGE_BODY = htmlentities($MESSAGE_BODY, ENT_NOQUOTES, RCUBE_CHARSET); + $attrib['class'] = 'mce_editor'; + $attrib['is_escaped'] = true; + $textarea = new html_textarea($attrib); + $out .= $textarea->show($MESSAGE_BODY); + } + else { + $textarea = new html_textarea($attrib); + $out .= $textarea->show(''); + + // quote plain text, inject into textarea + $table = get_html_translation_table(HTML_SPECIALCHARS); + $MESSAGE_BODY = strtr($MESSAGE_BODY, $table); + $out = substr($out, 0, -11) . $MESSAGE_BODY . '</textarea>'; + } + + $out .= $form_end ? "\n$form_end" : ''; + + $OUTPUT->set_env('composebody', $attrib['id']); + + // include HTML editor + $RCMAIL->html_editor(); + + // Set language list + if (!empty($CONFIG['enable_spellcheck'])) { + $engine = new rcube_spellchecker(); + $dictionary = (bool) $RCMAIL->config->get('spellcheck_dictionary'); + $spellcheck_langs = $engine->languages(); + $lang = $_SESSION['language']; + + // if not found in the list, try with two-letter code + if (!$spellcheck_langs[$lang]) { + $lang = strtolower(substr($lang, 0, 2)); + } + + if (!$spellcheck_langs[$lang]) { + $lang = 'en'; + } + + $OUTPUT->set_env('spell_langs', $spellcheck_langs); + $OUTPUT->set_env('spell_lang', $lang); + + $editor_lang_set = array(); + foreach ($spellcheck_langs as $key => $name) { + $editor_lang_set[] = ($key == $lang ? '+' : '') . rcube::JQ($name).'='.rcube::JQ($key); + } + + // include GoogieSpell + $OUTPUT->include_script('googiespell.js'); + $OUTPUT->add_script(sprintf( + "var googie = new GoogieSpell('%s/images/googiespell/','%s&lang=', %s);\n". + "googie.lang_chck_spell = \"%s\";\n". + "googie.lang_rsm_edt = \"%s\";\n". + "googie.lang_close = \"%s\";\n". + "googie.lang_revert = \"%s\";\n". + "googie.lang_no_error_found = \"%s\";\n". + "googie.lang_learn_word = \"%s\";\n". + "googie.setLanguages(%s);\n". + "googie.setCurrentLanguage('%s');\n". + "googie.setDecoration(false);\n". + "googie.decorateTextarea('%s');\n". + "%s.set_env('spellcheck', googie);", + $RCMAIL->output->get_skin_path(), + $RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)), + !empty($dictionary) ? 'true' : 'false', + rcube::JQ(rcube::Q($RCMAIL->gettext('checkspelling'))), + rcube::JQ(rcube::Q($RCMAIL->gettext('resumeediting'))), + rcube::JQ(rcube::Q($RCMAIL->gettext('close'))), + rcube::JQ(rcube::Q($RCMAIL->gettext('revertto'))), + rcube::JQ(rcube::Q($RCMAIL->gettext('nospellerrors'))), + rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))), + rcube_output::json_serialize($spellcheck_langs), + $lang, + $attrib['id'], + rcmail_output::JS_OBJECT_NAME), 'foot'); + + $OUTPUT->add_label('checking'); + $OUTPUT->set_env('spellcheck_langs', join(',', $editor_lang_set)); + } + + $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;"></iframe>'; + + return $out; } function rcmail_create_reply_body($body, $bodyIsHtml) { - global $RCMAIL, $MESSAGE, $LINE_LENGTH; - - // build reply prefix - $from = array_pop(rcube_mime::decode_address_list($MESSAGE->get_header('from'), 1, false, $MESSAGE->headers->charset)); - $prefix = $RCMAIL->gettext(array( - 'name' => 'mailreplyintro', - 'vars' => array( - 'date' => $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')), - 'sender' => $from['name'] ? $from['name'] : rcube_utils::idn_to_utf8($from['mailto']), - ) - )); - - if (!$bodyIsHtml) { - $body = preg_replace('/\r?\n/', "\n", $body); - $body = trim($body, "\n"); - - // soft-wrap and quote message text - $body = rcmail_wrap_and_quote($body, $LINE_LENGTH); - - $prefix .= "\n"; - $suffix = ''; - - if (intval($RCMAIL->config->get('reply_mode')) > 0) { // top-posting - $prefix = "\n\n\n" . $prefix; - } - } - else { - // save inline images to files - $cid_map = rcmail_write_inline_attachments($MESSAGE); - // set is_safe flag (we need this for html body washing) - rcmail_check_safe($MESSAGE); - // clean up html tags - $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); - - // build reply (quote content) - $prefix = '<p>' . rcube::Q($prefix) . "</p>\n"; - $prefix .= '<blockquote>'; - - if (intval($RCMAIL->config->get('reply_mode')) > 0) { // top-posting - $prefix = '<br>' . $prefix; - $suffix = '</blockquote>'; + global $RCMAIL, $MESSAGE, $LINE_LENGTH; + + // build reply prefix + $from = array_pop(rcube_mime::decode_address_list($MESSAGE->get_header('from'), 1, false, $MESSAGE->headers->charset)); + $prefix = $RCMAIL->gettext(array( + 'name' => 'mailreplyintro', + 'vars' => array( + 'date' => $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')), + 'sender' => $from['name'] ? $from['name'] : rcube_utils::idn_to_utf8($from['mailto']), + ) + )); + + if (!$bodyIsHtml) { + $body = preg_replace('/\r?\n/', "\n", $body); + $body = trim($body, "\n"); + + // soft-wrap and quote message text + $body = rcmail_wrap_and_quote($body, $LINE_LENGTH); + + $prefix .= "\n"; + $suffix = ''; + + if (intval($RCMAIL->config->get('reply_mode')) > 0) { // top-posting + $prefix = "\n\n\n" . $prefix; + } } else { - $suffix = '</blockquote><p></p>'; + // save inline images to files + $cid_map = rcmail_write_inline_attachments($MESSAGE); + // set is_safe flag (we need this for html body washing) + rcmail_check_safe($MESSAGE); + // clean up html tags + $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); + + // build reply (quote content) + $prefix = '<p>' . rcube::Q($prefix) . "</p>\n"; + $prefix .= '<blockquote>'; + + if (intval($RCMAIL->config->get('reply_mode')) > 0) { // top-posting + $prefix = '<br>' . $prefix; + $suffix = '</blockquote>'; + } + else { + $suffix = '</blockquote><p></p>'; + } } - } - return $prefix.$body.$suffix; + return $prefix . $body . $suffix; } function rcmail_create_forward_body($body, $bodyIsHtml) { - global $RCMAIL, $MESSAGE, $COMPOSE; - - // add attachments - if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts)) - $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); - - $date = $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); - - if (!$bodyIsHtml) { - $prefix = "\n\n\n-------- " . $RCMAIL->gettext('originalmessage') . " --------\n"; - $prefix .= $RCMAIL->gettext('subject') . ': ' . $MESSAGE->subject . "\n"; - $prefix .= $RCMAIL->gettext('date') . ': ' . $date . "\n"; - $prefix .= $RCMAIL->gettext('from') . ': ' . $MESSAGE->get_header('from') . "\n"; - $prefix .= $RCMAIL->gettext('to') . ': ' . $MESSAGE->get_header('to') . "\n"; - - if ($cc = $MESSAGE->headers->get('cc')) - $prefix .= $RCMAIL->gettext('cc') . ': ' . $cc . "\n"; - if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) - $prefix .= $RCMAIL->gettext('replyto') . ': ' . $replyto . "\n"; - - $prefix .= "\n"; - $body = trim($body, "\r\n"); - } - else { - // set is_safe flag (we need this for html body washing) - rcmail_check_safe($MESSAGE); - // clean up html tags - $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); - - $prefix = sprintf( - "<br /><p>-------- " . $RCMAIL->gettext('originalmessage') . " --------</p>" . - "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" . - "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . - "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . - "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . - "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", - $RCMAIL->gettext('subject'), rcube::Q($MESSAGE->subject), - $RCMAIL->gettext('date'), rcube::Q($date), - $RCMAIL->gettext('from'), rcube::Q($MESSAGE->get_header('from'), 'replace'), - $RCMAIL->gettext('to'), rcube::Q($MESSAGE->get_header('to'), 'replace')); - - if ($cc = $MESSAGE->headers->get('cc')) - $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", - $RCMAIL->gettext('cc'), rcube::Q($cc, 'replace')); - - if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) - $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", - $RCMAIL->gettext('replyto'), rcube::Q($replyto, 'replace')); - - $prefix .= "</tbody></table><br>"; - } - - return $prefix.$body; + global $RCMAIL, $MESSAGE, $COMPOSE; + + // add attachments + if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts)) { + $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); + } + + $date = $RCMAIL->format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long')); + + if (!$bodyIsHtml) { + $prefix = "\n\n\n-------- " . $RCMAIL->gettext('originalmessage') . " --------\n"; + $prefix .= $RCMAIL->gettext('subject') . ': ' . $MESSAGE->subject . "\n"; + $prefix .= $RCMAIL->gettext('date') . ': ' . $date . "\n"; + $prefix .= $RCMAIL->gettext('from') . ': ' . $MESSAGE->get_header('from') . "\n"; + $prefix .= $RCMAIL->gettext('to') . ': ' . $MESSAGE->get_header('to') . "\n"; + + if ($cc = $MESSAGE->headers->get('cc')) { + $prefix .= $RCMAIL->gettext('cc') . ': ' . $cc . "\n"; + } + if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) { + $prefix .= $RCMAIL->gettext('replyto') . ': ' . $replyto . "\n"; + } + + $prefix .= "\n"; + $body = trim($body, "\r\n"); + } + else { + // set is_safe flag (we need this for html body washing) + rcmail_check_safe($MESSAGE); + + // clean up html tags + $body = rcmail_wash_html($body, array('safe' => $MESSAGE->is_safe), $cid_map); + + $prefix = sprintf( + "<br /><p>-------- " . $RCMAIL->gettext('originalmessage') . " --------</p>" . + "<table border=\"0\" cellpadding=\"0\" cellspacing=\"0\"><tbody>" . + "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . + "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . + "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>" . + "<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", + $RCMAIL->gettext('subject'), rcube::Q($MESSAGE->subject), + $RCMAIL->gettext('date'), rcube::Q($date), + $RCMAIL->gettext('from'), rcube::Q($MESSAGE->get_header('from'), 'replace'), + $RCMAIL->gettext('to'), rcube::Q($MESSAGE->get_header('to'), 'replace')); + + if ($cc = $MESSAGE->headers->get('cc')) + $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", + $RCMAIL->gettext('cc'), rcube::Q($cc, 'replace')); + + if (($replyto = $MESSAGE->headers->get('reply-to')) && $replyto != $MESSAGE->get_header('from')) + $prefix .= sprintf("<tr><th align=\"right\" nowrap=\"nowrap\" valign=\"baseline\">%s: </th><td>%s</td></tr>", + $RCMAIL->gettext('replyto'), rcube::Q($replyto, 'replace')); + + $prefix .= "</tbody></table><br>"; + } + + return $prefix . $body; } function rcmail_create_draft_body($body, $bodyIsHtml) { - global $MESSAGE, $COMPOSE; + global $MESSAGE, $COMPOSE; - /** - * add attachments - * sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text! - */ - if (empty($COMPOSE['forward_attachments']) - && is_array($MESSAGE->mime_parts) - && count($MESSAGE->mime_parts) > 0) - { - $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); - } + // add attachments + // sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text! + if (empty($COMPOSE['forward_attachments']) + && is_array($MESSAGE->mime_parts) + && count($MESSAGE->mime_parts) > 0 + ) { + $cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml); + } - // clean up HTML tags - XSS prevention (#1489251) - if ($bodyIsHtml) { - $body = rcmail_wash_html($body, array('safe' => 1), $cid_map); + // clean up HTML tags - XSS prevention (#1489251) + if ($bodyIsHtml) { + $body = rcmail_wash_html($body, array('safe' => 1), $cid_map); - // remove comments (produced by washtml) - $body = preg_replace('/<!--[^>]+-->/', '', $body); + // remove comments (produced by washtml) + $body = preg_replace('/<!--[^>]+-->/', '', $body); - // replace cid with href in inline images links - if (!empty($cid_map)) { - $body = str_replace(array_keys($cid_map), array_values($cid_map), $body); + // replace cid with href in inline images links + if (!empty($cid_map)) { + $body = str_replace(array_keys($cid_map), array_values($cid_map), $body); + } } - } - return $body; + return $body; } function rcmail_remove_signature($body) { - global $RCMAIL; + global $RCMAIL; - $body = str_replace("\r\n", "\n", $body); - $len = strlen($body); - $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15); + $body = str_replace("\r\n", "\n", $body); + $len = strlen($body); + $sig_max_lines = $RCMAIL->config->get('sig_max_lines', 15); - while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) { - if ($sp == 0 || $body[$sp-1] == "\n") { - // do not touch blocks with more that X lines - if (substr_count($body, "\n", $sp) < $sig_max_lines) { - $body = substr($body, 0, max(0, $sp-1)); - } - break; + while (($sp = strrpos($body, "-- \n", $sp ? -$len+$sp-1 : 0)) !== false) { + if ($sp == 0 || $body[$sp-1] == "\n") { + // do not touch blocks with more that X lines + if (substr_count($body, "\n", $sp) < $sig_max_lines) { + $body = substr($body, 0, max(0, $sp-1)); + } + break; + } } - } - return $body; + return $body; } function rcmail_write_compose_attachments(&$message, $bodyIsHtml) { - global $RCMAIL, $COMPOSE, $compose_mode; - - $loaded_attachments = array(); - foreach ((array)$COMPOSE['attachments'] as $attachment) { - $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; - } - - $cid_map = array(); - $messages = array(); - - foreach ((array)$message->mime_parts as $pid => $part) - { - if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { - // skip parts that aren't valid attachments - if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') { - continue; - } - // skip message attachments in reply mode - if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) { - continue; - } - // skip inline images when forwarding in text mode - if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { - continue; - } - - // skip message/rfc822 attachments on forwards (#1489214) - // Thunderbird when forwarding in inline mode displays such attachments - // and skips any attachments from inside of such part, this however - // skipped e.g. images used in HTML body or other attachments. So, - // better to skip .eml attachments but not their content (included files). - if ($part->mimetype == 'message/rfc822') { - if ($compose_mode == RCUBE_COMPOSE_FORWARD) { - continue; - } - $messages[] = $part->mime_id; - } - else if ($compose_mode != RCUBE_COMPOSE_FORWARD) { - // skip attachments included in message/rfc822 attachment (#1486487) - foreach ($messages as $mimeid) - if (strpos($part->mime_id, $mimeid . '.') === 0) { - continue 2; - } - } - - if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) - || ($attachment = rcmail_save_attachment($message, $pid))) { - $COMPOSE['attachments'][$attachment['id']] = $attachment; - if ($bodyIsHtml && ($part->content_id || $part->content_location)) { - $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', - $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); - if ($part->content_id) - $cid_map['cid:'.$part->content_id] = $url; - else - $cid_map[$part->content_location] = $url; + global $RCMAIL, $COMPOSE, $compose_mode; + + $loaded_attachments = array(); + foreach ((array)$COMPOSE['attachments'] as $attachment) { + $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; + } + + $cid_map = array(); + $messages = array(); + + foreach ((array)$message->mime_parts as $pid => $part) { + if ($part->disposition == 'attachment' || ($part->disposition == 'inline' && $bodyIsHtml) || $part->filename) { + // skip parts that aren't valid attachments + if ($part->ctype_primary == 'multipart' || $part->mimetype == 'application/ms-tnef') { + continue; + } + + // skip message attachments in reply mode + if ($part->ctype_primary == 'message' && $compose_mode == RCUBE_COMPOSE_REPLY) { + continue; + } + + // skip inline images when forwarding in text mode + if ($part->content_id && $part->disposition == 'inline' && !$bodyIsHtml && $compose_mode == RCUBE_COMPOSE_FORWARD) { + continue; + } + + // skip message/rfc822 attachments on forwards (#1489214) + // Thunderbird when forwarding in inline mode displays such attachments + // and skips any attachments from inside of such part, this however + // skipped e.g. images used in HTML body or other attachments. So, + // better to skip .eml attachments but not their content (included files). + if ($part->mimetype == 'message/rfc822') { + if ($compose_mode == RCUBE_COMPOSE_FORWARD) { + continue; + } + $messages[] = $part->mime_id; + } + else if ($compose_mode != RCUBE_COMPOSE_FORWARD) { + // skip attachments included in message/rfc822 attachment (#1486487) + foreach ($messages as $mimeid) { + if (strpos($part->mime_id, $mimeid . '.') === 0) { + continue 2; + } + } + } + + if (($attachment = $loaded_attachments[rcmail_attachment_name($part) . $part->mimetype]) + || ($attachment = rcmail_save_attachment($message, $pid)) + ) { + $COMPOSE['attachments'][$attachment['id']] = $attachment; + + if ($bodyIsHtml && ($part->content_id || $part->content_location)) { + $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', + $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); + + if ($part->content_id) + $cid_map['cid:'.$part->content_id] = $url; + else + $cid_map[$part->content_location] = $url; + } + } } - } } - } - $COMPOSE['forward_attachments'] = true; + $COMPOSE['forward_attachments'] = true; - return $cid_map; + return $cid_map; } function rcmail_write_inline_attachments(&$message) { - global $RCMAIL, $COMPOSE; - - $cid_map = array(); - foreach ((array)$message->mime_parts as $pid => $part) { - if (($part->content_id || $part->content_location) && $part->filename) { - if ($attachment = rcmail_save_attachment($message, $pid)) { - $COMPOSE['attachments'][$attachment['id']] = $attachment; - $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', - $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); - if ($part->content_id) - $cid_map['cid:'.$part->content_id] = $url; - else - $cid_map[$part->content_location] = $url; - } + global $RCMAIL, $COMPOSE; + + $cid_map = array(); + foreach ((array)$message->mime_parts as $pid => $part) { + if (($part->content_id || $part->content_location) && $part->filename) { + if ($attachment = rcmail_save_attachment($message, $pid)) { + $COMPOSE['attachments'][$attachment['id']] = $attachment; + $url = sprintf('%s&_id=%s&_action=display-attachment&_file=rcmfile%s', + $RCMAIL->comm_path, $COMPOSE['id'], $attachment['id']); + + if ($part->content_id) + $cid_map['cid:'.$part->content_id] = $url; + else + $cid_map[$part->content_location] = $url; + } + } } - } - return $cid_map; + return $cid_map; } // Creates attachment(s) from the forwarded message(s) function rcmail_write_forward_attachments() { - global $RCMAIL, $COMPOSE, $MESSAGE; + global $RCMAIL, $COMPOSE, $MESSAGE; - $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(); + $storage = $RCMAIL->get_storage(); + $names = array(); - $loaded_attachments = array(); - foreach ((array)$COMPOSE['attachments'] as $attachment) { - $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; - } + $loaded_attachments = array(); + foreach ((array)$COMPOSE['attachments'] as $attachment) { + $loaded_attachments[$attachment['name'] . $attachment['mimetype']] = $attachment; + } - if ($COMPOSE['forward_uid'] == '*') { - $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); - $COMPOSE['forward_uid'] = $index->get(); - } - else { - $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); - } + if ($COMPOSE['forward_uid'] == '*') { + $index = $storage->index(null, rcmail_sort_column(), rcmail_sort_order()); + $COMPOSE['forward_uid'] = $index->get(); + } + else { + $COMPOSE['forward_uid'] = explode(',', $COMPOSE['forward_uid']); + } - foreach ((array)$COMPOSE['forward_uid'] as $uid) { - $message = new rcube_message($uid); + foreach ((array)$COMPOSE['forward_uid'] as $uid) { + $message = new rcube_message($uid); - if (empty($message->headers)) { - continue; - } + if (empty($message->headers)) { + continue; + } - if (!empty($message->headers->charset)) { - $storage->set_charset($message->headers->charset); - } + if (!empty($message->headers->charset)) { + $storage->set_charset($message->headers->charset); + } - if (empty($MESSAGE->subject)) { - $MESSAGE->subject = $message->subject; - } + 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'; + // 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; + + if (!empty($loaded_attachments[$name . 'message/rfc822'])) { + continue; + } - $data = $path = null; + // don't load too big attachments into memory + if (!rcube_utils::mem_check($message->size)) { + $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; + } - if (!empty($loaded_attachments[$name . 'message/rfc822'])) { - continue; + $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); + } } +} + + +function rcmail_save_attachment(&$message, $pid) +{ + global $COMPOSE; + + $rcmail = rcmail::get_instance(); + $part = $message->mime_parts[$pid]; + $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; - } + if (!rcube_utils::mem_check($part->size)) { + $temp_dir = unslashify($rcmail->config->get('temp_dir')); + $path = tempnam($temp_dir, 'rcmAttmnt'); + + if ($fp = fopen($path, 'w')) { + $message->get_part_content($pid, $fp, true, 0, false); + fclose($fp); + } + else { + return false; + } } else { - $data = $storage->get_raw_body($message->uid); - $curr_mem += $message->size; + $data = $message->get_part_content($pid, null, true, 0, false); } + $mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; + $filename = rcmail_attachment_name($part); + $attachment = array( - 'group' => $COMPOSE['id'], - 'name' => $name, - 'mimetype' => 'message/rfc822', - 'data' => $data, - 'path' => $path, - 'size' => $path ? filesize($path) : strlen($data), + 'group' => $COMPOSE['id'], + 'name' => $filename, + 'mimetype' => $mimetype, + 'content_id' => $part->content_id, + 'data' => $data, + 'path' => $path, + 'size' => $path ? filesize($path) : strlen($data), ); - $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment); + $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; + unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); + return $attachment; } else if ($path) { - @unlink($path); + @unlink($path); } - } -} - -function rcmail_save_attachment(&$message, $pid) -{ - global $COMPOSE; - - $rcmail = rcmail::get_instance(); - $part = $message->mime_parts[$pid]; - $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; - - // don't load too big attachments into memory - if ($mem_limit > 0 && $part->size > $mem_limit - $curr_mem) { - $temp_dir = unslashify($rcmail->config->get('temp_dir')); - $path = tempnam($temp_dir, 'rcmAttmnt'); - if ($fp = fopen($path, 'w')) { - $message->get_part_content($pid, $fp, true, 0, false); - fclose($fp); - } else - return false; - } else { - $data = $message->get_part_content($pid, null, true, 0, false); - } - - $mimetype = $part->ctype_primary . '/' . $part->ctype_secondary; - $filename = rcmail_attachment_name($part); - - $attachment = array( - 'group' => $COMPOSE['id'], - 'name' => $filename, - 'mimetype' => $mimetype, - 'content_id' => $part->content_id, - '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']); - return $attachment; - } else if ($path) { - @unlink($path); - } - - return false; + return false; } function rcmail_save_image($path, $mimetype='') { - global $COMPOSE; + global $COMPOSE; - // handle attachments in memory - $data = file_get_contents($path); - $name = rcmail_basename($path); + // handle attachments in memory + $data = file_get_contents($path); + $name = rcmail_basename($path); - $attachment = array( - 'group' => $COMPOSE['id'], - 'name' => $name, - 'mimetype' => $mimetype ? $mimetype : rcube_mime::file_content_type($path, $name), - 'data' => $data, - 'size' => strlen($data), - ); + $attachment = array( + 'group' => $COMPOSE['id'], + 'name' => $name, + 'mimetype' => $mimetype ? $mimetype : rcube_mime::file_content_type($path, $name), + 'data' => $data, + 'size' => strlen($data), + ); - $attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); + $attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment); - if ($attachment['status']) { - unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); - return $attachment; - } + if ($attachment['status']) { + unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']); + return $attachment; + } - return false; + return false; } function rcmail_basename($filename) { - // basename() is not unicode safe and locale dependent - if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) { - return preg_replace('/^.*[\\\\\\/]/', '', $filename); - } else { - return preg_replace('/^.*[\/]/', '', $filename); - } + // basename() is not unicode safe and locale dependent + if (stristr(PHP_OS, 'win') || stristr(PHP_OS, 'netware')) { + return preg_replace('/^.*[\\\\\\/]/', '', $filename); + } + else { + return preg_replace('/^.*[\/]/', '', $filename); + } } function rcmail_compose_subject($attrib) { - global $MESSAGE, $COMPOSE, $compose_mode; + global $MESSAGE, $COMPOSE, $compose_mode; - list($form_start, $form_end) = get_form_tags($attrib); - unset($attrib['form']); + list($form_start, $form_end) = get_form_tags($attrib); + unset($attrib['form']); - $attrib['name'] = '_subject'; - $attrib['spellcheck'] = 'true'; - $textfield = new html_inputfield($attrib); + $attrib['name'] = '_subject'; + $attrib['spellcheck'] = 'true'; - $subject = ''; + $textfield = new html_inputfield($attrib); + $subject = ''; - // use subject from post - if (isset($_POST['_subject'])) { - $subject = rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE); - } - // create a reply-subject - else if ($compose_mode == RCUBE_COMPOSE_REPLY) { - if (preg_match('/^re:/i', $MESSAGE->subject)) - $subject = $MESSAGE->subject; - else - $subject = 'Re: '.$MESSAGE->subject; - } - // create a forward-subject - else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { - if (preg_match('/^fwd:/i', $MESSAGE->subject)) - $subject = $MESSAGE->subject; - else - $subject = 'Fwd: '.$MESSAGE->subject; - } - // creeate a draft-subject - else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { - $subject = $MESSAGE->subject; - } - else if (!empty($COMPOSE['param']['subject'])) { - $subject = $COMPOSE['param']['subject']; - } - - $out = $form_start ? "$form_start\n" : ''; - $out .= $textfield->show($subject); - $out .= $form_end ? "\n$form_end" : ''; - - return $out; + // use subject from post + if (isset($_POST['_subject'])) { + $subject = rcube_utils::get_input_value('_subject', rcube_utils::INPUT_POST, TRUE); + } + // create a reply-subject + else if ($compose_mode == RCUBE_COMPOSE_REPLY) { + if (preg_match('/^re:/i', $MESSAGE->subject)) + $subject = $MESSAGE->subject; + else + $subject = 'Re: '.$MESSAGE->subject; + } + // create a forward-subject + else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { + if (preg_match('/^fwd:/i', $MESSAGE->subject)) + $subject = $MESSAGE->subject; + else + $subject = 'Fwd: '.$MESSAGE->subject; + } + // creeate a draft-subject + else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) { + $subject = $MESSAGE->subject; + } + else if (!empty($COMPOSE['param']['subject'])) { + $subject = $COMPOSE['param']['subject']; + } + + $out = $form_start ? "$form_start\n" : ''; + $out .= $textfield->show($subject); + $out .= $form_end ? "\n$form_end" : ''; + + return $out; } function rcmail_compose_attachment_list($attrib) { - global $RCMAIL, $OUTPUT, $CONFIG, $COMPOSE; - - // add ID if not given - if (!$attrib['id']) - $attrib['id'] = 'rcmAttachmentList'; - - $out = "\n"; - $jslist = array(); - $button = ''; - - if (is_array($COMPOSE['attachments'])) { - if ($attrib['deleteicon']) { - $button = html::img(array( - 'src' => $CONFIG['skin_path'] . $attrib['deleteicon'], - 'alt' => $RCMAIL->gettext('delete') - )); - } - else if (rcube_utils::get_boolean($attrib['textbuttons'])) { - $button = rcube::Q($RCMAIL->gettext('delete')); - } - - foreach ($COMPOSE['attachments'] as $id => $a_prop) { - if (empty($a_prop)) - continue; - - $out .= html::tag('li', - array( - 'id' => 'rcmfile'.$id, - 'class' => rcube_utils::file2class($a_prop['mimetype'], $a_prop['name']), - 'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)", - ), - html::a(array( - 'href' => "#delete", - 'title' => $RCMAIL->gettext('delete'), - 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id), - 'class' => 'delete' - ), - $button - ) . rcube::Q($a_prop['name']) - ); - - $jslist['rcmfile'.$id] = array('name' => $a_prop['name'], 'complete' => true, 'mimetype' => $a_prop['mimetype']); - } - } - - if ($attrib['deleteicon']) - $COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon']; - else if (rcube_utils::get_boolean($attrib['textbuttons'])) - $COMPOSE['textbuttons'] = true; - if ($attrib['cancelicon']) - $OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']); - if ($attrib['loadingicon']) - $OUTPUT->set_env('loadingicon', $CONFIG['skin_path'] . $attrib['loadingicon']); - - $OUTPUT->set_env('attachments', $jslist); - $OUTPUT->add_gui_object('attachmentlist', $attrib['id']); - - return html::tag('ul', $attrib, $out, html::$common_attrib); + global $RCMAIL, $OUTPUT, $CONFIG, $COMPOSE; + + // add ID if not given + if (!$attrib['id']) + $attrib['id'] = 'rcmAttachmentList'; + + $out = "\n"; + $jslist = array(); + $button = ''; + + if (is_array($COMPOSE['attachments'])) { + if ($attrib['deleteicon']) { + $button = html::img(array( + 'src' => $CONFIG['skin_path'] . $attrib['deleteicon'], + 'alt' => $RCMAIL->gettext('delete') + )); + } + else if (rcube_utils::get_boolean($attrib['textbuttons'])) { + $button = rcube::Q($RCMAIL->gettext('delete')); + } + + foreach ($COMPOSE['attachments'] as $id => $a_prop) { + if (empty($a_prop)) { + continue; + } + + $out .= html::tag('li', array( + 'id' => 'rcmfile'.$id, + 'class' => rcube_utils::file2class($a_prop['mimetype'], $a_prop['name']), + 'onmouseover' => "rcube_webmail.long_subject_title_ex(this, 0)", + ), + html::a(array( + 'href' => "#delete", + 'title' => $RCMAIL->gettext('delete'), + 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id), + 'class' => 'delete' + ), + $button + ) . rcube::Q($a_prop['name']) + ); + + $jslist['rcmfile'.$id] = array( + 'name' => $a_prop['name'], + 'complete' => true, + 'mimetype' => $a_prop['mimetype'] + ); + } + } + + if ($attrib['deleteicon']) + $COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon']; + else if (rcube_utils::get_boolean($attrib['textbuttons'])) + $COMPOSE['textbuttons'] = true; + if ($attrib['cancelicon']) + $OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']); + if ($attrib['loadingicon']) + $OUTPUT->set_env('loadingicon', $CONFIG['skin_path'] . $attrib['loadingicon']); + + $OUTPUT->set_env('attachments', $jslist); + $OUTPUT->add_gui_object('attachmentlist', $attrib['id']); + + return html::tag('ul', $attrib, $out, html::$common_attrib); } function rcmail_compose_attachment_form($attrib) { - global $OUTPUT, $RCMAIL; + global $OUTPUT, $RCMAIL; + + // set defaults + $attrib += array('id' => 'rcmUploadbox', 'buttons' => 'yes'); - // set defaults - $attrib += array('id' => 'rcmUploadbox', 'buttons' => 'yes'); + // Get filesize, enable upload progress bar + $max_filesize = $RCMAIL->upload_init(); - // Get filesize, enable upload progress bar - $max_filesize = $RCMAIL->upload_init(); + $button = new html_inputfield(array('type' => 'button')); + $content = html::div(null, rcmail_compose_attachment_field()) + . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))); + + if (rcube_utils::get_boolean($attrib['buttons'])) { + $content .= html::div('buttons', + $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . + $button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('send-attachment', this.form)")) + ); + } - $button = new html_inputfield(array('type' => 'button')); + $out = html::div($attrib, $OUTPUT->form_tag(array( + 'id' => $attrib['id'] . 'Frm', + 'name' => 'uploadform', + 'method' => 'post', + 'enctype' => 'multipart/form-data' + ), $content + )); - $out = html::div($attrib, - $OUTPUT->form_tag(array('id' => $attrib['id'].'Frm', 'name' => 'uploadform', 'method' => 'post', 'enctype' => 'multipart/form-data'), - html::div(null, rcmail_compose_attachment_field()) . - html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))) . - (rcube_utils::get_boolean($attrib['buttons']) ? html::div('buttons', - $button->show($RCMAIL->gettext('close'), array('class' => 'button', 'onclick' => "$('#$attrib[id]').hide()")) . ' ' . - $button->show($RCMAIL->gettext('upload'), array('class' => 'button mainaction', 'onclick' => rcmail_output::JS_OBJECT_NAME . ".command('send-attachment', this.form)")) - ) : '') - ) - ); + $OUTPUT->add_gui_object('uploadform', $attrib['id'] . 'Frm'); - $OUTPUT->add_gui_object('uploadform', $attrib['id'].'Frm'); - return $out; + return $out; } function rcmail_compose_attachment_field($attrib = array()) { - $attrib['type'] = 'file'; - $attrib['name'] = '_attachments[]'; - $attrib['multiple'] = 'multiple'; + $attrib['type'] = 'file'; + $attrib['name'] = '_attachments[]'; + $attrib['multiple'] = 'multiple'; - $field = new html_inputfield($attrib); - return $field->show(); + $field = new html_inputfield($attrib); + + return $field->show(); } function rcmail_priority_selector($attrib) { - global $RCMAIL, $MESSAGE; + global $RCMAIL, $MESSAGE; - list($form_start, $form_end) = get_form_tags($attrib); - unset($attrib['form']); + list($form_start, $form_end) = get_form_tags($attrib); + unset($attrib['form']); - $attrib['name'] = '_priority'; - $selector = new html_select($attrib); + $attrib['name'] = '_priority'; + $prio_list = array( + $RCMAIL->gettext('lowest') => 5, + $RCMAIL->gettext('low') => 4, + $RCMAIL->gettext('normal') => 0, + $RCMAIL->gettext('high') => 2, + $RCMAIL->gettext('highest') => 1, + ); - $selector->add(array($RCMAIL->gettext('lowest'), - $RCMAIL->gettext('low'), - $RCMAIL->gettext('normal'), - $RCMAIL->gettext('high'), - $RCMAIL->gettext('highest')), - array('5', '4', '0', '2', '1')); + $selector = new html_select($attrib); + $selector->add(array_keys($prio_list), array_values($prio_list)); - if (isset($_POST['_priority'])) - $sel = $_POST['_priority']; - else if (isset($MESSAGE->headers->priority) && intval($MESSAGE->headers->priority) != 3) - $sel = $MESSAGE->headers->priority; - else - $sel = 0; + if (isset($_POST['_priority'])) + $sel = $_POST['_priority']; + else if (isset($MESSAGE->headers->priority) && intval($MESSAGE->headers->priority) != 3) + $sel = $MESSAGE->headers->priority; + else + $sel = 0; - $out = $form_start ? "$form_start\n" : ''; - $out .= $selector->show(strval($sel)); - $out .= $form_end ? "\n$form_end" : ''; + $out = $form_start ? "$form_start\n" : ''; + $out .= $selector->show(strval($sel)); + $out .= $form_end ? "\n$form_end" : ''; - return $out; + return $out; } function rcmail_receipt_checkbox($attrib) { - global $RCMAIL, $MESSAGE, $compose_mode; + global $RCMAIL, $MESSAGE, $compose_mode; - list($form_start, $form_end) = get_form_tags($attrib); - unset($attrib['form']); + list($form_start, $form_end) = get_form_tags($attrib); + unset($attrib['form']); - if (!isset($attrib['id'])) - $attrib['id'] = 'receipt'; + if (!isset($attrib['id'])) + $attrib['id'] = 'receipt'; - $attrib['name'] = '_receipt'; - $attrib['value'] = '1'; - $checkbox = new html_checkbox($attrib); + $attrib['name'] = '_receipt'; + $attrib['value'] = '1'; - 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'); + $checkbox = new html_checkbox($attrib); - $out = $form_start ? "$form_start\n" : ''; - $out .= $checkbox->show($mdn_default); - $out .= $form_end ? "\n$form_end" : ''; + 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'); - return $out; + $out = $form_start ? "$form_start\n" : ''; + $out .= $checkbox->show($mdn_default); + $out .= $form_end ? "\n$form_end" : ''; + + return $out; } function rcmail_dsn_checkbox($attrib) { - global $RCMAIL; + global $RCMAIL; + + list($form_start, $form_end) = get_form_tags($attrib); + unset($attrib['form']); - list($form_start, $form_end) = get_form_tags($attrib); - unset($attrib['form']); + if (!isset($attrib['id'])) + $attrib['id'] = 'dsn'; - if (!isset($attrib['id'])) - $attrib['id'] = 'dsn'; + $attrib['name'] = '_dsn'; + $attrib['value'] = '1'; - $attrib['name'] = '_dsn'; - $attrib['value'] = '1'; - $checkbox = new html_checkbox($attrib); + $checkbox = new html_checkbox($attrib); - if (isset($_POST['_dsn'])) - $dsn_value = $_POST['_dsn']; - else - $dsn_value = $RCMAIL->config->get('dsn_default'); + if (isset($_POST['_dsn'])) + $dsn_value = (int) $_POST['_dsn']; + else + $dsn_value = $RCMAIL->config->get('dsn_default'); - $out = $form_start ? "$form_start\n" : ''; - $out .= $checkbox->show($dsn_value); - $out .= $form_end ? "\n$form_end" : ''; + $out = $form_start ? "$form_start\n" : ''; + $out .= $checkbox->show($dsn_value); + $out .= $form_end ? "\n$form_end" : ''; - return $out; + return $out; } function rcmail_editor_selector($attrib) { - global $RCMAIL; + global $RCMAIL; - // determine whether HTML or plain text should be checked - $useHtml = rcmail_compose_editor_mode(); + // determine whether HTML or plain text should be checked + $useHtml = rcmail_compose_editor_mode(); - if (empty($attrib['editorid'])) - $attrib['editorid'] = 'rcmComposeBody'; + if (empty($attrib['editorid'])) + $attrib['editorid'] = 'rcmComposeBody'; - if (empty($attrib['name'])) - $attrib['name'] = 'editorSelect'; + if (empty($attrib['name'])) + $attrib['name'] = 'editorSelect'; - $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')"; + $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')"; - $select = new html_select($attrib); + $select = new html_select($attrib); - $select->add(rcube::Q($RCMAIL->gettext('htmltoggle')), 'html'); - $select->add(rcube::Q($RCMAIL->gettext('plaintoggle')), 'plain'); + $select->add(rcube::Q($RCMAIL->gettext('htmltoggle')), 'html'); + $select->add(rcube::Q($RCMAIL->gettext('plaintoggle')), 'plain'); - return $select->show($useHtml ? 'html' : 'plain'); -/* - foreach ($choices as $value => $text) { - $attrib['id'] = '_' . $value; - $attrib['value'] = $value; - $selector .= $radio->show($chosenvalue, $attrib) . html::label($attrib['id'], rcube::Q($RCMAIL->gettext($text))); - } - - return $selector; -*/ + return $select->show($useHtml ? 'html' : 'plain'); } function rcmail_store_target_selection($attrib) { - global $COMPOSE, $RCMAIL; - - $attrib['name'] = '_store_target'; - $select = $RCMAIL->folder_selector(array_merge($attrib, array( - 'noselection' => '- ' . $RCMAIL->gettext('dontsave') . ' -', - 'folder_filter' => 'mail', - 'folder_rights' => 'w', - ))); - return $select->show(isset($_POST['_store_target']) ? $_POST['_store_target'] : $COMPOSE['param']['sent_mbox'], $attrib); + global $COMPOSE, $RCMAIL; + + $attrib['name'] = '_store_target'; + $select = $RCMAIL->folder_selector(array_merge($attrib, array( + 'noselection' => '- ' . $RCMAIL->gettext('dontsave') . ' -', + 'folder_filter' => 'mail', + 'folder_rights' => 'w', + ))); + + 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; + global $RCMAIL; - // we'll not save the message, so it doesn't matter - if ($RCMAIL->config->get('no_save_sent_messages')) { - return true; - } + // 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; - } + if ($RCMAIL->storage->folder_exists($folder, true)) { + return true; + } - // folder may exist but isn't subscribed (#1485241) - if ($create) { - if (!$RCMAIL->storage->folder_exists($folder)) - return $RCMAIL->storage->create_folder($folder, true); - else - return $RCMAIL->storage->subscribe($folder); - } + // folder may exist but isn't subscribed (#1485241) + if ($create) { + if (!$RCMAIL->storage->folder_exists($folder)) + return $RCMAIL->storage->create_folder($folder, true); + else + return $RCMAIL->storage->subscribe($folder); + } - return false; + return false; } function get_form_tags($attrib) { - global $RCMAIL, $MESSAGE_FORM, $COMPOSE; + global $RCMAIL, $MESSAGE_FORM, $COMPOSE; - $form_start = ''; - if (!$MESSAGE_FORM) - { - $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); - $hiddenfields->add(array('name' => '_action', 'value' => 'send')); - $hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id'])); - $hiddenfields->add(array('name' => '_attachments')); + $form_start = ''; + if (!$MESSAGE_FORM) { + $hiddenfields = new html_hiddenfield(array('name' => '_task', 'value' => $RCMAIL->task)); + $hiddenfields->add(array('name' => '_action', 'value' => 'send')); + $hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id'])); + $hiddenfields->add(array('name' => '_attachments')); - $form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; - $form_start .= $hiddenfields->show(); - } + $form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : ''; + $form_start .= $hiddenfields->show(); + } - $form_end = ($MESSAGE_FORM && !strlen($attrib['form'])) ? '</form>' : ''; - $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; + $form_end = ($MESSAGE_FORM && !strlen($attrib['form'])) ? '</form>' : ''; + $form_name = !empty($attrib['form']) ? $attrib['form'] : 'form'; - if (!$MESSAGE_FORM) - $RCMAIL->output->add_gui_object('messageform', $form_name); + if (!$MESSAGE_FORM) + $RCMAIL->output->add_gui_object('messageform', $form_name); - $MESSAGE_FORM = $form_name; + $MESSAGE_FORM = $form_name; - return array($form_start, $form_end); + return array($form_start, $form_end); } @@ -1791,25 +1843,3 @@ function rcmail_compose_responses_list($attrib) return $list->show(); } - - -// register UI objects -$OUTPUT->add_handlers(array( - 'composeheaders' => 'rcmail_compose_headers', - 'composesubject' => 'rcmail_compose_subject', - 'composebody' => 'rcmail_compose_body', - 'composeattachmentlist' => 'rcmail_compose_attachment_list', - 'composeattachmentform' => 'rcmail_compose_attachment_form', - 'composeattachment' => 'rcmail_compose_attachment_field', - 'filedroparea' => 'compose_file_drop_area', - 'priorityselector' => 'rcmail_priority_selector', - 'editorselector' => 'rcmail_editor_selector', - 'receiptcheckbox' => 'rcmail_receipt_checkbox', - 'dsncheckbox' => 'rcmail_dsn_checkbox', - 'storetarget' => 'rcmail_store_target_selection', - 'addressbooks' => 'rcmail_addressbook_list', - 'addresslist' => 'rcmail_contacts_list', - 'responseslist' => 'rcmail_compose_responses_list', -)); - -$OUTPUT->send('compose'); |