summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG1
-rw-r--r--plugins/enigma/lib/enigma_ui.php3
-rw-r--r--program/include/rcmail.php4
-rw-r--r--program/include/rcube_imap.php2
-rw-r--r--program/include/rcube_ldap.php24
-rw-r--r--program/include/rcube_session.php13
-rw-r--r--program/steps/mail/compose.inc186
-rw-r--r--program/steps/mail/func.inc1
-rw-r--r--program/steps/mail/search.inc2
-rw-r--r--program/steps/mail/sendmail.inc44
-rw-r--r--tests/maildecode.php46
11 files changed, 180 insertions, 146 deletions
diff --git a/CHANGELOG b/CHANGELOG
index f6f8b0253..cfe92646c 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Improved handling of some malformed values encoded with quoted-printable (#1488232)
- Add possibility to do LDAP bind before searching for bind DN
- Fix handling of empty <U> tags in HTML messages (#1488225)
- Add content filter for embedded attachments to protect from XSS on IE (#1487895)
diff --git a/plugins/enigma/lib/enigma_ui.php b/plugins/enigma/lib/enigma_ui.php
index b9ccff53d..5901b58d9 100644
--- a/plugins/enigma/lib/enigma_ui.php
+++ b/plugins/enigma/lib/enigma_ui.php
@@ -412,9 +412,6 @@ class enigma_ui
private function compose_ui()
{
- if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != get_input_value('_id', RCUBE_INPUT_GET))
- return;
-
// Options menu button
// @TODO: make this work with non-default skins
$this->enigma->add_button(array(
diff --git a/program/include/rcmail.php b/program/include/rcmail.php
index e06594fcd..6f0ba2ce9 100644
--- a/program/include/rcmail.php
+++ b/program/include/rcmail.php
@@ -453,8 +453,7 @@ class rcmail
}
// add to the 'books' array for shutdown function
- if (!isset($this->address_books[$id]))
- $this->address_books[$id] = $contacts;
+ $this->address_books[$id] = $contacts;
return $contacts;
}
@@ -1228,7 +1227,6 @@ class rcmail
// before closing the database connection, write session data
if ($_SERVER['REMOTE_ADDR'] && is_object($this->session)) {
- $this->session->cleanup();
session_write_close();
}
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index a0a5f8189..1c5dd2e3f 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -4162,7 +4162,7 @@ class rcube_imap
$input = preg_replace("/\?=\s+=\?/", '?==?', $input);
// encoded-word regexp
- $re = '/=\?([^?]+)\?([BbQq])\?([^?\n]*)\?=/';
+ $re = '/=\?([^?]+)\?([BbQq])\?([^\n]*?)\?=/';
// Find all RFC2047's encoded words
if (preg_match_all($re, $input, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER)) {
diff --git a/program/include/rcube_ldap.php b/program/include/rcube_ldap.php
index 03347512c..3ec0e5f3b 100644
--- a/program/include/rcube_ldap.php
+++ b/program/include/rcube_ldap.php
@@ -655,14 +655,11 @@ class rcube_ldap extends rcube_addressbook
$attrib = $count ? array('dn') : array_values($this->fieldmap);
if ($result = @$func($this->conn, $m[1], $filter,
- $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']))
- {
+ $attrib, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit'])
+ ) {
$this->_debug("S: ".ldap_count_entries($this->conn, $result)." record(s) for ".$m[1]);
- if ($err = ldap_errno($this->conn))
- $this->_debug("S: Error: " .ldap_err2str($err));
}
- else
- {
+ else {
$this->_debug("S: ".ldap_error($this->conn));
return $group_members;
}
@@ -1227,15 +1224,14 @@ class rcube_ldap extends rcube_addressbook
// only fetch dn for count (should keep the payload low)
$attrs = $count ? array('dn') : array_values($this->fieldmap);
if ($this->ldap_result = @$function($this->conn, $this->base_dn, $filter,
- $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit']))
- {
- $this->_debug("S: ".ldap_count_entries($this->conn, $this->ldap_result)." record(s)");
- if ($err = ldap_errno($this->conn))
- $this->_debug("S: Error: " .ldap_err2str($err));
- return $count ? ldap_count_entries($this->conn, $this->ldap_result) : true;
+ $attrs, 0, (int)$this->prop['sizelimit'], (int)$this->prop['timelimit'])
+ ) {
+ $entries_count = ldap_count_entries($this->conn, $this->ldap_result);
+ $this->_debug("S: $count_entries record(s)");
+
+ return $count ? $count_entries : true;
}
- else
- {
+ else {
$this->_debug("S: ".ldap_error($this->conn));
}
}
diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php
index 582b27efa..bd0ce60e4 100644
--- a/program/include/rcube_session.php
+++ b/program/include/rcube_session.php
@@ -336,19 +336,6 @@ class rcube_session
/**
- * Cleanup session data before saving
- */
- public function cleanup()
- {
- // current compose information is stored in $_SESSION['compose'], move it to $_SESSION['compose_data_<ID>']
- if ($compose_id = $_SESSION['compose']['id']) {
- $_SESSION['compose_data_'.$compose_id] = $_SESSION['compose'];
- $this->remove('compose');
- }
- }
-
-
- /**
* Register additional garbage collector functions
*
* @param mixed Callback function
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 9df25f031..d98452afc 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -25,23 +25,26 @@ define('RCUBE_COMPOSE_FORWARD', 0x0107);
define('RCUBE_COMPOSE_DRAFT', 0x0108);
define('RCUBE_COMPOSE_EDIT', 0x0109);
-$MESSAGE_FORM = NULL;
-$MESSAGE = NULL;
+$MESSAGE_FORM = null;
+$MESSAGE = null;
+$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET);
+$COMPOSE = null;
-$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET);
-$_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+if ($COMPOSE_ID && $_SESSION['compose_data_'.$COMPOSE_ID])
+ $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
// give replicated session storage some time to synchronize
$retries = 0;
-while ($COMPOSE_ID && !is_array($_SESSION['compose']) && $RCMAIL->db->is_replicated() && $retries++ < 5) {
+while ($COMPOSE_ID && !is_array($COMPOSE) && $RCMAIL->db->is_replicated() && $retries++ < 5) {
usleep(500000);
$RCMAIL->session->reload();
- $_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+ 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($_SESSION['compose']))
+if (!is_array($COMPOSE))
{
// Infinite redirect prevention in case of broken session (#1487028)
if ($COMPOSE_ID)
@@ -49,31 +52,33 @@ if (!is_array($_SESSION['compose']))
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, true);
- $_SESSION['compose'] = array(
- 'id' => uniqid(mt_rand()),
- 'param' => request2param(RCUBE_INPUT_GET),
+ $COMPOSE_ID = uniqid(mt_rand());
+ $_SESSION['compose_data_'.$COMPOSE_ID] = array(
+ 'id' => $COMPOSE_ID,
+ 'param' => request2param(RCUBE_INPUT_GET),
'mailbox' => $IMAP->get_mailbox_name(),
);
+ $COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
// process values like "mailto:foo@bar.com?subject=new+message&cc=another"
- if ($_SESSION['compose']['param']['to']) {
+ if ($COMPOSE['param']['to']) {
// #1486037: remove "mailto:" prefix
- $_SESSION['compose']['param']['to'] = preg_replace('/^mailto:/i', '', $_SESSION['compose']['param']['to']);
- $mailto = explode('?', $_SESSION['compose']['param']['to']);
+ $COMPOSE['param']['to'] = preg_replace('/^mailto:/i', '', $COMPOSE['param']['to']);
+ $mailto = explode('?', $COMPOSE['param']['to']);
if (count($mailto) > 1) {
- $_SESSION['compose']['param']['to'] = $mailto[0];
+ $COMPOSE['param']['to'] = $mailto[0];
parse_str($mailto[1], $query);
foreach ($query as $f => $val)
- $_SESSION['compose']['param'][$f] = $val;
+ $COMPOSE['param'][$f] = $val;
}
}
// select folder where to save the sent message
- $_SESSION['compose']['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
+ $COMPOSE['param']['sent_mbox'] = $RCMAIL->config->get('sent_mbox');
// pipe compose parameters thru plugins
- $plugin = $RCMAIL->plugins->exec_hook('message_compose', $_SESSION['compose']);
- $_SESSION['compose']['param'] = array_merge($_SESSION['compose']['param'], $plugin['param']);
+ $plugin = $RCMAIL->plugins->exec_hook('message_compose', $COMPOSE);
+ $COMPOSE['param'] = array_merge($COMPOSE['param'], $plugin['param']);
// add attachments listed by message_compose hook
if (is_array($plugin['attachments'])) {
@@ -100,18 +105,18 @@ if (!is_array($_SESSION['compose']))
if ($attachment['status'] && !$attachment['abort']) {
unset($attachment['data'], $attachment['status'], $attachment['abort']);
- $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ $COMPOSE['attachments'][$attachment['id']] = $attachment;
}
}
}
// check if folder for saving sent messages exists and is subscribed (#1486802)
- if ($sent_folder = $_SESSION['compose']['param']['sent_mbox']) {
+ 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' => $_SESSION['compose']['id']));
+ $OUTPUT->redirect(array('_action' => 'compose', '_id' => $COMPOSE['id']));
}
@@ -121,7 +126,7 @@ $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubj
'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'uploadingmany',
'fileuploaderror');
-$OUTPUT->set_env('compose_id', $COMPOSE_ID);
+$OUTPUT->set_env('compose_id', $COMPOSE['id']);
// add config parameters to client script
if (!empty($CONFIG['drafts_mbox'])) {
@@ -135,15 +140,15 @@ $OUTPUT->set_env('top_posting', $RCMAIL->config->get('top_posting', false));
$OUTPUT->set_env('recipients_separator', trim($RCMAIL->config->get('recipients_separator', ',')));
// get reference message and set compose mode
-if ($msg_uid = $_SESSION['compose']['param']['draft_uid']) {
+if ($msg_uid = $COMPOSE['param']['draft_uid']) {
$RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']);
$compose_mode = RCUBE_COMPOSE_DRAFT;
}
-else if ($msg_uid = $_SESSION['compose']['param']['reply_uid'])
+else if ($msg_uid = $COMPOSE['param']['reply_uid'])
$compose_mode = RCUBE_COMPOSE_REPLY;
-else if ($msg_uid = $_SESSION['compose']['param']['forward_uid'])
+else if ($msg_uid = $COMPOSE['param']['forward_uid'])
$compose_mode = RCUBE_COMPOSE_FORWARD;
-else if ($msg_uid = $_SESSION['compose']['param']['uid'])
+else if ($msg_uid = $COMPOSE['param']['uid'])
$compose_mode = RCUBE_COMPOSE_EDIT;
$config_show_sig = $RCMAIL->config->get('show_sig', 1);
@@ -175,20 +180,20 @@ if (!empty($msg_uid))
if ($compose_mode == RCUBE_COMPOSE_REPLY)
{
- $_SESSION['compose']['reply_uid'] = $msg_uid;
- $_SESSION['compose']['reply_msgid'] = $MESSAGE->headers->messageID;
- $_SESSION['compose']['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
+ $COMPOSE['reply_uid'] = $msg_uid;
+ $COMPOSE['reply_msgid'] = $MESSAGE->headers->messageID;
+ $COMPOSE['references'] = trim($MESSAGE->headers->references . " " . $MESSAGE->headers->messageID);
- if (!empty($_SESSION['compose']['param']['all']))
- $MESSAGE->reply_all = $_SESSION['compose']['param']['all'];
+ if (!empty($COMPOSE['param']['all']))
+ $MESSAGE->reply_all = $COMPOSE['param']['all'];
$OUTPUT->set_env('compose_mode', 'reply');
// Save the sent message in the same folder of the message being replied to
- if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $_SESSION['compose']['mailbox'])
+ if ($RCMAIL->config->get('reply_same_folder') && ($sent_folder = $COMPOSE['mailbox'])
&& rcmail_check_sent_folder($sent_folder, false)
) {
- $_SESSION['compose']['param']['sent_mbox'] = $sent_folder;
+ $COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
else if ($compose_mode == RCUBE_COMPOSE_DRAFT)
@@ -199,31 +204,31 @@ if (!empty($msg_uid))
$info = rcmail_draftinfo_decode($MESSAGE->headers->others['x-draft-info']);
if ($info['type'] == 'reply')
- $_SESSION['compose']['reply_uid'] = $info['uid'];
+ $COMPOSE['reply_uid'] = $info['uid'];
else if ($info['type'] == 'forward')
- $_SESSION['compose']['forward_uid'] = $info['uid'];
+ $COMPOSE['forward_uid'] = $info['uid'];
- $_SESSION['compose']['mailbox'] = $info['folder'];
+ $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)
) {
- $_SESSION['compose']['param']['sent_mbox'] = $sent_folder;
+ $COMPOSE['param']['sent_mbox'] = $sent_folder;
}
}
if ($MESSAGE->headers->in_reply_to)
- $_SESSION['compose']['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
+ $COMPOSE['reply_msgid'] = '<'.$MESSAGE->headers->in_reply_to.'>';
- $_SESSION['compose']['references'] = $MESSAGE->headers->references;
+ $COMPOSE['references'] = $MESSAGE->headers->references;
}
else if ($compose_mode == RCUBE_COMPOSE_FORWARD)
{
- $_SESSION['compose']['forward_uid'] = $msg_uid;
+ $COMPOSE['forward_uid'] = $msg_uid;
$OUTPUT->set_env('compose_mode', 'forward');
- if (!empty($_SESSION['compose']['param']['attachment']))
+ if (!empty($COMPOSE['param']['attachment']))
$MESSAGE->forward_attachment = true;
}
}
@@ -247,8 +252,8 @@ if (count($MESSAGE->identities))
if (!empty($_POST['_from'])) {
$MESSAGE->compose['from'] = get_input_value('_from', RCUBE_INPUT_POST);
}
-else if (!empty($_SESSION['compose']['param']['from'])) {
- $MESSAGE->compose['from'] = $_SESSION['compose']['param']['from'];
+else if (!empty($COMPOSE['param']['from'])) {
+ $MESSAGE->compose['from'] = $COMPOSE['param']['from'];
}
else if (count($MESSAGE->identities)) {
$a_recipients = array();
@@ -340,17 +345,17 @@ foreach ($parts as $header) {
$decode_header = true;
// we have a set of recipients stored is session
- if ($header == 'to' && ($mailto_id = $_SESSION['compose']['param']['mailto'])
- && $_SESSION['mailto'][$mailto_id]
+ if ($header == 'to' && ($mailto_id = $COMPOSE['param']['mailto'])
+ && $COMPOSE[$mailto_id]
) {
- $fvalue = urldecode($_SESSION['mailto'][$mailto_id]);
+ $fvalue = urldecode($COMPOSE[$mailto_id]);
$decode_header = false;
}
else if (!empty($_POST['_'.$header])) {
$fvalue = get_input_value('_'.$header, RCUBE_INPUT_POST, TRUE);
}
- else if (!empty($_SESSION['compose']['param'][$header])) {
- $fvalue = $_SESSION['compose']['param'][$header];
+ 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
@@ -530,7 +535,7 @@ function rcmail_compose_header_from($attrib)
$select_from->add(format_email_recipient($sql_arr['email'], $sql_arr['name']), $identity_id);
// add signature to array
- if (!empty($sql_arr['signature']) && empty($_SESSION['compose']['param']['nosig']))
+ if (!empty($sql_arr['signature']) && empty($COMPOSE['param']['nosig']))
{
$a_signatures[$identity_id]['text'] = $sql_arr['signature'];
$a_signatures[$identity_id]['is_html'] = ($sql_arr['html_signature'] == 1) ? true : false;
@@ -584,22 +589,22 @@ function rcmail_compose_editor_mode()
function rcmail_prepare_message_body()
{
- global $RCMAIL, $MESSAGE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
+ global $RCMAIL, $MESSAGE, $COMPOSE, $compose_mode, $LINE_LENGTH, $HTML_MODE;
// use posted message body
if (!empty($_POST['_message'])) {
$body = get_input_value('_message', RCUBE_INPUT_POST, true);
$isHtml = (bool) get_input_value('_is_html', RCUBE_INPUT_POST);
}
- else if ($_SESSION['compose']['param']['body']) {
- $body = $_SESSION['compose']['param']['body'];
+ else if ($COMPOSE['param']['body']) {
+ $body = $COMPOSE['param']['body'];
$isHtml = false;
}
// forward as attachment
else if ($compose_mode == RCUBE_COMPOSE_FORWARD && $MESSAGE->forward_attachment) {
$isHtml = rcmail_compose_editor_mode();
$body = '';
- if (empty($_SESSION['compose']['attachments']))
+ if (empty($COMPOSE['attachments']))
rcmail_write_forward_attachment($MESSAGE);
}
// reply/edit/draft/forward
@@ -662,9 +667,9 @@ function rcmail_prepare_message_body()
// add blocked.gif attachment (#1486516)
if ($isHtml && preg_match('#<img src="\./program/blocked\.gif"#', $body)) {
if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) {
- $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ $COMPOSE['attachments'][$attachment['id']] = $attachment;
$body = preg_replace('#\./program/blocked\.gif#',
- $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'],
+ $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'],
$body);
}
}
@@ -848,10 +853,10 @@ function rcmail_create_reply_body($body, $bodyIsHtml)
function rcmail_create_forward_body($body, $bodyIsHtml)
{
- global $RCMAIL, $MESSAGE;
+ global $RCMAIL, $MESSAGE, $COMPOSE;
// add attachments
- if (!isset($_SESSION['compose']['forward_attachments']) && is_array($MESSAGE->mime_parts))
+ if (!isset($COMPOSE['forward_attachments']) && is_array($MESSAGE->mime_parts))
$cid_map = rcmail_write_compose_attachments($MESSAGE, $bodyIsHtml);
$date = format_date($MESSAGE->headers->date, $RCMAIL->config->get('date_long'));
@@ -910,13 +915,13 @@ function rcmail_create_forward_body($body, $bodyIsHtml)
function rcmail_create_draft_body($body, $bodyIsHtml)
{
- global $MESSAGE, $OUTPUT;
+ global $MESSAGE, $OUTPUT, $COMPOSE;
/**
* add attachments
* sizeof($MESSAGE->mime_parts can be 1 - e.g. attachment, but no text!
*/
- if (empty($_SESSION['compose']['forward_attachments'])
+ if (empty($COMPOSE['forward_attachments'])
&& is_array($MESSAGE->mime_parts)
&& count($MESSAGE->mime_parts) > 0)
{
@@ -954,7 +959,7 @@ function rcmail_remove_signature($body)
function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
{
- global $RCMAIL;
+ global $RCMAIL, $COMPOSE;
$cid_map = $messages = array();
foreach ((array)$message->mime_parts as $pid => $part)
@@ -976,9 +981,9 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
}
if (!$skip && ($attachment = rcmail_save_attachment($message, $pid))) {
- $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ $COMPOSE['attachments'][$attachment['id']] = $attachment;
if ($bodyIsHtml && ($part->content_id || $part->content_location)) {
- $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'];
+ $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
@@ -988,7 +993,7 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
}
}
- $_SESSION['compose']['forward_attachments'] = true;
+ $COMPOSE['forward_attachments'] = true;
return $cid_map;
}
@@ -996,14 +1001,14 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
function rcmail_write_inline_attachments(&$message)
{
- global $RCMAIL;
+ 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)) {
- $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
- $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'];
+ $COMPOSE['attachments'][$attachment['id']] = $attachment;
+ $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$COMPOSE['id'];
if ($part->content_id)
$cid_map['cid:'.$part->content_id] = $url;
else
@@ -1018,7 +1023,7 @@ function rcmail_write_inline_attachments(&$message)
// Creates an attachment from the forwarded message
function rcmail_write_forward_attachment(&$message)
{
- global $RCMAIL;
+ global $RCMAIL, $COMPOSE;
if (strlen($message->subject)) {
$name = mb_substr($message->subject, 0, 64) . '.eml';
@@ -1045,7 +1050,7 @@ function rcmail_write_forward_attachment(&$message)
}
$attachment = array(
- 'group' => $_SESSION['compose']['id'],
+ 'group' => $COMPOSE['id'],
'name' => $name,
'mimetype' => 'message/rfc822',
'data' => $data,
@@ -1057,7 +1062,7 @@ function rcmail_write_forward_attachment(&$message)
if ($attachment['status']) {
unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
- $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+ $COMPOSE['attachments'][$attachment['id']] = $attachment;
return true;
} else if ($path) {
@unlink($path);
@@ -1069,6 +1074,8 @@ function rcmail_write_forward_attachment(&$message)
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'));
@@ -1089,7 +1096,7 @@ function rcmail_save_attachment(&$message, $pid)
}
$attachment = array(
- 'group' => $_SESSION['compose']['id'],
+ 'group' => $COMPOSE['id'],
'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary,
'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
'content_id' => $part->content_id,
@@ -1112,11 +1119,13 @@ function rcmail_save_attachment(&$message, $pid)
function rcmail_save_image($path, $mimetype='')
{
+ global $COMPOSE;
+
// handle attachments in memory
$data = file_get_contents($path);
$attachment = array(
- 'group' => $_SESSION['compose']['id'],
+ 'group' => $COMPOSE['id'],
'name' => rcmail_basename($path),
'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name),
'data' => $data,
@@ -1145,11 +1154,11 @@ function rcmail_basename($filename)
function rcmail_compose_subject($attrib)
{
- global $MESSAGE, $compose_mode;
-
+ global $MESSAGE, $COMPOSE, $compose_mode;
+
list($form_start, $form_end) = get_form_tags($attrib);
unset($attrib['form']);
-
+
$attrib['name'] = '_subject';
$attrib['spellcheck'] = 'true';
$textfield = new html_inputfield($attrib);
@@ -1178,10 +1187,10 @@ function rcmail_compose_subject($attrib)
else if ($compose_mode == RCUBE_COMPOSE_DRAFT || $compose_mode == RCUBE_COMPOSE_EDIT) {
$subject = $MESSAGE->subject;
}
- else if (!empty($_SESSION['compose']['param']['subject'])) {
- $subject = $_SESSION['compose']['param']['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" : '';
@@ -1192,17 +1201,16 @@ function rcmail_compose_subject($attrib)
function rcmail_compose_attachment_list($attrib)
{
- global $OUTPUT, $CONFIG;
-
+ global $OUTPUT, $CONFIG, $COMPOSE;
+
// add ID if not given
if (!$attrib['id'])
$attrib['id'] = 'rcmAttachmentList';
-
+
$out = "\n";
$jslist = array();
- if (is_array($_SESSION['compose']['attachments']))
- {
+ if (is_array($COMPOSE['attachments'])) {
if ($attrib['deleteicon']) {
$button = html::img(array(
'src' => $CONFIG['skin_path'] . $attrib['deleteicon'],
@@ -1212,11 +1220,11 @@ function rcmail_compose_attachment_list($attrib)
else
$button = Q(rcube_label('delete'));
- foreach ($_SESSION['compose']['attachments'] as $id => $a_prop)
+ foreach ($COMPOSE['attachments'] as $id => $a_prop)
{
if (empty($a_prop))
continue;
-
+
$out .= html::tag('li', array('id' => 'rcmfile'.$id),
html::a(array(
'href' => "#delete",
@@ -1229,7 +1237,7 @@ function rcmail_compose_attachment_list($attrib)
}
if ($attrib['deleteicon'])
- $_SESSION['compose']['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
+ $COMPOSE['deleteicon'] = $CONFIG['skin_path'] . $attrib['deleteicon'];
if ($attrib['cancelicon'])
$OUTPUT->set_env('cancelicon', $CONFIG['skin_path'] . $attrib['cancelicon']);
if ($attrib['loadingicon'])
@@ -1397,13 +1405,15 @@ function rcmail_editor_selector($attrib)
function rcmail_store_target_selection($attrib)
{
+ global $COMPOSE;
+
$attrib['name'] = '_store_target';
$select = rcmail_mailbox_select(array_merge($attrib, array(
'noselection' => '- '.rcube_label('dontsave').' -',
'folder_filter' => 'mail',
'folder_rights' => 'w',
)));
- return $select->show($_SESSION['compose']['param']['sent_mbox'], $attrib);
+ return $select->show($COMPOSE['param']['sent_mbox'], $attrib);
}
@@ -1429,14 +1439,14 @@ function rcmail_check_sent_folder($folder, $create=false)
function get_form_tags($attrib)
{
- global $RCMAIL, $MESSAGE_FORM;
+ 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' => $_SESSION['compose']['id']));
+ $hiddenfields->add(array('name' => '_id', 'value' => $COMPOSE['id']));
$form_start = empty($attrib['form']) ? $RCMAIL->output->form_tag(array('name' => "form", 'method' => "post")) : '';
$form_start .= $hiddenfields->show();
diff --git a/program/steps/mail/func.inc b/program/steps/mail/func.inc
index c070dad3a..b0a1e95bd 100644
--- a/program/steps/mail/func.inc
+++ b/program/steps/mail/func.inc
@@ -1424,7 +1424,6 @@ function rcmail_compose_cleanup($id)
$rcmail = rcmail::get_instance();
$rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id));
$rcmail->session->remove('compose_data_'.$id);
- $rcmail->session->remove('compose');
}
diff --git a/program/steps/mail/search.inc b/program/steps/mail/search.inc
index 593eac427..49f31e0c1 100644
--- a/program/steps/mail/search.inc
+++ b/program/steps/mail/search.inc
@@ -107,7 +107,7 @@ $search_str = trim($search_str);
// execute IMAP search
if ($search_str)
- $result = $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
+ $IMAP->search($mbox, $search_str, $imap_charset, $_SESSION['sort_col']);
// Get the headers
$result_h = $IMAP->list_headers($mbox, 1, $_SESSION['sort_col'], $_SESSION['sort_order']);
diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc
index 0fdcd78cd..64deb73d8 100644
--- a/program/steps/mail/sendmail.inc
+++ b/program/steps/mail/sendmail.inc
@@ -27,11 +27,11 @@ $OUTPUT->framed = TRUE;
$savedraft = !empty($_POST['_draft']) ? true : false;
$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC);
-$_SESSION['compose'] = $_SESSION['compose_data_'.$COMPOSE_ID];
+$COMPOSE =& $_SESSION['compose_data_'.$COMPOSE_ID];
/****** checks ********/
-if (!isset($_SESSION['compose']['id'])) {
+if (!isset($COMPOSE['id'])) {
raise_error(array('code' => 500, 'type' => 'php',
'file' => __FILE__, 'line' => __LINE__,
'message' => "Invalid compose ID"), true, false);
@@ -340,20 +340,20 @@ if (!empty($headers['Reply-To'])) {
if (!empty($_POST['_followupto'])) {
$headers['Mail-Followup-To'] = rcmail_email_input_format(get_input_value('_followupto', RCUBE_INPUT_POST, TRUE, $message_charset));
}
-if (!empty($_SESSION['compose']['reply_msgid'])) {
- $headers['In-Reply-To'] = $_SESSION['compose']['reply_msgid'];
+if (!empty($COMPOSE['reply_msgid'])) {
+ $headers['In-Reply-To'] = $COMPOSE['reply_msgid'];
}
// remember reply/forward UIDs in special headers
-if (!empty($_SESSION['compose']['reply_uid']) && $savedraft) {
- $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $_SESSION['compose']['reply_uid']);
+if (!empty($COMPOSE['reply_uid']) && $savedraft) {
+ $headers['X-Draft-Info'] = array('type' => 'reply', 'uid' => $COMPOSE['reply_uid']);
}
-else if (!empty($_SESSION['compose']['forward_uid']) && $savedraft) {
- $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $_SESSION['compose']['forward_uid']);
+else if (!empty($COMPOSE['forward_uid']) && $savedraft) {
+ $headers['X-Draft-Info'] = array('type' => 'forward', 'uid' => $COMPOSE['forward_uid']);
}
-if (!empty($_SESSION['compose']['references'])) {
- $headers['References'] = $_SESSION['compose']['references'];
+if (!empty($COMPOSE['references'])) {
+ $headers['References'] = $COMPOSE['references'];
}
if (!empty($_POST['_priority'])) {
@@ -374,7 +374,7 @@ $headers['Message-ID'] = $message_id;
$headers['X-Sender'] = $from;
if (is_array($headers['X-Draft-Info'])) {
- $headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $_SESSION['compose']['mailbox']));
+ $headers['X-Draft-Info'] = rcmail_draftinfo_encode($headers['X-Draft-Info'] + array('folder' => $COMPOSE['mailbox']));
}
if (!empty($CONFIG['useragent'])) {
$headers['User-Agent'] = $CONFIG['useragent'];
@@ -414,12 +414,12 @@ if (!$savedraft) {
// Check spelling before send
if ($CONFIG['spellcheck_before_send'] && $CONFIG['enable_spellcheck']
- && empty($_SESSION['compose']['spell_checked']) && !empty($message_body)
+ && empty($COMPOSE['spell_checked']) && !empty($message_body)
) {
$spellchecker = new rcube_spellchecker(get_input_value('_lang', RCUBE_INPUT_GPC));
$spell_result = $spellchecker->check($message_body, $isHtml);
- $_SESSION['compose']['spell_checked'] = true;
+ $COMPOSE['spell_checked'] = true;
if (!$spell_result) {
$result = $isHtml ? $spellchecker->get_words() : $spellchecker->get_xml();
@@ -458,12 +458,12 @@ $MAIL_MIME = new Mail_mime("\r\n");
// Check if we have enough memory to handle the message in it
// It's faster than using files, so we'll do this if we only can
-if (is_array($_SESSION['compose']['attachments']) && $CONFIG['smtp_server']
+if (is_array($COMPOSE['attachments']) && $CONFIG['smtp_server']
&& ($mem_limit = parse_bytes(ini_get('memory_limit'))))
{
$memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
- foreach ($_SESSION['compose']['attachments'] as $id => $attachment)
+ foreach ($COMPOSE['attachments'] as $id => $attachment)
$memory += $attachment['size'];
// Yeah, Net_SMTP needs up to 12x more memory, 1.33 is for base64
@@ -527,9 +527,9 @@ else {
}
// add stored attachments, if any
-if (is_array($_SESSION['compose']['attachments']))
+if (is_array($COMPOSE['attachments']))
{
- foreach ($_SESSION['compose']['attachments'] as $id => $attachment) {
+ foreach ($COMPOSE['attachments'] as $id => $attachment) {
// This hook retrieves the attachment contents from the file storage backend
$attachment = $RCMAIL->plugins->exec_hook('attachment_get', $attachment);
@@ -626,10 +626,10 @@ if (!$savedraft)
$RCMAIL->user->save_prefs(array('last_message_time' => time()));
// set replied/forwarded flag
- if ($_SESSION['compose']['reply_uid'])
- $IMAP->set_flag($_SESSION['compose']['reply_uid'], 'ANSWERED', $_SESSION['compose']['mailbox']);
- else if ($_SESSION['compose']['forward_uid'])
- $IMAP->set_flag($_SESSION['compose']['forward_uid'], 'FORWARDED', $_SESSION['compose']['mailbox']);
+ if ($COMPOSE['reply_uid'])
+ $IMAP->set_flag($COMPOSE['reply_uid'], 'ANSWERED', $COMPOSE['mailbox']);
+ else if ($COMPOSE['forward_uid'])
+ $IMAP->set_flag($COMPOSE['forward_uid'], 'FORWARDED', $COMPOSE['mailbox']);
} // End of SMTP Delivery Block
@@ -729,7 +729,7 @@ if ($savedraft) {
$draftuids = $IMAP->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid, true);
$saved = $draftuids[0];
}
- $_SESSION['compose']['param']['draft_uid'] = $saved;
+ $COMPOSE['param']['draft_uid'] = $saved;
// display success
$OUTPUT->show_message('messagesaved', 'confirmation');
diff --git a/tests/maildecode.php b/tests/maildecode.php
index 7d67352c3..664161cce 100644
--- a/tests/maildecode.php
+++ b/tests/maildecode.php
@@ -84,4 +84,50 @@ class rcube_test_maildecode extends UnitTestCase
}
}
+ /**
+ * Test decoding of header values
+ * Uses rcube_imap::decode_mime_string()
+ */
+ function test_header_decode_qp()
+ {
+ $test = array(
+ // #1488232: invalid character "?"
+ 'quoted-printable (1)' => array(
+ 'in' => '=?utf-8?Q?Certifica=C3=A7=C3=A3??=',
+ 'out' => 'Certifica=C3=A7=C3=A3?',
+ ),
+ 'quoted-printable (2)' => array(
+ 'in' => '=?utf-8?Q?Certifica=?= =?utf-8?Q?C3=A7=C3=A3?=',
+ 'out' => 'Certifica=C3=A7=C3=A3',
+ ),
+ 'quoted-printable (3)' => array(
+ 'in' => '=?utf-8?Q??= =?utf-8?Q??=',
+ 'out' => '',
+ ),
+ 'quoted-printable (4)' => array(
+ 'in' => '=?utf-8?Q??= a =?utf-8?Q??=',
+ 'out' => ' a ',
+ ),
+ 'quoted-printable (5)' => array(
+ 'in' => '=?utf-8?Q?a?= =?utf-8?Q?b?=',
+ 'out' => 'ab',
+ ),
+ 'quoted-printable (6)' => array(
+ 'in' => '=?utf-8?Q? ?= =?utf-8?Q?a?=',
+ 'out' => ' a',
+ ),
+ 'quoted-printable (7)' => array(
+ 'in' => '=?utf-8?Q?___?= =?utf-8?Q?a?=',
+ 'out' => ' a',
+ ),
+ );
+
+ foreach ($test as $idx => $item) {
+ $res = $this->app->imap->decode_mime_string($item['in'], 'UTF-8');
+ $res = quoted_printable_encode($res);
+
+ $this->assertEqual($item['out'], $res, "Header decoding for: " . $idx);
+ }
+
+ }
}