v5.0-git
--------
+[mms] Use alternate text part to generate reply/forward text when switching
+ compose modes if user has not altered message text (DIMP).
[mms] Improved login error reporting/logging in IMP (Request #9211).
[mms] Add hook to skip MDN prompt based on content of message headers.
[mms] Allow expand/collapse of folders in MIMP.
var DimpCompose = {
// Variables defaulting to empty/false:
// auto_save_interval, compose_cursor, disabled, drafts_mbox,
- // editor_wait, is_popup, knl, last_msg, old_action, old_identity,
- // resizing, rte, skip_spellcheck, spellcheck, sc_submit, uploading
+ // editor_wait, is_popup, knl, md5_hdrs, md5_msg, md5_msgOrig,
+ // old_action, old_identity, resizing, rte, rte_loaded, skip_spellcheck,
+ // spellcheck, sc_submit, uploading
knl: {},
closeQReply: function()
{
var al = $('attach_list').childElements();
- this.last_msg = '';
+ this.md5_hdrs = this.md5_msg = this.md5_msgOrig = '';
if (al.size()) {
this.removeAttach(al);
DIMP.SpellChecker.resume();
}
- var config, text;
+ var changed, config, text;
if (IMP_Compose_Base.editor_on) {
+ changed = (this.msgHash() != this.md5_msgOrig);
text = this.rte.getData();
this.rte.destroy();
+ this.rte_loaded = false;
this.RTELoading('show');
- DimpCore.doAction('html2Text', { identity: $F('identity'), text: text }, { callback: this.setMessageText.bind(this), ajaxopts: { asynchronous: false } });
+ DimpCore.doAction('html2Text', {
+ changed: Number(changed),
+ identity: $F('identity'),
+ imp_compose: $F('composeCache'),
+ text: text
+ }, {
+ ajaxopts: { asynchronous: false },
+ callback: this.setMessageText.bind(this)
+ });
this.RTELoading('hide');
} else {
if (!noupdate) {
- DimpCore.doAction('text2Html', { identity: $F('identity'), text: $F('composeMessage') }, { callback: this.setMessageText.bind(this), ajaxopts: { asynchronous: false } });
+ DimpCore.doAction('text2Html', {
+ changed: Number(this.msgHash() != this.md5_msgOrig),
+ identity: $F('identity'),
+ imp_compose: $F('composeCache'),
+ text: $F('composeMessage')
+ }, {
+ ajaxopts: { asynchronous: false },
+ callback: this.setMessageText.bind(this)
+ });
}
config = Object.clone(IMP.ckeditor_config);
this.resizeMsgArea();
this.RTELoading('hide');
this.rte.focus();
+ this.rte_loaded = true;
}.bind(this);
this.RTELoading('show');
this.rte = CKEDITOR.replace('composeMessage', config);
identity = IMP_Compose_Base.getIdentity($F('last_identity'));
opts = opts || {};
- // Set auto-save-drafts now if not already active.
- if (DIMP.conf_compose.auto_save_interval_val &&
- !this.auto_save_interval) {
- this.auto_save_interval = new PeriodicalExecuter(function() {
- if ($('compose').visible()) {
- var curr_hash = MD5.hash($('to', 'cc', 'bcc', 'subject').invoke('getValue').join('\0') + (IMP_Compose_Base.editor_on ? this.rte.getData() : $F('composeMessage')));
- if (this.last_msg && curr_hash != this.last_msg) {
- this.uniqueSubmit('autoSaveDraft');
- }
- this.last_msg = curr_hash;
- }
- }.bind(this), DIMP.conf_compose.auto_save_interval_val * 60);
- /* Immediately execute to get MD5 hash of empty message. */
- this.auto_save_interval.execute();
- }
-
$('to').setValue(header.to);
if (header.cc) {
$('cc').setValue(header.cc);
this.focusEditor();
}
}
+
+ this.fillFormHash();
+ },
+
+ fillFormHash: function()
+ {
+ if (IMP_Compose_Base.editor_on && !this.rte_loaded) {
+ this.fillFormHash.bind(this).defer();
+ return;
+ }
+
+ // This value is used to determine if the text has changed when
+ // swapping compose modes.
+ this.md5_msgOrig = this.msgHash();
+
+ // Set auto-save-drafts now if not already active.
+ if (DIMP.conf_compose.auto_save_interval_val &&
+ !this.auto_save_interval) {
+ this.auto_save_interval = new PeriodicalExecuter(function() {
+ if ($('compose').visible()) {
+ var hdrs = MD5.hash($('to', 'cc', 'bcc', 'subject').invoke('getValue').join('\0')), msg;
+ if (this.md5_hdrs) {
+ msg = this.msgHash();
+ if (this.md5_hdrs != hdrs || this.md5_msg != msg) {
+ this.uniqueSubmit('autoSaveDraft');
+ }
+ } else {
+ msg = this.md5_msgOrig;
+ }
+ this.md5_hdrs = hdrs;
+ this.md5_msg = msg;
+ }
+ }.bind(this), DIMP.conf_compose.auto_save_interval_val * 60);
+
+ /* Immediately execute to get MD5 hash of headers. */
+ this.auto_save_interval.execute();
+ }
+ },
+
+ msgHash: function()
+ {
+ return MD5.hash(IMP_Compose_Base.editor_on ? this.rte.getData() : $F('composeMessage'));
},
fadeNotice: function(elt)
*
* Variables used:
* <pre>
+ * 'changed' - (integer) Has the text changed from the original?
* 'identity' - (integer) The current identity.
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
* 'text' - (string) The text to convert.
* </pre>
*
public function html2Text()
{
$result = new stdClass;
+
+ if (!$this->_vars->changed) {
+ list($imp_compose, $imp_contents) = $this->_initCompose();
+
+ switch ($imp_compose->getMetadata('reply_type')) {
+ case 'forward':
+ switch ($imp_compose->getMetadata('forward_type')) {
+ case 'forward_body':
+ case 'forward_both':
+ $data = $imp_compose->forwardMessageText($imp_contents, array(
+ 'format' => 'text'
+ ));
+ $result->text = $data['body'];
+ return $result;
+ }
+ break;
+
+ case 'reply':
+ case 'reply_all':
+ case 'reply_list':
+ $data = $imp_compose->replyMessageText($imp_contents, array(
+ 'format' => 'text'
+ ));
+ $result->text = $data['body'];
+ return $result;
+ }
+ }
+
$result->text = $GLOBALS['injector']->getInstance('IMP_Ui_Compose')->convertComposeText($this->_vars->text, 'text', intval($this->_vars->identity));
return $result;
*
* Variables used:
* <pre>
+ * 'changed' - (integer) Has the text changed from the original?
* 'identity' - (integer) The current identity.
+ * 'imp_compose' - (string) The IMP_Compose cache identifier.
* 'text' - (string) The text to convert.
* </pre>
*
public function text2Html()
{
$result = new stdClass;
+
+ if (!$this->_vars->changed) {
+ list($imp_compose, $imp_contents) = $this->_initCompose();
+
+ switch ($imp_compose->getMetadata('reply_type')) {
+ case 'forward':
+ switch ($imp_compose->getMetadata('forward_type')) {
+ case 'forward_body':
+ case 'forward_both':
+ $data = $imp_compose->forwardMessageText($imp_contents, array(
+ 'format' => 'html'
+ ));
+ $result->text = $data['body'];
+ return $result;
+ }
+ break;
+
+ case 'reply':
+ case 'reply_all':
+ case 'reply_list':
+ $data = $imp_compose->replyMessageText($imp_contents, array(
+ 'format' => 'html'
+ ));
+ $result->text = $data['body'];
+ return $result;
+ }
+ }
+
$result->text = $GLOBALS['injector']->getInstance('IMP_Ui_Compose')->convertComposeText($this->_vars->text, 'html', intval($this->_vars->identity));
return $result;
$this->_modified = true;
}
+ return array_merge(array(
+ 'headers' => $header,
+ 'identity' => $match_identity,
+ 'type' => $reply_type
+ ), $this->replyMessageText($contents));
+ }
+
+ /**
+ * Returns the reply text for a message.
+ *
+ * @param IMP_Contents $contents An IMP_Contents object.
+ * @param array $opts Additional options:
+ * <pre>
+ * 'format' - (string) Force to this format.
+ * DEFAULT: Auto-determine.
+ * </pre>
+ *
+ * @return array An array with the following keys:
+ * <pre>
+ * 'body' - The text of the body part
+ * 'encoding' - The guessed charset to use for the reply
+ * 'format' - The format of the body message
+ * </pre>
+ */
+ public function replyMessageText($contents, array $opts = array())
+ {
+ global $prefs;
+
if (!$prefs->getValue('reply_quote')) {
return array(
'body' => '',
- 'format' => 'text',
- 'headers' => $header,
- 'identity' => $match_identity,
- 'type' => $reply_type
+ 'encoding' => '',
+ 'format' => 'text'
);
}
+ $charset = $GLOBALS['registry']->getCharset();
+ $h = $contents->getHeaderOb();
+
$from = Horde_Mime_Address::addrArray2String($h->getOb('from'), array('charset' => $charset));
if ($prefs->getValue('reply_headers') && !empty($h)) {
$msg_post = '';
}
- $compose_html = (($_SESSION['imp']['view'] != 'mimp') && $GLOBALS['prefs']->getValue('compose_html'));
+ if ($_SESSION['imp']['view'] == 'mimp') {
+ $compose_html = false;
+ } elseif (!empty($opts['format'])) {
+ $compose_html = ($opts['format'] == 'html');
+ } else {
+ $compose_html = ($prefs->getValue('compose_html') || $prefs->getValue('reply_format'));
+ }
$msg_text = $this->_getMessageText($contents, array(
- 'html' => ($GLOBALS['prefs']->getValue('reply_format') || $compose_html),
+ 'html' => $compose_html,
'replylimit' => true,
'toflowed' => true,
'type' => 'reply'
));
if (!empty($msg_text) &&
- ($compose_html || ($msg_text['mode'] == 'html'))) {
+ ($prefs->getValue('compose_html') ||
+ ($msg_text['mode'] == 'html'))) {
$msg = '<p>' . $this->text2html(trim($msg_pre)) . '</p>' .
'<blockquote type="cite" style="background-color:#f0f0f0;border-left:1px solid blue;padding-left:1em;">' .
(($msg_text['mode'] == 'text') ? $this->text2html($msg_text['text']) : $msg_text['text']) .
$msg = empty($msg_text['text'])
? '[' . _("No message body text") . ']'
: $msg_pre . $msg_text['text'] . $msg_post;
+ $msg_text['mode'] = 'text';
}
return array(
'body' => $msg . "\n",
'encoding' => $msg_text['encoding'],
- 'format' => $msg_text['mode'],
- 'headers' => $header,
- 'identity' => $match_identity,
- 'type' => $reply_type
+ 'format' => $msg_text['mode']
);
}
* added to the outgoing messages. */
$this->_metadata['in_reply_to'] = trim($h->getValue('message-id'));
$this->_metadata['reply_type'] = 'forward';
+ $this->_metadata['forward_type'] = $type;
$this->_modified = true;
$header['subject'] = $h->getValue('subject');
$header['subject'] = 'Fwd:';
}
+ if ($attach &&
+ in_array($type, array('forward_attach', 'forward_both'))) {
+ $this->attachIMAPMessage(new IMP_Indices($contents));
+ }
+
if (in_array($type, array('forward_body', 'forward_both'))) {
- $from = Horde_Mime_Address::addrArray2String($h->getOb('from'), array('charset' => $GLOBALS['registry']->getCharset()));
+ $ret = $this->forwardMessageText($contents);
+ } else {
+ $ret = array(
+ 'body' => '',
+ 'encoding' => '',
+ 'format' => 'text'
+ );
+ }
- $msg_pre = "\n----- " .
- ($from ? sprintf(_("Forwarded message from %s"), $from) : _("Forwarded message")) .
- " -----\n" . $this->_getMsgHeaders($h) . "\n";
- $msg_post = "\n\n----- " . _("End forwarded message") . " -----\n";
+ return array_merge(array(
+ 'headers' => $header,
+ 'identity' => $this->_getMatchingIdentity($h),
+ 'type' => $type
+ ), $ret);
+ }
- $compose_html = (($_SESSION['imp']['view'] != 'mimp') && $GLOBALS['prefs']->getValue('compose_html'));
+ /**
+ * Returns the forward text for a message.
+ *
+ * @param IMP_Contents $contents An IMP_Contents object.
+ * @param array $opts Additional options:
+ * <pre>
+ * 'format' - (string) Force to this format.
+ * DEFAULT: Auto-determine.
+ * </pre>
+ *
+ * @return array An array with the following keys:
+ * <pre>
+ * 'body' - The text of the body part
+ * 'encoding' - The guessed charset to use for the reply
+ * 'format' - The format of the body message
+ * </pre>
+ */
+ public function forwardMessageText($contents, array $opts = array())
+ {
+ global $prefs;
- $msg_text = $this->_getMessageText($contents, array(
- 'html' => ($GLOBALS['prefs']->getValue('forward_format') || $compose_html),
- 'type' => 'forward'
- ));
+ $h = $contents->getHeaderOb();
- if (!empty($msg_text) &&
- ($compose_html || ($msg_text['mode'] == 'html'))) {
- $msg = $this->text2html($msg_pre) .
- (($msg_text['mode'] == 'text') ? $this->text2html($msg_text['text']) : $msg_text['text']) .
- $this->text2html($msg_post);
- $format = 'html';
- } else {
- $msg = $msg_pre . $msg_text['text'] . $msg_post;
- }
+ $from = Horde_Mime_Address::addrArray2String($h->getOb('from'), array(
+ 'charset' => $GLOBALS['registry']->getCharset()
+ ));
+
+ $msg_pre = "\n----- " .
+ ($from ? sprintf(_("Forwarded message from %s"), $from) : _("Forwarded message")) .
+ " -----\n" . $this->_getMsgHeaders($h) . "\n";
+ $msg_post = "\n\n----- " . _("End forwarded message") . " -----\n";
+
+ if ($_SESSION['imp']['view'] == 'mimp') {
+ $compose_html = false;
+ } elseif (!empty($opts['format'])) {
+ $compose_html = ($opts['format'] == 'html');
+ } else {
+ $compose_html = ($prefs->getValue('compose_html') || $prefs->getValue('forward_format'));
}
- if ($attach &&
- in_array($type, array('forward_attach', 'forward_both'))) {
- $this->attachIMAPMessage(new IMP_Indices($contents));
+ $msg_text = $this->_getMessageText($contents, array(
+ 'html' => $compose_html,
+ 'type' => 'forward'
+ ));
+
+ if (!empty($msg_text) &&
+ ($prefs->getValue('compose_html') ||
+ ($msg_text['mode'] == 'html'))) {
+ $msg = $this->text2html($msg_pre) .
+ (($msg_text['mode'] == 'text') ? $this->text2html($msg_text['text']) : $msg_text['text']) .
+ $this->text2html($msg_post);
+ $format = 'html';
+ } else {
+ $msg = $msg_pre . $msg_text['text'] . $msg_post;
+ $format = 'text';
}
return array(
'body' => $msg,
- 'encoding' => isset($msg_text) ? $msg_text['encoding'] : $GLOBALS['registry']->getCharset(),
- 'format' => $format,
- 'headers' => $header,
- 'identity' => $this->_getMatchingIdentity($h),
- 'type' => $type
+ 'encoding' => $msg_text['encoding'],
+ 'format' => $format
);
}