diff options
-rw-r--r-- | CHANGELOG | 1 | ||||
-rw-r--r-- | program/include/rcmail.php | 4 | ||||
-rw-r--r-- | program/include/rcube_session.php | 13 | ||||
-rw-r--r-- | program/js/app.js | 6 | ||||
-rw-r--r-- | program/js/editor_images.js | 2 | ||||
-rw-r--r-- | program/steps/addressbook/save.inc | 3 | ||||
-rw-r--r-- | program/steps/mail/attachments.inc | 6 | ||||
-rw-r--r-- | program/steps/mail/compose.inc | 37 | ||||
-rw-r--r-- | program/steps/mail/func.inc | 8 | ||||
-rw-r--r-- | program/steps/mail/sendmail.inc | 7 |
10 files changed, 57 insertions, 30 deletions
@@ -1,6 +1,7 @@ CHANGELOG Roundcube Webmail =========================== +- Allow multiple concurrent compose sessions - Force names of unique constraints in PostgreSQL DDL - Add code for prevention from IMAP connection hangs when server closes socket unexpectedly - Remove redundant DELETE query (for old session deletion) on login diff --git a/program/include/rcmail.php b/program/include/rcmail.php index 980efe43d..d9bb30bbe 100644 --- a/program/include/rcmail.php +++ b/program/include/rcmail.php @@ -1078,8 +1078,10 @@ class rcmail $this->imap->close(); // before closing the database connection, write session data - if ($_SERVER['REMOTE_ADDR']) + if ($_SERVER['REMOTE_ADDR']) { + $this->session->cleanup(); session_write_close(); + } // write performance stats to logs/console if ($this->config->get('devel_mode')) { diff --git a/program/include/rcube_session.php b/program/include/rcube_session.php index 1fa331753..8c7adb3f1 100644 --- a/program/include/rcube_session.php +++ b/program/include/rcube_session.php @@ -192,6 +192,19 @@ 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'] + if ($_SESSION['compose']) { + $_SESSION['compose_data'][$_SESSION['compose']['id']] = $_SESSION['compose']; + $this->remove('compose'); + } + } + + + /** * Register additional garbage collector functions * * @param mixed Callback function diff --git a/program/js/app.js b/program/js/app.js index a155653d0..fdd9d9c97 100644 --- a/program/js/app.js +++ b/program/js/app.js @@ -227,7 +227,7 @@ function rcube_webmail() } } else if (this.env.action == 'compose') { - this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'toggle-editor']; + this.env.compose_commands = ['send-attachment', 'remove-attachment', 'send', 'cancel', 'toggle-editor']; if (this.env.drafts_mailbox) this.env.compose_commands.push('savedraft') @@ -3270,7 +3270,7 @@ function rcube_webmail() this.remove_attachment = function(name) { if (name && this.env.attachments[name]) - this.http_post('remove-attachment', '_file='+urlencode(name)); + this.http_post('remove-attachment', { _id:this.env.compose_id, _file:name }); return true; }; @@ -5408,7 +5408,7 @@ function rcube_webmail() $(frame_name).bind('load', {ts:ts}, onload); form.target = frame_name; - form.action = this.url(action, { _uploadid:ts }); + form.action = this.url(action, { _id:this.env.compose_id||'', _uploadid:ts }); form.setAttribute('enctype', 'multipart/form-data'); form.submit(); diff --git a/program/js/editor_images.js b/program/js/editor_images.js index 2faafd339..28e6bec38 100644 --- a/program/js/editor_images.js +++ b/program/js/editor_images.js @@ -7,6 +7,6 @@ if (rc_client.env.attachments) { var att = rc_client.env.attachments[id]; if (att.complete && att.mimetype.indexOf('image/') == 0) - tinyMCEImageList.push([att.name, rc_client.env.comm_path+'&_action=display-attachment&_file='+id]); + tinyMCEImageList.push([att.name, rc_client.env.comm_path+'&_action=display-attachment&_file='+id+'&_id='+rc_client.env.compose_id]); } }; diff --git a/program/steps/addressbook/save.inc b/program/steps/addressbook/save.inc index 2884aa418..8949a239b 100644 --- a/program/steps/addressbook/save.inc +++ b/program/steps/addressbook/save.inc @@ -57,6 +57,7 @@ if ($RCMAIL->action == 'upload-photo') { 'size' => $_FILES['_photo']['size'], 'name' => $_FILES['_photo']['name'], 'mimetype' => 'image/' . $imageprop['type'], + 'group' => 'contact', )); } else @@ -156,7 +157,7 @@ if (isset($a_record['photo'])) { unset($a_record['photo']); // cleanup session data - $RCMAIL->plugins->exec_hook('attachments_cleanup', array()); + $RCMAIL->plugins->exec_hook('attachments_cleanup', array('group' => 'contact')); $RCMAIL->session->remove('contacts'); } diff --git a/program/steps/mail/attachments.inc b/program/steps/mail/attachments.inc index 13fb5e0b1..6b32ad6a7 100644 --- a/program/steps/mail/attachments.inc +++ b/program/steps/mail/attachments.inc @@ -20,6 +20,9 @@ */ +$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GPC); +$_SESSION['compose'] = $_SESSION['compose_data'][$COMPOSE_ID]; + if (!$_SESSION['compose']) { die("Invalid session var!"); } @@ -84,7 +87,8 @@ if (is_array($_FILES['_attachments']['tmp_name'])) { 'path' => $filepath, 'size' => $_FILES['_attachments']['size'][$i], 'name' => $_FILES['_attachments']['name'][$i], - 'mimetype' => rc_mime_content_type($filepath, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]) + 'mimetype' => rc_mime_content_type($filepath, $_FILES['_attachments']['name'][$i], $_FILES['_attachments']['type'][$i]), + 'group' => $COMPOSE_ID, ); $attachment = $RCMAIL->plugins->exec_hook('attachment_upload', $attachment); diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc index 41f7b145d..0a949949f 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -28,18 +28,15 @@ define('RCUBE_COMPOSE_EDIT', 0x0109); $MESSAGE_FORM = NULL; $MESSAGE = NULL; +$COMPOSE_ID = get_input_value('_id', RCUBE_INPUT_GET); +$_SESSION['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). -// Since there are many ways to leave the compose page improperly, it seems necessary to clean-up an old -// compose when a "new/forward/reply/draft" is called - otherwise the old session attachments will appear - -$MESSAGE_ID = get_input_value('_id', RCUBE_INPUT_GET); -if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != $MESSAGE_ID) +if (!is_array($_SESSION['compose'])) { - rcmail_compose_cleanup(); - // Infinite redirect prevention in case of broken session (#1487028) - if ($MESSAGE_ID) + if ($COMPOSE_ID) raise_error(array('code' => 500, 'type' => 'php', 'file' => __FILE__, 'line' => __LINE__, 'message' => "Invalid session"), true, true); @@ -81,9 +78,10 @@ if (!is_array($_SESSION['compose']) || $_SESSION['compose']['id'] != $MESSAGE_ID else { $filename = basename($attach); $attachment = array( + 'group' => $COMPOSE_ID, 'name' => $filename, 'mimetype' => rc_mime_content_type($attach, $filename), - 'path' => $attach + 'path' => $attach, ); } @@ -115,6 +113,8 @@ $OUTPUT->add_label('nosubject', 'nosenderwarning', 'norecipientwarning', 'nosubj 'messagesaved', 'converting', 'editorwarning', 'searching', 'uploading', 'fileuploaderror', 'autocompletechars'); +$OUTPUT->set_env('compose_id', $COMPOSE_ID); + // add config parameters to client script if (!empty($CONFIG['drafts_mbox'])) { $OUTPUT->set_env('drafts_mailbox', $CONFIG['drafts_mbox']); @@ -127,16 +127,16 @@ $OUTPUT->set_env('top_posting', $CONFIG['top_posting']); $OUTPUT->set_env('autocomplete_min_length', $CONFIG['autocomplete_min_length']); // get reference message and set compose mode -if ($msg_uid = $_SESSION['compose']['param']['reply_uid']) +if ($msg_uid = $_SESSION['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']) $compose_mode = RCUBE_COMPOSE_REPLY; else if ($msg_uid = $_SESSION['compose']['param']['forward_uid']) $compose_mode = RCUBE_COMPOSE_FORWARD; else if ($msg_uid = $_SESSION['compose']['param']['uid']) $compose_mode = RCUBE_COMPOSE_EDIT; -else if ($msg_uid = $_SESSION['compose']['param']['draft_uid']) { - $RCMAIL->imap->set_mailbox($CONFIG['drafts_mbox']); - $compose_mode = RCUBE_COMPOSE_DRAFT; -} $config_show_sig = $RCMAIL->config->get('show_sig', 1); if ($config_show_sig == 1) @@ -620,7 +620,7 @@ function rcmail_prepare_message_body() if ($attachment = rcmail_save_image('program/blocked.gif', 'image/gif')) { $_SESSION['compose']['attachments'][$attachment['id']] = $attachment; $body = preg_replace('#\./program/blocked\.gif#', - $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'], + $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id'], $body); } } @@ -921,7 +921,7 @@ function rcmail_write_compose_attachments(&$message, $bodyIsHtml) if (!$skip && ($attachment = rcmail_save_attachment($message, $pid))) { $_SESSION['compose']['attachments'][$attachment['id']] = $attachment; if ($bodyIsHtml && ($part->content_id || $part->content_location)) { - $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id']; + $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id']; if ($part->content_id) $cid_map['cid:'.$part->content_id] = $url; else @@ -946,7 +946,7 @@ function rcmail_write_inline_attachments(&$message) 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']; + $url = $RCMAIL->comm_path.'&_action=display-attachment&_file=rcmfile'.$attachment['id'].'&_id='.$_SESSION['compose']['id']; if ($part->content_id) $cid_map['cid:'.$part->content_id] = $url; else @@ -980,6 +980,7 @@ function rcmail_save_attachment(&$message, $pid) } $attachment = array( + 'group' => $_SESSION['compose']['id'], 'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary, 'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary, 'content_id' => $part->content_id, @@ -1006,6 +1007,7 @@ function rcmail_save_image($path, $mimetype='') $data = file_get_contents($path); $attachment = array( + 'group' => $_SESSION['compose']['id'], 'name' => rcmail_basename($path), 'mimetype' => $mimetype ? $mimetype : rc_mime_content_type($path, $name), 'data' => $data, @@ -1323,6 +1325,7 @@ function get_form_tags($attrib) { $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'])); $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 090317691..18ef2de68 100644 --- a/program/steps/mail/func.inc +++ b/program/steps/mail/func.inc @@ -1419,14 +1419,14 @@ function rcmail_message_part_frame($attrib) /** * clear message composing settings */ -function rcmail_compose_cleanup() +function rcmail_compose_cleanup($id) { - if (!isset($_SESSION['compose'])) + if (!isset($_SESSION['compose_data'][$id])) return; $rcmail = rcmail::get_instance(); - $rcmail->plugins->exec_hook('attachments_cleanup', array()); - $rcmail->session->remove('compose'); + $rcmail->plugins->exec_hook('attachments_cleanup', array('group' => $id)); + unset($_SESSION['compose_data'][$id]); } diff --git a/program/steps/mail/sendmail.inc b/program/steps/mail/sendmail.inc index 118e9edeb..a492e937c 100644 --- a/program/steps/mail/sendmail.inc +++ b/program/steps/mail/sendmail.inc @@ -26,6 +26,9 @@ $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]; + /****** checks ********/ if (!isset($_SESSION['compose']['id'])) { @@ -702,7 +705,7 @@ if ($savedraft) // remember new draft-uid $draftuids = $IMAP->search_once($CONFIG['drafts_mbox'], 'HEADER Message-ID '.$msgid, true); - $_SESSION['compose']['param']['_draft_uid'] = $draftuids[0]; + $_SESSION['compose']['param']['draft_uid'] = $draftuids[0]; // display success $OUTPUT->show_message('messagesaved', 'confirmation'); @@ -718,7 +721,7 @@ if ($savedraft) } else { - rcmail_compose_cleanup(); + rcmail_compose_cleanup($COMPOSE_ID); if ($store_folder && !$saved) $OUTPUT->command('sent_successfully', 'error', rcube_label('errorsavingsent')); |