From 1088d667458ae03a54fcb4b8d290f6218e84d304 Mon Sep 17 00:00:00 2001 From: alecpl <alec@alec.pl> Date: Mon, 05 May 2008 05:59:56 -0400 Subject: [PATCH] - Do charset conversion also for from/to column on messages list --- program/steps/mail/func.inc | 352 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 files changed, 316 insertions(+), 36 deletions(-) diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc index dd38016..34586dd 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -19,8 +19,8 @@ */ -require_once('lib/html2text.inc'); require_once('lib/enriched.inc'); +require_once('include/rcube_smtp.inc'); $EMAIL_ADDRESS_PATTERN = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/i'; @@ -47,7 +47,11 @@ // set message set for search result if (!empty($_REQUEST['_search']) && isset($_SESSION['search'][$_REQUEST['_search']])) + { $IMAP->set_search_set($_SESSION['search'][$_REQUEST['_search']]); + $OUTPUT->set_env('search_request', $_REQUEST['_search']); + $OUTPUT->set_env('search_text', $_SESSION['last_text_search']); + } // define url for getting message parts @@ -67,11 +71,11 @@ $OUTPUT->set_env('junk_mailbox', $CONFIG['junk_mbox']); if (!$OUTPUT->ajax_call) - rcube_add_label('checkingmail', 'deletemessage', 'movemessagetotrash'); + rcube_add_label('checkingmail', 'deletemessage', 'movemessagetotrash', 'movingmessage'); // set page title -if (empty($_action) || $_action == 'list') - $OUTPUT->set_pagetitle(rcube_charset_convert($IMAP->get_mailbox_name(), 'UTF-7')); +if (empty($RCMAIL->action) || $RCMAIL->action == 'list') + $OUTPUT->set_pagetitle(rcmail_localize_foldername($IMAP->get_mailbox_name())); @@ -227,12 +231,12 @@ $zebra_class); $out .= sprintf("<td class=\"icon\">%s</td>\n", $message_icon ? sprintf($image_tag, $skin_path, $message_icon, '') : ''); - + // format each col foreach ($a_show_cols as $col) { if ($col=='from' || $col=='to') - $cont = Q(rcmail_address_string($header->$col, 3, $attrib['addicon']), 'show'); + $cont = Q(rcmail_address_string(rcube_imap::decode_mime_string($header->$col, $header->charset), 3, $attrib['addicon']), 'show'); else if ($col=='subject') { $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show'; @@ -285,6 +289,7 @@ $OUTPUT->set_env('attachmenticon', $skin_path . $attrib['attachmenticon']); $OUTPUT->set_env('messages', $a_js_message_arr); + $OUTPUT->set_env('coltypes', $a_show_cols); $OUTPUT->include_script('list.js'); @@ -320,7 +325,7 @@ foreach ($a_show_cols as $col) { if ($col=='from' || $col=='to') - $cont = Q(rcmail_address_string($header->$col, 3), 'show'); + $cont = Q(rcmail_address_string(rcube_imap::decode_mime_string($header->$col, $header->charset), 3), 'show'); else if ($col=='subject') { $action = $mbox==$CONFIG['drafts_mbox'] ? 'compose' : 'show'; @@ -402,30 +407,43 @@ if (!$attrib['id']) $attrib['id'] = 'rcmquotadisplay'; + if(isset($attrib['display'])) + $_SESSION['quota_display'] = $attrib['display']; + $OUTPUT->add_gui_object('quotadisplay', $attrib['id']); // allow the following attributes to be added to the <span> tag - $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); + $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'display')); $out = '<span' . $attrib_str . '>'; - $out .= rcmail_quota_content($attrib['display']); + $out .= rcmail_quota_content(); $out .= '</span>'; return $out; } -function rcmail_quota_content($display) +function rcmail_quota_content($quota=NULL) { global $IMAP, $COMM_PATH; - if (!$IMAP->get_capability('QUOTA')) - $quota_text = rcube_label('unknown'); - else if ($quota = $IMAP->get_quota()) + $display = isset($_SESSION['quota_display']) ? $_SESSION['quota_display'] : ''; + + if (is_array($quota) && !empty($quota['used']) && !empty($quota['total'])) { - $quota_text = sprintf("%s / %s (%.0f%%)", - show_bytes($quota["used"] * 1024), - show_bytes($quota["total"] * 1024), - $quota["percent"]); + if (!isset($quota['percent'])) + $quota['percent'] = $quota['used'] / $quota['total']; + } + elseif (!$IMAP->get_capability('QUOTA')) + return rcube_label('unknown'); + else + $quota = $IMAP->get_quota(); + + if ($quota) + { + $quota_text = sprintf('%s / %s (%.0f%%)', + show_bytes($quota['used'] * 1024), + show_bytes($quota['total'] * 1024), + $quota['percent']); // show quota as image (by Brett Patterson) if ($display == 'image' && function_exists('imagegif')) @@ -473,6 +491,127 @@ 'count' => $max))); return Q($out); + } + + +/* Stolen from Squirrelmail */ +function sq_deent(&$attvalue, $regex, $hex=false) + { + $ret_match = false; + preg_match_all($regex, $attvalue, $matches); + if (is_array($matches) && sizeof($matches[0]) > 0) + { + $repl = Array(); + for ($i = 0; $i < sizeof($matches[0]); $i++) + { + $numval = $matches[1][$i]; + if ($hex) + $numval = hexdec($numval); + $repl{$matches[0][$i]} = chr($numval); + } + $attvalue = strtr($attvalue, $repl); + return true; + } + else + return false; + } + + +/* Stolen verbatim from Squirrelmail */ +function sq_defang(&$attvalue) + { + /* Skip this if there aren't ampersands or backslashes. */ + if ((strpos($attvalue, '&') === false) && + (strpos($attvalue, '\\') === false)) + return; + $m = false; + do + { + $m = false; + $m = $m || sq_deent($attvalue, '/\�*(\d+);*/s'); + $m = $m || sq_deent($attvalue, '/\�*((\d|[a-f])+);*/si', true); + $m = $m || sq_deent($attvalue, '/\\\\(\d+)/s', true); + } while ($m == true); + $attvalue = stripslashes($attvalue); + } + + +function rcmail_html_filter($html) + { + preg_match_all('/<\/?\w+((\s+\w+(\s*=\s*(?:".*?"|\'.*?\'|[^\'">\s]+))?)+\s*|\s*)\/?>/', $html, $tags); + + /* From Squirrelmail: Translate all dangerous Unicode or Shift_JIS characters which are accepted by + * IE as regular characters. */ + $replace = array(array('ʟ', 'ʟ', /* L UNICODE IPA Extension */ + 'ʀ', 'ʀ', /* R UNICODE IPA Extension */ + 'ɴ', 'ɴ', /* N UNICODE IPA Extension */ + 'E', 'E', /* Unicode FULLWIDTH LATIN CAPITAL LETTER E */ + 'e', 'e', /* Unicode FULLWIDTH LATIN SMALL LETTER E */ + 'X', 'X', /* Unicode FULLWIDTH LATIN CAPITAL LETTER X */ + 'x', 'x', /* Unicode FULLWIDTH LATIN SMALL LETTER X */ + 'P', 'P', /* Unicode FULLWIDTH LATIN CAPITAL LETTER P */ + 'p', 'p', /* Unicode FULLWIDTH LATIN SMALL LETTER P */ + 'R', 'R', /* Unicode FULLWIDTH LATIN CAPITAL LETTER R */ + 'r', 'r', /* Unicode FULLWIDTH LATIN SMALL LETTER R */ + 'S', 'S', /* Unicode FULLWIDTH LATIN CAPITAL LETTER S */ + 's', 's', /* Unicode FULLWIDTH LATIN SMALL LETTER S */ + 'I', 'I', /* Unicode FULLWIDTH LATIN CAPITAL LETTER I */ + 'i', 'i', /* Unicode FULLWIDTH LATIN SMALL LETTER I */ + 'O', 'O', /* Unicode FULLWIDTH LATIN CAPITAL LETTER O */ + 'o', 'o', /* Unicode FULLWIDTH LATIN SMALL LETTER O */ + 'N', 'N', /* Unicode FULLWIDTH LATIN CAPITAL LETTER N */ + 'n', 'n', /* Unicode FULLWIDTH LATIN SMALL LETTER N */ + 'L', 'L', /* Unicode FULLWIDTH LATIN CAPITAL LETTER L */ + 'l', 'l', /* Unicode FULLWIDTH LATIN SMALL LETTER L */ + 'U', 'U', /* Unicode FULLWIDTH LATIN CAPITAL LETTER U */ + 'u', 'u', /* Unicode FULLWIDTH LATIN SMALL LETTER U */ + 'ⁿ', 'ⁿ' , /* Unicode SUPERSCRIPT LATIN SMALL LETTER N */ + "\xEF\xBC\xA5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER E */ + /* in unicode this is some Chinese char range */ + "\xEF\xBD\x85", /* Shift JIS FULLWIDTH LATIN SMALL LETTER E */ + "\xEF\xBC\xB8", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER X */ + "\xEF\xBD\x98", /* Shift JIS FULLWIDTH LATIN SMALL LETTER X */ + "\xEF\xBC\xB0", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER P */ + "\xEF\xBD\x90", /* Shift JIS FULLWIDTH LATIN SMALL LETTER P */ + "\xEF\xBC\xB2", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER R */ + "\xEF\xBD\x92", /* Shift JIS FULLWIDTH LATIN SMALL LETTER R */ + "\xEF\xBC\xB3", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER S */ + "\xEF\xBD\x93", /* Shift JIS FULLWIDTH LATIN SMALL LETTER S */ + "\xEF\xBC\xA9", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER I */ + "\xEF\xBD\x89", /* Shift JIS FULLWIDTH LATIN SMALL LETTER I */ + "\xEF\xBC\xAF", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER O */ + "\xEF\xBD\x8F", /* Shift JIS FULLWIDTH LATIN SMALL LETTER O */ + "\xEF\xBC\xAE", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER N */ + "\xEF\xBD\x8E", /* Shift JIS FULLWIDTH LATIN SMALL LETTER N */ + "\xEF\xBC\xAC", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER L */ + "\xEF\xBD\x8C", /* Shift JIS FULLWIDTH LATIN SMALL LETTER L */ + "\xEF\xBC\xB5", /* Shift JIS FULLWIDTH LATIN CAPITAL LETTER U */ + "\xEF\xBD\x95", /* Shift JIS FULLWIDTH LATIN SMALL LETTER U */ + "\xE2\x81\xBF", /* Shift JIS FULLWIDTH SUPERSCRIPT N */ + "\xCA\x9F", /* L UNICODE IPA Extension */ + "\xCA\x80", /* R UNICODE IPA Extension */ + "\xC9\xB4"), /* N UNICODE IPA Extension */ + array('l', 'l', 'r', 'r', 'n', 'n', 'E', 'E', 'e', 'e', 'X', 'X', 'x', 'x', + 'P', 'P', 'p', 'p', 'R', 'R', 'r', 'r', 'S', 'S', 's', 's', 'I', 'I', + 'i', 'i', 'O', 'O', 'o', 'o', 'N', 'N', 'n', 'n', 'L', 'L', 'l', 'l', + 'U', 'U', 'u', 'u', 'n', 'n', 'E', 'e', 'X', 'x', 'P', 'p', 'R', 'r', + 'S', 's', 'I', 'i', 'O', 'o', 'N', 'n', 'L', 'l', 'U', 'u', 'n', 'l', 'r', 'n')); + if ((count($tags)>3) && (count($tags[3])>0)) + foreach ($tags[3] as $nr=>$value) + { + /* Remove comments */ + $newvalue = preg_replace('/(\/\*.*\*\/)/','$2',$value); + /* Translate dangerous characters */ + $newvalue = str_replace($replace[0], $replace[1], $newvalue); + sq_defang($newvalue); + /* Rename dangerous CSS */ + $newvalue = preg_replace('/expression/i', 'idiocy', $newvalue); + $newvalue = preg_replace('/url/i', 'idiocy', $newvalue); + $newattrs = preg_replace('/'.preg_quote($value, '/').'$/', $newvalue, $tags[1][$nr]); + $newtag = preg_replace('/'.preg_quote($tags[1][$nr], '/').'/', $newattrs, $tags[0][$nr]); + $html = preg_replace('/'.preg_quote($tags[0][$nr], '/').'/', $newtag, $html); + } + return $html; } @@ -527,7 +666,7 @@ $body = preg_replace($remote_patterns, $remote_replaces, $body); } - return Q($body, 'show', FALSE); + return Q(rcmail_html_filter($body), 'show', FALSE); } // text/enriched @@ -552,8 +691,8 @@ $convert_patterns[] = '/([a-z0-9][a-z0-9\-\.\+\_]*@[a-z0-9]([a-z0-9\-][.]?)*[a-z0-9]\\.[a-z]{2,5})/ie'; $convert_replaces[] = "rcmail_str_replacement('<a href=\"mailto:\\1\" onclick=\"return ".JS_OBJECT_NAME.".command(\'compose\',\'\\1\',this)\">\\1</a>', \$replace_strings)"; - if ($part->ctype_parameters['format'] != 'flowed') - $body = wordwrap(trim($body), 80); +// if ($part->ctype_parameters['format'] != 'flowed') +// $body = wordwrap(trim($body), 80); $body = preg_replace($convert_patterns, $convert_replaces, $body); @@ -568,10 +707,10 @@ $quotation = ''; $q = 0; - if (preg_match('/^(>+\s*)/', $line, $regs)) + if (preg_match('/^(>+\s*)+/', $line, $regs)) { - $q = strlen(preg_replace('/\s/', '', $regs[1])); - $line = substr($line, strlen($regs[1])); + $q = strlen(preg_replace('/\s/', '', $regs[0])); + $line = substr($line, strlen($regs[0])); if ($q > $quote_level) $quotation = str_repeat('<blockquote>', $q - $quote_level); @@ -633,7 +772,7 @@ $structure->type = 'content'; $a_return_parts[] = &$structure; } - + // message contains alternative parts else if ($message_ctype_primary=='multipart' && $message_ctype_secondary=='alternative' && is_array($structure->parts)) { @@ -725,7 +864,7 @@ // part text/[plain|html] OR message/delivery-status else if (($primary_type=='text' && ($secondary_type=='plain' || $secondary_type=='html') && $mail_part->disposition!='attachment') || - ($primary_type=='message' && $secondary_type=='delivery-status')) + ($primary_type=='message' && ($secondary_type=='delivery-status' || $secondary_type=='disposition-notification'))) { $mail_part->type = 'content'; $a_return_parts[] = $mail_part; @@ -739,6 +878,10 @@ $a_return_parts = array_merge($a_return_parts, $parts); $a_attachments = array_merge($a_attachments, $attachmnts); } + + // ignore "virtual" protocol parts + else if ($primary_type=='protocol') + continue; // part is file/attachment else if ($mail_part->disposition=='attachment' || $mail_part->disposition=='inline' || $mail_part->headers['content-id'] || @@ -758,7 +901,7 @@ else { if (!$mail_part->filename) - $mail_part->filename = 'file_'.$mail_part->mime_id; + $mail_part->filename = 'Part '.$mail_part->mime_id; $a_attachments[] = $mail_part; } } @@ -827,7 +970,7 @@ continue; if ($hkey=='date' && !empty($headers[$hkey])) - $header_value = format_date(strtotime($headers[$hkey])); + $header_value = format_date($headers[$hkey]); else if (in_array($hkey, array('from', 'to', 'cc', 'bcc', 'reply-to'))) $header_value = Q(rcmail_address_string($headers[$hkey], NULL, $attrib['addicon']), 'show'); else @@ -856,7 +999,7 @@ if (!$attrib['id']) $attrib['id'] = 'rcmailMsgBody'; - $safe_mode = intval($_GET['_safe']); + $safe_mode = $MESSAGE['is_safe'] || intval($_GET['_safe']); $attrib_str = create_attrib_string($attrib, array('style', 'class', 'id')); $out = '<div '. $attrib_str . ">\n"; @@ -979,7 +1122,7 @@ while ($body != $prev_body) { $prev_body = $body; - $body = preg_replace('/(<[^!][^>]*\s)(on[^=>]+)=([^>]+>)/im', '$1__removed=$3', $body); + $body = preg_replace('/(<[^!][^>]*\s)on(?:load|unload|click|dblclick|mousedown|mouseup|mouseover|mousemove|mouseout|focus|blur|keypress|keydown|keyup|submit|reset|select|change)=([^>]+>)/im', '$1__removed=$2', $body); $body = preg_replace('/(<[^!][^>]*\shref=["\']?)(javascript:)([^>]*?>)/im', '$1null:$3', $body); } @@ -996,7 +1139,8 @@ // add comments arround html and other tags $out = preg_replace(array( - '/(<!DOCTYPE.+)/i', + '/(<!DOCTYPE[^>]*>)/i', + '/(<\?xml[^>]*>)/i', '/(<\/?html[^>]*>)/i', '/(<\/?head[^>]*>)/i', '/(<title[^>]*>.*<\/title>)/Ui', @@ -1133,7 +1277,7 @@ function rcmail_address_string($input, $max=NULL, $addicon=NULL) { global $IMAP, $PRINT_MODE, $CONFIG, $OUTPUT, $EMAIL_ADDRESS_PATTERN; - + $a_parts = $IMAP->decode_address_list($input); if (!sizeof($a_parts)) @@ -1147,7 +1291,7 @@ { $j++; if ($PRINT_MODE) - $out .= sprintf('%s <%s>', Q($part['name']), $part['mailto']); + $out .= sprintf('%s <%s>', Q(rcube_charset_convert($part['name'])), $part['mailto']); else if (preg_match($EMAIL_ADDRESS_PATTERN, $part['mailto'])) { $out .= sprintf('<a href="mailto:%s" onclick="return %s.command(\'compose\',\'%s\',this)" class="rcmContactAddress" title="%s">%s</a>', @@ -1195,12 +1339,11 @@ if (!is_array($MESSAGE) || !is_array($MESSAGE['parts']) || !($_GET['_uid'] && $_GET['_part']) || !$MESSAGE['parts'][$part]) return ''; - $part = &$MESSAGE['parts'][$part]; - + $part = $MESSAGE['parts'][$part]; $attrib_str = create_attrib_string($attrib, array('id', 'class', 'style', 'cellspacing', 'cellpadding', 'border', 'summary')); $out = '<table '. $attrib_str . ">\n"; - if ($filename) + if ($part->filename) { $out .= sprintf('<tr><td class="title">%s</td><td>%s</td><td>[<a href="./?%s">%s</a>]</tr>'."\n", Q(rcube_label('filename')), @@ -1250,6 +1393,143 @@ unset($_SESSION['compose']); } + + +/** + * Send the given message compose object using the configured method + */ +function rcmail_deliver_message(&$message, $from, $mailto) +{ + global $CONFIG; + + $headers = $message->headers(); + $msg_body = $message->get(); + + // send thru SMTP server using custom SMTP library + if ($CONFIG['smtp_server']) + { + // generate list of recipients + $a_recipients = array($mailto); + + if (strlen($headers['Cc'])) + $a_recipients[] = $headers['Cc']; + if (strlen($headers['Bcc'])) + $a_recipients[] = $headers['Bcc']; + + // clean Bcc from header for recipients + $send_headers = $headers; + unset($send_headers['Bcc']); + // here too, it because txtHeaders() below use $message->_headers not only $send_headers + unset($message->_headers['Bcc']); + + // send message + $smtp_response = array(); + $sent = smtp_mail($from, $a_recipients, ($foo = $message->txtHeaders($send_headers, true)), $msg_body, $smtp_response); + + // log error + if (!$sent) + raise_error(array('code' => 800, 'type' => 'smtp', 'line' => __LINE__, 'file' => __FILE__, + 'message' => "SMTP error: ".join("\n", $smtp_response)), TRUE, FALSE); + } + + // send mail using PHP's mail() function + else + { + // unset some headers because they will be added by the mail() function + $headers_enc = $message->headers($headers); + $headers_php = $message->_headers; + unset($headers_php['To'], $headers_php['Subject']); + + // reset stored headers and overwrite + $message->_headers = array(); + $header_str = $message->txtHeaders($headers_php); + + if (ini_get('safe_mode')) + $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str); + else + $sent = mail($headers_enc['To'], $headers_enc['Subject'], $msg_body, $header_str, "-f$from"); + } + + if ($sent) // remove MDN headers after sending + unset($headers['Return-Receipt-To'], $headers['Disposition-Notification-To']); + + $message->_headers = array(); + $message->headers($headers); + + return $sent; +} + + +function rcmail_send_mdn($uid) +{ + global $CONFIG, $USER, $IMAP; + + $message = array('UID' => $uid); + $message['headers'] = $IMAP->get_headers($message['UID']); + $message['subject'] = rcube_imap::decode_mime_string($message['headers']->subject, $message['headers']->charset); + + if ($message['headers']->mdn_to && !$message['headers']->mdn_sent) + { + $identity = $USER->get_identity(); + $sender = format_email_recipient($identity['email'], $identity['name']); + $recipient = array_shift($IMAP->decode_address_list($message['headers']->mdn_to)); + $mailto = $recipient['mailto']; + + $compose = new rcube_mail_mime(rcmail_header_delm()); + $compose->setParam(array( + 'text_encoding' => 'quoted-printable', + 'html_encoding' => 'quoted-printable', + 'head_encoding' => 'quoted-printable', + 'head_charset' => RCMAIL_CHARSET, + 'html_charset' => RCMAIL_CHARSET, + 'text_charset' => RCMAIL_CHARSET, + )); + + // compose headers array + $headers = array( + 'Date' => date('r'), + 'From' => $sender, + 'To' => $message['headers']->mdn_to, + 'Subject' => rcube_label('receiptread') . ': ' . $message['subject'], + 'Message-ID' => sprintf('<%s@%s>', md5(uniqid('rcmail'.rand(),true)), rcmail_mail_domain($_SESSION['imap_host'])), + 'X-Sender' => $identity['email'], + 'Content-Type' => 'multipart/report; report-type=disposition-notification', + ); + + if (!empty($CONFIG['useragent'])) + $headers['User-Agent'] = $CONFIG['useragent']; + + $body = rcube_label("yourmessage") . "\r\n\r\n" . + "\t" . rcube_label("to") . ': ' . rcube_imap::decode_mime_string($message['headers']->to, $message['headers']->charset) . "\r\n" . + "\t" . rcube_label("subject") . ': ' . $message['subject'] . "\r\n" . + "\t" . rcube_label("sent") . ': ' . format_date($message['headers']->date, $CONFIG['date_long']) . "\r\n" . + "\r\n" . rcube_label("receiptnote") . "\r\n"; + + $ua = !empty($CONFIG['useragent']) ? $CONFIG['useragent'] : "RoundCube Webmail (Version ".RCMAIL_VERSION.")"; + $report = "Reporting-UA: $ua\r\n"; + + if ($message['headers']->to) + $report .= "Original-Recipient: {$message['headers']->to}\r\n"; + + $report .= "Final-Recipient: rfc822; {$identity['email']}\r\n" . + "Original-Message-ID: {$message['headers']->messageID}\r\n" . + "Disposition: manual-action/MDN-sent-manually; displayed\r\n"; + + $compose->headers($headers, true); + $compose->setTXTBody($body); + $compose->addAttachment($report, 'message/disposition-notification', 'MDNPart2.txt', false, '7bit', 'inline'); + + $sent = rcmail_deliver_message($compose, $identity['email'], $mailto); + + if ($sent) + { + $IMAP->set_flag($message['UID'], 'MDNSENT'); + return true; + } + } + + return false; +} // register UI objects @@ -1263,7 +1543,7 @@ 'messagecontentframe' => 'rcmail_messagecontent_frame', 'messagepartframe' => 'rcmail_message_part_frame', 'messagepartcontrols' => 'rcmail_message_part_controls', - 'searchform' => 'rcmail_search_form' + 'searchform' => array($OUTPUT, 'search_form'), )); ?> -- Gitblit v1.9.1