diff options
Diffstat (limited to 'program/steps/mail')
-rw-r--r-- | program/steps/mail/attachments.inc | 25 | ||||
-rw-r--r-- | program/steps/mail/autocomplete.inc | 18 | ||||
-rw-r--r-- | program/steps/mail/check_recent.inc | 9 | ||||
-rw-r--r-- | program/steps/mail/compose.inc | 59 | ||||
-rw-r--r-- | program/steps/mail/copy.inc | 16 | ||||
-rw-r--r-- | program/steps/mail/folders.inc | 4 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 238 | ||||
-rw-r--r-- | program/steps/mail/get.inc | 2 | ||||
-rw-r--r-- | program/steps/mail/list.inc | 106 | ||||
-rw-r--r-- | program/steps/mail/list_contacts.inc | 2 | ||||
-rw-r--r-- | program/steps/mail/move_del.inc | 17 | ||||
-rw-r--r-- | program/steps/mail/search.inc | 26 | ||||
-rw-r--r-- | program/steps/mail/search_contacts.inc | 2 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 62 | ||||
-rw-r--r-- | program/steps/mail/show.inc | 22 |
15 files changed, 323 insertions, 285 deletions
diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc index 85bc36cac..5eaa655e3 100644 --- a/program/steps/mail/attachments.inc +++ b/program/steps/mail/attachments.inc @@ -38,7 +38,7 @@ if (!$COMPOSE) { // remove an attachment -if ($RCMAIL->action=='remove-attachment') { +if ($RCMAIL->action == 'remove-attachment') { $id = 'undefined'; if (preg_match('/^rcmfile(\w+)$/', $_POST['_file'], $regs)) { @@ -60,32 +60,14 @@ if ($RCMAIL->action=='remove-attachment') { exit; } -if ($RCMAIL->action=='display-attachment') { +if ($RCMAIL->action == 'display-attachment') { $id = 'undefined'; if (preg_match('/^rcmfile(\w+)$/', $_GET['_file'], $regs)) { $id = $regs[1]; } - if ($attachment = $COMPOSE['attachments'][$id]) { - $attachment = $RCMAIL->plugins->exec_hook('attachment_display', $attachment); - } - - if ($attachment['status']) { - if (empty($attachment['size'])) { - $attachment['size'] = $attachment['data'] ? strlen($attachment['data']) : @filesize($attachment['path']); - } - - header('Content-Type: ' . $attachment['mimetype']); - header('Content-Length: ' . $attachment['size']); - - if ($attachment['data']) { - echo $attachment['data']; - } - else if ($attachment['path']) { - readfile($attachment['path']); - } - } + $RCMAIL->display_uploaded_file($COMPOSE['attachments'][$id]); exit; } @@ -139,6 +121,7 @@ if (is_array($_FILES['_attachments']['tmp_name'])) { 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id), 'title' => $RCMAIL->gettext('delete'), 'class' => 'delete', + 'aria-label' => $RCMAIL->gettext('delete') . ' ' . $attachment['name'], ), $button); $content .= rcube::Q($attachment['name']); diff --git a/program/steps/mail/autocomplete.inc b/program/steps/mail/autocomplete.inc index 71b337a53..30b8f2299 100644 --- a/program/steps/mail/autocomplete.inc +++ b/program/steps/mail/autocomplete.inc @@ -90,8 +90,14 @@ if (!empty($book_types) && strlen($search)) { // skip duplicates if (!in_array($contact, $contacts)) { - $contacts[] = array('name' => $contact, 'type' => $sql_arr['_type']); - $sort_keys[] = sprintf('%s %03d', $sql_arr['name'] , $idx++); + $contact = array('name' => $contact, 'type' => $sql_arr['_type']); + + if (($display = rcube_addressbook::compose_search_name($sql_arr, $email, $name)) && $display != $contact['name']) { + $contact['display'] = $display; + } + + $contacts[] = $contact; + $sort_keys[] = sprintf('%s %03d', $contact['display'] ?: $name, $idx++); if (count($contacts) >= $MAXNUM) { break 2; @@ -118,7 +124,13 @@ if (!empty($book_types) && strlen($search)) { if ($group_prop['email']) { $idx = 0; foreach ((array)$group_prop['email'] as $email) { - $contacts[] = array('name' => format_email_recipient($email, $group['name']), 'type' => 'group'); + $contacts[] = array( + 'name' => format_email_recipient($email, $group['name']), + 'email' => $email, + 'type' => 'group', + 'id' => $group['ID'], + 'source' => $id, + ); $sort_keys[] = sprintf('%s %03d', $group['name'] , $idx++); if (count($contacts) >= $MAXNUM) { diff --git a/program/steps/mail/check_recent.inc b/program/steps/mail/check_recent.inc index cfdcda605..b95819415 100644 --- a/program/steps/mail/check_recent.inc +++ b/program/steps/mail/check_recent.inc @@ -77,15 +77,16 @@ foreach ($a_mailboxes as $mbox_name) { if ($search_request && isset($_SESSION['search'])) { unset($search_request); // only do this once $_SESSION['search'] = $RCMAIL->storage->refresh_search(); - if ($_SESSION['search'][1]->multi) + if ($_SESSION['search'][1]->multi) { $mbox_name = ''; + } } if (!empty($_POST['_quota'])) { - $OUTPUT->command('set_quota', $RCMAIL->quota_content()); + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox_name)); } - $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS')); + $OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS', true)); // "No-list" mode, don't get messages if (empty($_POST['_list'])) { @@ -146,7 +147,7 @@ foreach ($a_mailboxes as $mbox_name) { // set trash folder state if ($mbox_name === $trash) { - $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox_name, 'EXISTS')); + $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($mbox_name, 'EXISTS', true)); } } diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 2b717d673..1770a1bcb 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -80,7 +80,7 @@ if (!is_array($COMPOSE)) { $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubjectwarning', 'cancel', 'nobodywarning', 'notsentwarning', 'notuploadedwarning', 'savingmessage', 'sendingmessage', 'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany', - 'fileuploaderror', 'sendmessage', 'savenewresponse', 'responsename', 'responsetext', 'save', + 'fileuploaderror', 'sendmessage', 'newresponse', 'responsename', 'responsetext', 'save', 'savingresponse', 'restoresavedcomposedata', 'restoremessage', 'delete', 'restore', 'ignore', 'selectimportfile'); @@ -91,6 +91,7 @@ $OUTPUT->set_env('session_id', session_id()); $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', ','))); +$OUTPUT->set_env('save_localstorage', (bool)$RCMAIL->config->get('compose_save_localstorage')); $drafts_mbox = $RCMAIL->config->get('drafts_mbox'); $config_show_sig = $RCMAIL->config->get('show_sig', 1); @@ -280,6 +281,7 @@ $from_email = @mb_strtolower($MESSAGE->compose['from_email']); foreach ($parts as $header) { $fvalue = ''; $decode_header = true; + $charset = $MESSAGE->headers->charset; // we have a set of recipients stored is session if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto']) @@ -287,16 +289,19 @@ foreach ($parts as $header) { ) { $fvalue = urldecode($_SESSION['mailto'][$mailto_id]); $decode_header = false; + $charset = $RCMAIL->output->charset; // 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); + $fvalue = rcube_utils::get_input_value('_'.$header, rcube_utils::INPUT_POST, TRUE); + $charset = $RCMAIL->output->charset; } else if (!empty($COMPOSE['param'][$header])) { - $fvalue = $COMPOSE['param'][$header]; + $fvalue = $COMPOSE['param'][$header]; + $charset = $RCMAIL->output->charset; } else if ($compose_mode == RCUBE_COMPOSE_REPLY) { // get recipent address(es) out of the message headers @@ -337,9 +342,9 @@ foreach ($parts as $header) { // 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); + $from = rcube_mime::decode_address_list($v, null, false, $charset, true); + $to = rcube_mime::decode_address_list($MESSAGE->headers->to, null, false, $charset, true); + $replyto = rcube_mime::decode_address_list($MESSAGE->headers->replyto, null, false, $charset, true); if (count($replyto) && !count(array_diff($to, $replyto)) && count(array_diff($from, $to))) { $fvalue .= (!empty($fvalue) ? $separator : '') . $v; @@ -365,7 +370,7 @@ foreach ($parts as $header) { // 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); + $to_addresses = rcube_mime::decode_address_list($fvalue, null, $decode_header, $charset); $fvalue = array(); foreach ($to_addresses as $addr_part) { @@ -611,7 +616,7 @@ function rcmail_compose_header_from($attrib) $text = $html = $sql_arr['signature']; if ($sql_arr['html_signature']) { - $h2t = new rcube_html2text($sql_arr['signature'], false, false); + $h2t = new rcube_html2text($sql_arr['signature'], false, true); $text = trim($h2t->get_text()); } else { @@ -624,7 +629,8 @@ function rcmail_compose_header_from($attrib) } if (!$sql_arr['html_signature']) { - $html = "<pre>" . $html . "</pre>"; + $t2h = new rcube_text2html($sql_arr['signature'], false); + $html = $t2h->get_html(); } $a_signatures[$identity_id]['text'] = $text; @@ -826,15 +832,8 @@ function rcmail_compose_part_body($part, $isHtml = false) } } - if ($part->ctype_parameters['format'] == 'flowed') { - $body = rcube_mime::unfold_flowed($body); - } - // add HTML formatting - $body = rcmail_plain_body($body); - if ($body) { - $body = '<pre>' . $body . '</pre>'; - } + $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); } } else { @@ -957,8 +956,7 @@ function rcmail_compose_body($attrib) "googie.setLanguages(%s);\n". "googie.setCurrentLanguage('%s');\n". "googie.setDecoration(false);\n". - "googie.decorateTextarea('%s');\n". - "%s.set_env('spellcheck', googie);", + "googie.decorateTextarea('%s');\n", $RCMAIL->output->get_skin_path(), $RCMAIL->url(array('_task' => 'utils', '_action' => 'spell', '_remote' => 1)), !empty($dictionary) ? 'true' : 'false', @@ -970,14 +968,13 @@ function rcmail_compose_body($attrib) rcube::JQ(rcube::Q($RCMAIL->gettext('addtodict'))), rcube_output::json_serialize($spellcheck_langs), $lang, - $attrib['id'], - rcmail_output::JS_OBJECT_NAME), 'foot'); + $attrib['id']), '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>'; + $out .= "\n".'<iframe name="savetarget" src="program/resources/blank.gif" style="width:0;height:0;border:none;visibility:hidden;" aria-hidden="true"></iframe>'; return $out; } @@ -1463,6 +1460,9 @@ function rcmail_compose_subject($attrib) $subject = $MESSAGE->subject; else $subject = 'Re: '.$MESSAGE->subject; + + // replace (was: ...) (#1489375) + $subject = preg_replace('/\s*\([wW]as:[^\)]+\)\s*$/', '', $subject); } // create a forward-subject else if ($compose_mode == RCUBE_COMPOSE_FORWARD) { @@ -1525,7 +1525,9 @@ function rcmail_compose_attachment_list($attrib) 'href' => "#delete", 'title' => $RCMAIL->gettext('delete'), 'onclick' => sprintf("return %s.command('remove-attachment','rcmfile%s', this)", rcmail_output::JS_OBJECT_NAME, $id), - 'class' => 'delete' + 'class' => 'delete', + 'tabindex' => $attrib['tabindex'] ?: '0', + 'aria-label' => $RCMAIL->gettext('delete') . ' ' . $a_prop['name'], ), $button ) . rcube::Q($a_prop['name']) @@ -1551,6 +1553,12 @@ function rcmail_compose_attachment_list($attrib) $OUTPUT->set_env('attachments', $jslist); $OUTPUT->add_gui_object('attachmentlist', $attrib['id']); + // put tabindex value into data-tabindex attribute + if (isset($attrib['tabindex'])) { + $attrib['data-tabindex'] = $attrib['tabindex']; + unset($attrib['tabindex']); + } + return html::tag('ul', $attrib, $out, html::$common_attrib); } @@ -1707,7 +1715,7 @@ function rcmail_editor_selector($attrib) if (empty($attrib['name'])) $attrib['name'] = 'editorSelect'; - $attrib['onchange'] = "return rcmail_toggle_editor(this, '".$attrib['editorid']."', '_is_html')"; + $attrib['onchange'] = "return rcmail.command('toggle-editor', {id: '".$attrib['editorid']."', html: this.value == 'html'}, '', event)"; $select = new html_select($attrib); @@ -1864,9 +1872,10 @@ function rcmail_compose_responses_list($attrib) foreach ($RCMAIL->get_compose_responses(true) as $response) { $key = $response['key']; $item = html::a(array( - 'href '=> '#'.urlencode($response['name']), + 'href' => '#'.urlencode($response['name']), 'class' => rtrim('insertresponse ' . $attrib['itemclass']), 'unselectable' => 'on', + 'tabindex' => '0', 'rel' => $key, ), rcube::Q($response['name'])); diff --git a/program/steps/mail/copy.inc b/program/steps/mail/copy.inc index 86586d34d..585310d47 100644 --- a/program/steps/mail/copy.inc +++ b/program/steps/mail/copy.inc @@ -24,15 +24,19 @@ if (!$OUTPUT->ajax_call) { return; } -// move messages +// copy messages if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { - $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true); + $target = rcube_utils::get_input_value('_target_mbox', rcube_utils::INPUT_POST, true); + $sources = array(); - foreach (rcmail::get_uids() as $mbox => $uids) { - if ($mbox === $target) + foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { + if ($mbox === $target) { $copied++; - else + } + else { $copied += (int)$RCMAIL->storage->copy_message($uids, $target, $mbox); + $sources[] = $mbox; + } } if (!$copied) { @@ -47,7 +51,7 @@ if (!empty($_POST['_uid']) && strlen($_POST['_target_mbox'])) { rcmail_send_unread_count($target, true); - $OUTPUT->command('set_quota', $RCMAIL->quota_content()); + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX')); } // unknown action or missing query param else { diff --git a/program/steps/mail/folders.inc b/program/steps/mail/folders.inc index 519a41fdd..49bf25377 100644 --- a/program/steps/mail/folders.inc +++ b/program/steps/mail/folders.inc @@ -35,7 +35,7 @@ if ($RCMAIL->action == 'expunge') { $OUTPUT->show_message('folderexpunged', 'confirmation'); if (!empty($_REQUEST['_reload'])) { - $OUTPUT->command('set_quota', $RCMAIL->quota_content()); + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox)); $OUTPUT->command('message_list.clear'); $RCMAIL->action = 'list'; return; @@ -69,7 +69,7 @@ else if ($RCMAIL->action == 'purge') { $OUTPUT->command('message_list.clear'); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text(), $mbox); $OUTPUT->command('set_unread_count', $mbox, 0); - $OUTPUT->command('set_quota', $RCMAIL->quota_content()); + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $mbox)); rcmail_set_unseen_count($mbox, 0); // set trash folder state diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index 7270cf95a..a7c483bba 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -23,39 +23,8 @@ // always instantiate storage object (but not connect to server yet) $RCMAIL->storage_init(); -// set imap properties and session vars -if (!strlen($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))) { - $mbox = strlen($_SESSION['mbox']) ? $_SESSION['mbox'] : 'INBOX'; -} -if (!($page = intval($_GET['_page']))) { - $page = $_SESSION['page'] ? $_SESSION['page'] : 1; -} - -$RCMAIL->storage->set_folder($_SESSION['mbox'] = $mbox); -$RCMAIL->storage->set_page($_SESSION['page'] = $page); - -$a_threading = $RCMAIL->config->get('message_threading', array()); -$message_sort_col = $RCMAIL->config->get('message_sort_col'); -$message_sort_order = $RCMAIL->config->get('message_sort_order'); - -// set default sort col/order to session -if (!isset($_SESSION['sort_col'])) { - $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : ''; -} -if (!isset($_SESSION['sort_order'])) { - $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC'; -} - -// set threads mode -if (isset($_GET['_threads'])) { - if ($_GET['_threads']) - $a_threading[$_SESSION['mbox']] = true; - else - unset($a_threading[$_SESSION['mbox']]); - - $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); -} -$RCMAIL->storage->set_threading($a_threading[$_SESSION['mbox']]); +// init environment - set current folder, page, list mode +rcmail_init_env(); // set message set for search result if (!empty($_REQUEST['_search']) && isset($_SESSION['search']) @@ -135,14 +104,20 @@ if (empty($RCMAIL->action) || $RCMAIL->action == 'list') { } } + if (!empty($_GET['_uid'])) { + $OUTPUT->set_env('list_uid', $_GET['_uid']); + } + // set configuration $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted', - 'skip_deleted', 'display_next', 'message_extwin', 'compose_extwin', 'forward_attachment')); + 'skip_deleted', 'display_next', 'message_extwin', 'forward_attachment')); if (!$OUTPUT->ajax_call) { $OUTPUT->add_label('checkingmail', 'deletemessage', 'movemessagetotrash', 'movingmessage', 'copyingmessage', 'deletingmessage', 'markingmessage', - 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching'); + 'copy', 'move', 'quota', 'replyall', 'replylist', 'stillsearching', + 'flagged', 'unflagged', 'unread', 'deleted', 'replied', 'forwarded', + 'priority', 'withattachment', 'fileuploaderror'); } $pagetitle = $RCMAIL->localize_foldername($mbox_name, true); @@ -185,6 +160,64 @@ $RCMAIL->register_action_map(array( /** + * Sets storage properties and session + */ +function rcmail_init_env() +{ + global $RCMAIL; + + $default_threading = $RCMAIL->config->get('default_list_mode', 'list') == 'threads'; + $a_threading = $RCMAIL->config->get('message_threading', array()); + $message_sort_col = $RCMAIL->config->get('message_sort_col'); + $message_sort_order = $RCMAIL->config->get('message_sort_order'); + + // set imap properties and session vars + if (!strlen($mbox = rcube_utils::get_input_value('_mbox', rcube_utils::INPUT_GPC, true))) { + $mbox = strlen($_SESSION['mbox']) ? $_SESSION['mbox'] : 'INBOX'; + } + if (!($page = intval($_GET['_page']))) { + $page = $_SESSION['page'] ? $_SESSION['page'] : 1; + } + + $RCMAIL->storage->set_folder($_SESSION['mbox'] = $mbox); + $RCMAIL->storage->set_page($_SESSION['page'] = $page); + + // set default sort col/order to session + if (!isset($_SESSION['sort_col'])) { + $_SESSION['sort_col'] = $message_sort_col ? $message_sort_col : ''; + } + if (!isset($_SESSION['sort_order'])) { + $_SESSION['sort_order'] = strtoupper($message_sort_order) == 'ASC' ? 'ASC' : 'DESC'; + } + + // set threads mode + if (isset($_GET['_threads'])) { + if ($_GET['_threads']) { + // re-set current page number when listing mode changes + if (!$a_threading[$_SESSION['mbox']]) { + $RCMAIL->storage->set_page($_SESSION['page'] = 1); + } + + $a_threading[$_SESSION['mbox']] = true; + } + else { + // re-set current page number when listing mode changes + if ($a_threading[$_SESSION['mbox']]) { + $RCMAIL->storage->set_page($_SESSION['page'] = 1); + } + + $a_threading[$_SESSION['mbox']] = false; + } + + $RCMAIL->user->save_prefs(array('message_threading' => $a_threading)); + } + + $threading = isset($a_threading[$_SESSION['mbox']]) ? $a_threading[$_SESSION['mbox']] : $default_threading; + + $RCMAIL->storage->set_threading($threading); +} + +/** * Returns default search mods */ function rcmail_search_mods() @@ -351,13 +384,18 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null $head_replace = true; } - // add 'folder' column to list on multi-folder searches - $search_set = $RCMAIL->storage->get_search_set(); + $search_set = $RCMAIL->storage->get_search_set(); $multifolder = $search_set && $search_set[1]->multi; + + // add/remove 'folder' column to the list on multi-folder searches if ($multifolder && !in_array('folder', $a_show_cols)) { $a_show_cols[] = 'folder'; $head_replace = true; } + else if (!$multifolder && ($found = array_search('folder', $a_show_cols)) !== false) { + unset($a_show_cols[$found]); + $head_replace = true; + } $mbox = $RCMAIL->storage->get_folder(); @@ -369,6 +407,7 @@ function rcmail_js_message_list($a_headers, $insert_top=false, $a_show_cols=null // Make sure there are no duplicated columns (#1486999) $a_show_cols = array_unique($a_show_cols); + $_SESSION['list_attrib']['columns'] = $a_show_cols; // Plugins may set header's list_cols/list_flags and other rcube_message_header variables // and list columns @@ -507,14 +546,19 @@ function rcmail_message_list_head($attrib, $a_show_cols) $a_sort_cols = array('subject', 'date', 'from', 'to', 'fromto', 'size', 'cc'); if (!empty($attrib['optionsmenuicon'])) { - $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu')"; - if ($attrib['optionsmenuicon'] === true || $attrib['optionsmenuicon'] == 'true') - $list_menu = html::div(array('onclick' => $onclick, 'class' => 'listmenu', - 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions'))); - else - $list_menu = html::a(array('href' => '#', 'onclick' => $onclick), - html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], - 'id' => 'listmenulink', 'title' => $RCMAIL->gettext('listoptions')))); + $onclick = 'return ' . rcmail_output::JS_OBJECT_NAME . ".command('menu-open', 'messagelistmenu', this, event)"; + $inner = $RCMAIL->gettext('listoptions'); + if (is_string($attrib['optionsmenuicon']) && $attrib['optionsmenuicon'] != 'true') { + $inner = html::img(array('src' => $skin_path . $attrib['optionsmenuicon'], 'alt' => $RCMAIL->gettext('listoptions'))); + } + $list_menu = html::a(array( + 'href' => '#list-options', + 'onclick' => $onclick, + 'class' => 'listmenu', + 'id' => 'listmenulink', + 'title' => $RCMAIL->gettext('listoptions'), + 'tabindex' => '0', + ), $inner); } else { $list_menu = ''; @@ -534,12 +578,14 @@ function rcmail_message_list_head($attrib, $a_show_cols) // get column name switch ($col) { case 'flag': - $col_name = html::span('flagged', ' '); + $col_name = html::span('flagged', $RCMAIL->gettext('flagged')); break; case 'attachment': case 'priority': + $col_name = html::span($col, $RCMAIL->gettext($col)); + break; case 'status': - $col_name = html::span($col, ' '); + $col_name = html::span($col, $RCMAIL->gettext('readstatus')); break; case 'threads': $col_name = $list_menu; @@ -854,95 +900,29 @@ function rcmail_print_body($part, $p = array()) // plaintext postprocessing if ($part->ctype_secondary == 'plain') { - if ($part->ctype_secondary == 'plain' && $part->ctype_parameters['format'] == 'flowed') { - $body = rcube_mime::unfold_flowed($body); - } - - $body = rcmail_plain_body($body); + $body = rcmail_plain_body($body, $part->ctype_parameters['format'] == 'flowed'); } // allow post-processing of the message body $data = $RCMAIL->plugins->exec_hook('message_part_after', array('type' => $part->ctype_secondary, 'body' => $body, 'id' => $part->mime_id) + $data); - return $data['type'] == 'html' ? $data['body'] : html::tag('pre', array(), $data['body']); + return $data['body']; } /** * Handle links and citation marks in plain text message * * @param string Plain text string + * @param boolean Set to True if the source text is in format=flowed * * @return string Formatted HTML string */ -function rcmail_plain_body($body) +function rcmail_plain_body($body, $flowed = false) { - global $RCMAIL; - - // make links and email-addresses clickable - $attribs = array('link_attribs' => array('rel' => 'noreferrer', 'target' => '_blank')); - $replacer = new rcmail_string_replacer($attribs); - - // search for patterns like links and e-mail addresses and replace with tokens - $body = $replacer->replace($body); - - // split body into single lines - $body = preg_split('/\r?\n/', $body); - $quote_level = 0; - $last = -1; - - // find/mark quoted lines... - for ($n=0, $cnt=count($body); $n < $cnt; $n++) { - if ($body[$n][0] == '>' && preg_match('/^(>+ {0,1})+/', $body[$n], $regs)) { - $q = substr_count($regs[0], '>'); - $body[$n] = substr($body[$n], strlen($regs[0])); - - if ($q > $quote_level) { - $body[$n] = $replacer->get_replacement($replacer->add( - str_repeat('<blockquote>', $q - $quote_level))) . $body[$n]; - $last = $n; - } - else if ($q < $quote_level) { - $body[$n] = $replacer->get_replacement($replacer->add( - str_repeat('</blockquote>', $quote_level - $q))) . $body[$n]; - $last = $n; - } - } - else { - $q = 0; - if ($quote_level > 0) - $body[$n] = $replacer->get_replacement($replacer->add( - str_repeat('</blockquote>', $quote_level))) . $body[$n]; - } - - $quote_level = $q; - } - - $body = join("\n", $body); - - // quote plain text (don't use rcube::Q() here, to display entities "as is") - $table = get_html_translation_table(HTML_SPECIALCHARS); - unset($table['?']); - $body = strtr($body, $table); - - // colorize signature (up to <sig_max_lines> lines) - $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)) - . '<span class="sig">'.substr($body, $sp).'</span>'; - } - - break; - } - } - - // insert url/mailto links and citation tags - $body = $replacer->resolve($body); + $options = array('flowed' => $flowed, 'wrap' => !$flowed, 'replacer' => 'rcmail_string_replacer'); + $text2html = new rcube_text2html($body, false, $options); + $body = $text2html->get_html(); return $body; } @@ -1097,7 +1077,9 @@ function rcmail_message_headers($attrib, $headers=null) $plugin = $RCMAIL->plugins->exec_hook('message_headers_output', array( 'output' => $output_headers, 'headers' => $headers_obj, - 'exclude' => $exclude_headers + 'exclude' => $exclude_headers, // readonly + 'folder' => $MESSAGE->folder, // readonly + 'uid' => $MESSAGE->uid, // readonly )); // single header value is requested @@ -1272,8 +1254,8 @@ function rcmail_message_body($attrib) $plugin = $RCMAIL->plugins->exec_hook('message_body_prefix', array('part' => $MESSAGE, 'prefix' => '')); - $out .= html::div('message-part', $plugin['prefix'] . html::tag('pre', array(), - rcmail_plain_body(rcube::Q($MESSAGE->body, 'strict', false)))); + $out .= html::div('message-part', + $plugin['prefix'] . rcmail_plain_body($MESSAGE->body)); } } @@ -1840,7 +1822,7 @@ function rcmail_send_mdn($message, &$smtp_error) $body = $RCMAIL->gettext("yourmessage") . "\r\n\r\n" . "\t" . $RCMAIL->gettext("to") . ': ' . rcube_mime::decode_mime_string($message->headers->to, $message->headers->charset) . "\r\n" . "\t" . $RCMAIL->gettext("subject") . ': ' . $message->subject . "\r\n" . - "\t" . $RCMAIL->gettext("sent") . ': ' . $RCMAIL->format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" . + "\t" . $RCMAIL->gettext("date") . ': ' . $RCMAIL->format_date($message->headers->date, $RCMAIL->config->get('date_long')) . "\r\n" . "\r\n" . $RCMAIL->gettext("receiptnote"); $compose->headers($headers); @@ -2099,6 +2081,7 @@ function rcmail_message_import_form($attrib = array()) )); $content = html::tag('input', array('type' => 'hidden', 'name' => '_unlock', 'value' => '')) + . html::tag('input', array('type' => 'hidden', 'name' => '_framed', 'value' => '1')) . html::div(null, $fileinput->show()) . html::div('hint', $RCMAIL->gettext(array('name' => 'maxuploadsize', 'vars' => array('size' => $max_filesize)))); @@ -2136,11 +2119,10 @@ function rcmail_compose_contact_groups($abook, $source_id, $search = null, $sear foreach ($abook->list_groups($search, $search_mode) as $group) { $abook->reset(); $abook->set_group($group['ID']); - $group_prop = $abook->get_group($group['ID']); // group (distribution list) with email address(es) - if ($group_prop['email']) { - foreach ((array)$group_prop['email'] as $email) { + if ($group['email']) { + foreach ((array)$group['email'] as $email) { $row_id = 'G'.$group['ID']; $jsresult[$row_id] = format_email_recipient($email, $group['name']); $OUTPUT->command('add_contact_row', $row_id, array( @@ -2148,7 +2130,7 @@ function rcmail_compose_contact_groups($abook, $source_id, $search = null, $sear } } // make virtual groups clickable to list their members - else if ($group_prop['virtual']) { + else if ($group['virtual']) { $row_id = 'G'.$group['ID']; $OUTPUT->command('add_contact_row', $row_id, array( 'contactgroup' => html::a(array( diff --git a/program/steps/mail/get.inc b/program/steps/mail/get.inc index 02d57c7dc..b260d2c85 100644 --- a/program/steps/mail/get.inc +++ b/program/steps/mail/get.inc @@ -354,7 +354,7 @@ else if (strlen($part_id)) { } // send part as-it-is else { - if ($part->body) { + if ($part->body && empty($plugin['download'])) { header("Content-Length: " . strlen($part->body)); echo $part->body; $sent = true; diff --git a/program/steps/mail/list.inc b/program/steps/mail/list.inc index c4a6df57b..2dcc40d17 100644 --- a/program/steps/mail/list.inc +++ b/program/steps/mail/list.inc @@ -20,7 +20,7 @@ */ if (!$OUTPUT->ajax_call) { - return; + return; } $save_arr = array(); @@ -28,28 +28,28 @@ $dont_override = (array) $RCMAIL->config->get('dont_override'); // is there a sort type for this request? if ($sort = rcube_utils::get_input_value('_sort', rcube_utils::INPUT_GET)) { - // yes, so set the sort vars - list($sort_col, $sort_order) = explode('_', $sort); - - // set session vars for sort (so next page and task switch know how to sort) - if (!in_array('message_sort_col', $dont_override)) { - $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col; - } - if (!in_array('message_sort_order', $dont_override)) { - $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order; - } + // yes, so set the sort vars + list($sort_col, $sort_order) = explode('_', $sort); + + // set session vars for sort (so next page and task switch know how to sort) + if (!in_array('message_sort_col', $dont_override)) { + $_SESSION['sort_col'] = $save_arr['message_sort_col'] = $sort_col; + } + if (!in_array('message_sort_order', $dont_override)) { + $_SESSION['sort_order'] = $save_arr['message_sort_order'] = $sort_order; + } } // is there a set of columns for this request? if ($cols = rcube_utils::get_input_value('_cols', rcube_utils::INPUT_GET)) { - $_SESSION['list_attrib']['columns'] = explode(',', $cols); - if (!in_array('list_cols', $dont_override)) { - $save_arr['list_cols'] = explode(',', $cols); - } + $_SESSION['list_attrib']['columns'] = explode(',', $cols); + if (!in_array('list_cols', $dont_override)) { + $save_arr['list_cols'] = explode(',', $cols); + } } if (!empty($save_arr)) { - $RCMAIL->user->save_prefs($save_arr); + $RCMAIL->user->save_prefs($save_arr); } $mbox_name = $RCMAIL->storage->get_folder(); @@ -60,27 +60,32 @@ $RCMAIL->storage->folder_sync($mbox_name); // initialize searching result if search_filter is used if ($_SESSION['search_filter'] && $_SESSION['search_filter'] != 'ALL') { - $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']); - $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column()); - $_SESSION['search'] = $RCMAIL->storage->get_search_set(); - $_SESSION['search_request'] = $search_request; - $OUTPUT->set_env('search_request', $search_request); - $OUTPUT->set_env('search_filter', $_SESSION['search_filter']); + $search_request = md5($mbox_name.$_SESSION['search_scope'].$_SESSION['search_filter']); + $RCMAIL->storage->search($mbox_name, $_SESSION['search_filter'], RCUBE_CHARSET, rcmail_sort_column()); + + $_SESSION['search'] = $RCMAIL->storage->get_search_set(); + $_SESSION['search_request'] = $search_request; + + $OUTPUT->set_env('search_request', $search_request); + $OUTPUT->set_env('search_filter', $_SESSION['search_filter']); + + $multifolder = is_a($_SESSION['search'][1], 'rcube_result_multifolder'); } // fetch message headers -if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) - $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order()); +if ($count = $RCMAIL->storage->count($mbox_name, $threading ? 'THREADS' : 'ALL', !empty($_REQUEST['_refresh']))) { + $a_headers = $RCMAIL->storage->list_messages($mbox_name, NULL, rcmail_sort_column(), rcmail_sort_order()); +} // update search set (possible change of threading mode) if (!empty($_REQUEST['_search']) && isset($_SESSION['search']) && $_SESSION['search_request'] == $_REQUEST['_search'] ) { - $_SESSION['search'] = $RCMAIL->storage->get_search_set(); + $_SESSION['search'] = $RCMAIL->storage->get_search_set(); } // remove old search data else if (empty($_REQUEST['_search']) && isset($_SESSION['search'])) { - $RCMAIL->session->remove('search'); + $RCMAIL->session->remove('search'); } // empty result? we'll skip UNSEEN counting in rcmail_send_unread_count() @@ -93,44 +98,47 @@ rcmail_send_unread_count($mbox_name, !empty($_REQUEST['_refresh']), $unseen); // update message count display $pages = ceil($count/$RCMAIL->storage->get_pagesize()); -$exists = $RCMAIL->storage->count($mbox_name, 'EXISTS'); +$page = $count ? $RCMAIL->storage->get_page() : 1; +$exists = $RCMAIL->storage->count($mbox_name, 'EXISTS', true); $OUTPUT->set_env('messagecount', $count); $OUTPUT->set_env('pagecount', $pages); $OUTPUT->set_env('threading', $threading); -$OUTPUT->set_env('current_page', $count ? $RCMAIL->storage->get_page() : 1); +$OUTPUT->set_env('current_page', $page); $OUTPUT->set_env('exists', $exists); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count), $mbox_name); // remove old message rows if commanded by the client if (!empty($_REQUEST['_clear'])) { - $OUTPUT->command('clear_message_list'); + $OUTPUT->command('clear_message_list'); } // add message rows rcmail_js_message_list($a_headers, false, $cols); if (isset($a_headers) && count($a_headers)) { - if ($search_request) { - $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); - } - - // remember last HIGHESTMODSEQ value (if supported) - // we need it for flag updates in check-recent - $data = $RCMAIL->storage->folder_data($mbox_name); - if (!empty($data['HIGHESTMODSEQ'])) { - $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; - } + if ($search_request) { + $OUTPUT->show_message('searchsuccessful', 'confirmation', array('nr' => $count)); + } + + // remember last HIGHESTMODSEQ value (if supported) + // we need it for flag updates in check-recent + $data = $RCMAIL->storage->folder_data($mbox_name); + if (!empty($data['HIGHESTMODSEQ'])) { + $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + } } else { - // handle IMAP errors (e.g. #1486905) - if ($err_code = $RCMAIL->storage->get_error_code()) { - $RCMAIL->display_server_error(); - } - else if ($search_request) - $OUTPUT->show_message('searchnomatch', 'notice'); - else - $OUTPUT->show_message('nomessagesfound', 'notice'); + // handle IMAP errors (e.g. #1486905) + if ($err_code = $RCMAIL->storage->get_error_code()) { + $RCMAIL->display_server_error(); + } + else if ($search_request) { + $OUTPUT->show_message('searchnomatch', 'notice'); + } + else { + $OUTPUT->show_message('nomessagesfound', 'notice'); + } } // set trash folder state @@ -138,5 +146,9 @@ if ($mbox_name === $RCMAIL->config->get('trash_mbox')) { $OUTPUT->command('set_trash_count', $exists); } +if ($page == 1) { + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? 'INBOX' : $mbox_name)); +} + // send response $OUTPUT->send(); diff --git a/program/steps/mail/list_contacts.inc b/program/steps/mail/list_contacts.inc index 0ee81135b..4f17beffd 100644 --- a/program/steps/mail/list_contacts.inc +++ b/program/steps/mail/list_contacts.inc @@ -110,7 +110,7 @@ else if (!empty($result) && $result->count > 0) { $keyname = $row['_type'] == 'group' ? 'contactgroup' : 'contact'; $OUTPUT->command('add_contact_row', $row_id, array( - $keyname => html::span(array('title' => $email), rcube::Q($name ? $name : $email) . + $keyname => html::a(array('title' => $email), rcube::Q($name ? $name : $email) . ($name && count($emails) > 1 ? ' ' . html::span('email', rcube::Q($email)) : '') )), $classname); } diff --git a/program/steps/mail/move_del.inc b/program/steps/mail/move_del.inc index c29985875..4c57d6fa9 100644 --- a/program/steps/mail/move_del.inc +++ b/program/steps/mail/move_del.inc @@ -27,6 +27,7 @@ if (!$OUTPUT->ajax_call) $threading = (bool) $RCMAIL->storage->get_threading(); $old_count = $RCMAIL->storage->count(NULL, $threading ? 'THREADS' : 'ALL'); $old_pages = ceil($old_count / $RCMAIL->storage->get_pagesize()); +$sources = array(); $trash = $RCMAIL->config->get('trash_mbox'); @@ -36,12 +37,13 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe $trash = $RCMAIL->config->get('trash_mbox'); $success = true; - foreach (rcmail::get_uids() as $mbox => $uids) { + foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { if ($mbox === $target) { $count += count($uids); } else if ($RCMAIL->storage->move_message($uids, $target, $mbox)) { $count += count($uids); + $sources[] = $mbox; } else { $success = false; @@ -69,10 +71,11 @@ if ($RCMAIL->action == 'move' && !empty($_POST['_uid']) && strlen($_POST['_targe } } // delete messages -else if ($RCMAIL->action=='delete' && !empty($_POST['_uid'])) { - foreach (rcmail::get_uids() as $mbox => $uids) { - $del += (int)$RCMAIL->storage->delete_message($uids, $mbox); - $count += count($uids); +else if ($RCMAIL->action == 'delete' && !empty($_POST['_uid'])) { + foreach (rcmail::get_uids(null, null, $multifolder) as $mbox => $uids) { + $del += (int)$RCMAIL->storage->delete_message($uids, $mbox); + $count += count($uids); + $sources[] = $mbox; } if (!$del) { @@ -146,7 +149,7 @@ else { rcmail_send_unread_count($target, true); } - $OUTPUT->command('set_quota', $RCMAIL->quota_content()); + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $multifolder ? $sources[0] : 'INBOX')); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($msg_count), $mbox); if ($threading) { @@ -166,7 +169,7 @@ else { $OUTPUT->command('set_trash_count', $exists); } else if ($target !== null && $target === $trash) { - $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($trash, 'EXISTS')); + $OUTPUT->command('set_trash_count', $RCMAIL->storage->count($trash, 'EXISTS', true)); } } diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc index e610e9137..b50593480 100644 --- a/program/steps/mail/search.inc +++ b/program/steps/mail/search.inc @@ -127,8 +127,9 @@ if ($search_str) { } else if ($scope == 'sub') { $mboxes = $RCMAIL->storage->list_folders_subscribed($mbox, '*', 'mail'); - if ($mbox != 'INBOX' && $mboxes[0] == 'INBOX') + if ($mbox != 'INBOX' && $mboxes[0] == 'INBOX') { array_shift($mboxes); + } } $result = $RCMAIL->storage->search($mboxes, $search_str, $imap_charset, $sort_column); @@ -144,7 +145,7 @@ if ($search_str) { $_SESSION['last_text_search'] = $str; } $_SESSION['search_request'] = $search_request; -$_SESSION['search_scope'] = $scope; +$_SESSION['search_scope'] = $scope; // Get the headers @@ -162,9 +163,11 @@ if (!empty($result_h)) { // remember last HIGHESTMODSEQ value (if supported) // we need it for flag updates in check-recent - $data = $RCMAIL->storage->folder_data($mbox_name); - if (!empty($data['HIGHESTMODSEQ'])) { - $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + if ($mbox !== null) { + $data = $RCMAIL->storage->folder_data($mbox); + if (!empty($data['HIGHESTMODSEQ'])) { + $_SESSION['list_mod_seq'] = $data['HIGHESTMODSEQ']; + } } } // handle IMAP errors (e.g. #1486905) @@ -179,17 +182,24 @@ else if ($result->incomplete) { else { $OUTPUT->show_message('searchnomatch', 'notice'); $OUTPUT->set_env('multifolder_listing', (bool)$result->multi); - if ($result->multi && $scope == 'all') + if ($result->multi && $scope == 'all') { $OUTPUT->command('select_folder', ''); + } } +$OUTPUT->set_pagetitle($RCMAIL->gettext(array('name' => 'searchfor', 'vars' => array('q' => $str)))); + // update message count display $OUTPUT->set_env('search_request', $search_str ? $search_request : ''); $OUTPUT->set_env('search_filter', $_SESSION['search_filter']); $OUTPUT->set_env('threading', $RCMAIL->storage->get_threading()); $OUTPUT->set_env('messagecount', $count); $OUTPUT->set_env('pagecount', ceil($count/$RCMAIL->storage->get_pagesize())); -$OUTPUT->set_env('exists', $RCMAIL->storage->count($mbox_name, 'EXISTS')); +$OUTPUT->set_env('exists', $mbox === null ? 0 : $RCMAIL->storage->count($mbox, 'EXISTS')); $OUTPUT->command('set_rowcount', rcmail_get_messagecount_text($count, 1), $mbox); -$OUTPUT->set_pagetitle($RCMAIL->gettext(array('name' => 'searchfor', 'vars' => array('q' => $str)))); + +if (!$result->incomplete) { + $OUTPUT->command('set_quota', $RCMAIL->quota_content(null, $result->multi ? 'INBOX' : $mbox)); +} + $OUTPUT->send(); diff --git a/program/steps/mail/search_contacts.inc b/program/steps/mail/search_contacts.inc index d56581695..ccef32dd2 100644 --- a/program/steps/mail/search_contacts.inc +++ b/program/steps/mail/search_contacts.inc @@ -87,7 +87,7 @@ if (!empty($result) && $result->count > 0) { $row_id = $row['ID'].'-'.$i; $jsresult[$row_id] = format_email_recipient($email, $name); $OUTPUT->command('add_contact_row', $row_id, array( - 'contact' => html::span(array('title' => $email), rcube::Q($name ? $name : $email) . + 'contact' => html::a(array('title' => $email), rcube::Q($name ? $name : $email) . ($name && count($emails) > 1 ? ' ' . html::span('email', rcube::Q($email)) : '') )), 'person'); } diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 04ba94f5e..bac751298 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -77,7 +77,7 @@ $mailto = rcmail_email_input_format(rcube_utils::get_input_value('_to', rcube_u $mailcc = rcmail_email_input_format(rcube_utils::get_input_value('_cc', rcube_utils::INPUT_POST, TRUE, $message_charset), true); $mailbcc = rcmail_email_input_format(rcube_utils::get_input_value('_bcc', rcube_utils::INPUT_POST, TRUE, $message_charset), true); -if ($EMAIL_FORMAT_ERROR) { +if ($EMAIL_FORMAT_ERROR && !$savedraft) { $OUTPUT->show_message('emailformaterror', 'error', array('email' => $EMAIL_FORMAT_ERROR)); $OUTPUT->send('iframe'); } @@ -273,20 +273,31 @@ if ($isHtml) { } // append doctype and html/body wrappers - $message_body = '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN">' - . "\r\n<html><body" . (!empty($bstyle) ? " style='" . implode($bstyle, '; ') . "'" : '') . ">\r\n" - . $message_body; + $bstyle = !empty($bstyle) ? (" style='" . implode($bstyle, '; ') . "'") : ''; + $message_body = '<html><head>' + . '<meta http-equiv="Content-Type" content="text/html; charset=' . $message_charset . '" /></head>' + . "<body" . $bstyle . ">\r\n" . $message_body; } if (!$savedraft) { if ($isHtml) { - // remove signature's div ID - $message_body = preg_replace('/\s*id="_rc_sig"/', '', $message_body); - - // add inline css for blockquotes - $bstyle = 'padding-left:5px; border-left:#1010ff 2px solid; margin-left:5px'; - $message_body = preg_replace('/<blockquote>/', - '<blockquote type="cite" style="'.$bstyle.'">', $message_body); + $b_style = 'padding: 0 0.4em; border-left: #1010ff 2px solid; margin: 0'; + $pre_style = 'margin: 0; padding: 0; font-family: monospace'; + + $message_body = preg_replace( + array( + // remove signature's div ID + '/\s*id="_rc_sig"/', + // add inline css for blockquotes and container + '/<blockquote>/', + '/<div class="pre">/' + ), + array( + '', + '<blockquote type="cite" style="'.$b_style.'">', + '<div class="pre" style="'.$pre_style.'">' + ), + $message_body); } // Check spelling before send @@ -300,10 +311,16 @@ if (!$savedraft) { $COMPOSE['spell_checked'] = true; if (!$spell_result) { - $result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml(); + if ($isHtml) { + $result['words'] = $spellchecker->get(); + $result['dictionary'] = (bool) $RCMAIL->config->get('spellcheck_dictionary'); + } + else { + $result = $spellchecker->get_xml(); + } $OUTPUT->show_message('mispellingsfound', 'error'); - $OUTPUT->command('spellcheck_resume', $isHtml, $result); + $OUTPUT->command('spellcheck_resume', $result); $OUTPUT->send('iframe'); } } @@ -411,7 +428,7 @@ if (is_array($COMPOSE['attachments'])) { $attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment); if ($isHtml) { - $dispurl = '/\ssrc\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' + $dispurl = '/\s(poster|src)\s*=\s*[\'"]*\S+display-attachment\S+file=rcmfile' . preg_quote($attachment['id']) . '[\s\'"]*/'; $message_body = $MAIL_MIME->getHTMLBody(); $is_inline = preg_match($dispurl, $message_body); @@ -432,7 +449,7 @@ if (is_array($COMPOSE['attachments'])) { $cid .= '@localhost'; } - $message_body = preg_replace($dispurl, ' src="cid:' . $cid . '" ', $message_body); + $message_body = preg_replace($dispurl, ' \\1="cid:' . $cid . '" ', $message_body); $MAIL_MIME->setHTMLBody($message_body); @@ -467,15 +484,11 @@ if (preg_match('/[^\x00-\x7F]/', $MAIL_MIME->getTXTBody())) { $transfer_encoding = $RCMAIL->config->get('force_7bit') ? 'quoted-printable' : '8bit'; } else { - $text_charset = ''; + $text_charset = 'US-ASCII'; $transfer_encoding = '7bit'; } if ($flowed) { - if (!$text_charset) { - $text_charset = 'US-ASCII'; - } - $text_charset .= ";\r\n format=flowed"; } @@ -728,11 +741,11 @@ function rcmail_get_identity($id) /** * go from this: - * <img src="http[s]://.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> + * <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> * * to this: * - * <img src="/path/on/server/.../tiny_mce/plugins/emotions/images/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> + * <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" border="0" alt="Cool" title="Cool" /> */ function rcmail_fix_emoticon_paths($mime_message) { @@ -743,7 +756,7 @@ function rcmail_fix_emoticon_paths($mime_message) // remove any null-byte characters before parsing $body = preg_replace('/\x00/', '', $body); - $searchstr = 'program/js/tiny_mce/plugins/emotions/img/'; + $searchstr = 'program/js/tinymce/plugins/emoticons/img/'; $offset = 0; // keep track of added images, so they're only added once @@ -912,7 +925,8 @@ function rcmail_generic_message_footer($isHtml) if (!preg_match('/\.(php|ini|conf)$/', $file) && strpos($file, '/etc/') === false) { $footer = file_get_contents($file); if ($isHtml && !$html_footer) { - $footer = '<pre>' . $footer . '</pre>'; + $t2h = new rcube_text2html($footer, false); + $footer = $t2h->get_html(); } return $footer; } diff --git a/program/steps/mail/show.inc b/program/steps/mail/show.inc index beb2cc6e9..d4121fdd8 100644 --- a/program/steps/mail/show.inc +++ b/program/steps/mail/show.inc @@ -80,7 +80,7 @@ if ($uid) { // set configuration $RCMAIL->set_env_config(array('delete_junk', 'flag_for_deletion', 'read_when_deleted', - 'skip_deleted', 'display_next', 'compose_extwin', 'forward_attachment')); + 'skip_deleted', 'display_next', 'forward_attachment')); // set special folders foreach (array('drafts', 'trash', 'junk') as $mbox) { @@ -148,11 +148,14 @@ if ($uid) { if (empty($MESSAGE->headers->flags['SEEN']) && ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0)) ) { + $RCMAIL->output->command('set_unread_message', $MESSAGE->uid, $mbox_name); $RCMAIL->plugins->exec_hook('message_read', array( 'uid' => $MESSAGE->uid, 'mailbox' => $mbox_name, 'message' => $MESSAGE, )); + + $set_seen_flag = true; } } @@ -174,9 +177,7 @@ else // mark message as read -if ($MESSAGE && $MESSAGE->headers && empty($MESSAGE->headers->flags['SEEN']) && - ($RCMAIL->action == 'show' || ($RCMAIL->action == 'preview' && intval($RCMAIL->config->get('preview_pane_mark_read')) == 0)) -) { +if (!empty($set_seen_flag)) { if ($RCMAIL->storage->set_flag($MESSAGE->uid, 'SEEN')) { if ($count = rcmail_get_unseen_count($mbox_name)) { rcmail_set_unseen_count($mbox_name, $count - 1); @@ -198,6 +199,7 @@ function rcmail_message_attachments($attrib) if (sizeof($MESSAGE->attachments)) { foreach ($MESSAGE->attachments as $attach_prop) { $filename = rcmail_attachment_name($attach_prop, true); + $size = ''; if ($PRINT_MODE) { $size = $RCMAIL->message_part_size($attach_prop); @@ -212,6 +214,10 @@ function rcmail_message_attachments($attrib) $title = ''; } + if ($attach_prop->size) { + $size = ' ' . html::span('attachment-size', '(' . $RCMAIL->show_bytes($attach_prop->size) . ')'); + } + $mimetype = rcmail_fix_mimetype($attach_prop->mimetype); $class = rcube_utils::file2class($mimetype, $filename); $id = 'attach' . $attach_prop->mime_id; @@ -221,7 +227,7 @@ function rcmail_message_attachments($attrib) rcmail_output::JS_OBJECT_NAME, $attach_prop->mime_id), 'onmouseover' => $title ? '' : 'rcube_webmail.long_subject_title_ex(this, 0)', 'title' => rcube::Q($title), - ), rcube::Q($filename)); + ), rcube::Q($filename) . $size); $ol .= html::tag('li', array('class' => $class, 'id' => $id), $link); @@ -343,12 +349,14 @@ function rcmail_message_contactphoto($attrib) '_task' => 'addressbook', '_action' => 'photo', '_email' => $MESSAGE->sender['mailto'], - '_alt' => $placeholder + '_alt' => $placeholder, )); + + $attrib['onerror'] = "this.src = '" . ($placeholder ? $placeholder : 'program/resources/blank.gif') . "'"; } else { $photo_img = $placeholder ? $placeholder : 'program/resources/blank.gif'; } - return html::img(array('src' => $photo_img) + $attrib); + return html::img(array('src' => $photo_img, 'alt' => $RCMAIL->gettext('contactphoto')) + $attrib); } |