IMP redirect compose improvements.
authorMichael M Slusarz <slusarz@curecanti.org>
Thu, 25 Mar 2010 04:47:23 +0000 (22:47 -0600)
committerMichael M Slusarz <slusarz@curecanti.org>
Thu, 25 Mar 2010 05:21:12 +0000 (23:21 -0600)
[mms] Properly redirect messages pursuant to RFC 5322 [3.6.6].
[mms] Add redirect message capability to DIMP.

20 files changed:
framework/Mime/lib/Horde/Mime/Headers.php
imp/compose-dimp.php
imp/compose-mimp.php
imp/compose.php
imp/docs/CHANGES
imp/js/DimpBase.js
imp/js/compose-dimp.js
imp/js/fullmessage-dimp.js
imp/lib/Ajax/Application.php
imp/lib/Compose.php
imp/lib/Contents.php
imp/lib/Ui/Compose.php
imp/lib/Views/Compose.php
imp/message-dimp.php
imp/templates/dimp/chunks/compose.php
imp/templates/dimp/chunks/message.php
imp/templates/dimp/index.inc
imp/templates/imp/compose/redirect.html
imp/themes/dimp/screen.css
imp/themes/silver/dimp/screen.css

index cbed752..edebab2 100644 (file)
@@ -234,22 +234,6 @@ class Horde_Mime_Headers
     }
 
     /**
-     * Generate the 'Resent' headers (conforms to guidelines in
-     * RFC 2822 [3.6.6]).
-     *
-     * @param string $from  The address to use for 'Resent-From'.
-     * @param string $to    The address to use for 'Resent-To'.
-     */
-    public function addResentHeaders($from, $to)
-    {
-        /* We don't set Resent-Sender, Resent-Cc, or Resent-Bcc. */
-        $this->addHeader('Resent-Date', date('r'));
-        $this->addHeader('Resent-From', $from);
-        $this->addHeader('Resent-To', $to);
-        $this->addHeader('Resent-Message-ID', Horde_Mime::generateMessageId());
-    }
-
-    /**
      * Generate the user agent description header.
      */
     public function addUserAgentHeader()
index d075a82..e9b51b4 100644 (file)
@@ -44,9 +44,13 @@ foreach (array('to', 'cc', 'bcc', 'subject') as $v) {
 
 $fillform_opts = array('noupdate' => 1);
 $get_sig = true;
-$js = array();
 $msg = '';
 
+$js = array();
+if ($vars->popup) {
+    $js[] = 'DIMP.conf_compose.popup = 1';
+}
+
 $identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
 if (!$prefs->isLocked('default_identity') && isset($vars->identity)) {
     $identity->setDefault($vars->identity);
@@ -58,14 +62,10 @@ $imp_compose = IMP_Compose::singleton();
 /* Init IMP_Ui_Compose:: object. */
 $imp_ui = new IMP_Ui_Compose();
 
-/* Attach spellchecker & auto completer. */
-$imp_ui->attachAutoCompleter(array('to', 'cc', 'bcc'));
-$imp_ui->attachSpellChecker();
-
 $show_editor = false;
 $title = _("New Message");
 
-if (in_array($vars->type, array('reply', 'reply_all', 'reply_auto', 'reply_list', 'forward_attach', 'forward_auto', 'forward_body', 'forward_both', 'resume'))) {
+if (in_array($vars->type, array('reply', 'reply_all', 'reply_auto', 'reply_list', 'forward_attach', 'forward_auto', 'forward_body', 'forward_both', 'forward_redirect', 'resume'))) {
     if (!$vars->uid || !$vars->folder) {
         $vars->type = 'new';
     }
@@ -134,6 +134,13 @@ case 'forward_both':
     }
     break;
 
+case 'forward_redirect':
+    $imp_compose->redirectMessage($imp_contents);
+    $get_sig = false;
+    $title = _("Redirect");
+    $vars->type = 'redirect';
+    break;
+
 case 'resume':
     try {
         $result = $imp_compose->resumeDraft($vars->uid . IMP::IDX_SEP . $vars->folder);
@@ -158,15 +165,27 @@ case 'new':
     break;
 }
 
-$sig = $identity->getSignature();
-if ($get_sig && !empty($sig)) {
-    if ($show_editor) {
-        $sig = '<p><!--begin_signature-->' . $imp_compose->text2html(trim($sig)) . '<!--end_signature--></p>';
+/* Attach spellchecker & auto completer. */
+if ($vars->type == 'redirect') {
+    $imp_ui->attachAutoCompleter(array('redirect_to'));
+} else {
+    $imp_ui->attachAutoCompleter(array('to', 'cc', 'bcc', 'redirect_to'));
+    $imp_ui->attachSpellChecker();
+
+    $sig = $identity->getSignature();
+    if ($get_sig && !empty($sig)) {
+        if ($show_editor) {
+            $sig = '<p><!--begin_signature-->' . $imp_compose->text2html(trim($sig)) . '<!--end_signature--></p>';
+        }
+
+        $msg = ($identity->getValue('sig_first'))
+            ? "\n" . $sig . $msg
+            : $msg . "\n" . $sig;
     }
 
-    $msg = ($identity->getValue('sig_first'))
-        ? "\n" . $sig . $msg
-        : $msg . "\n" . $sig;
+    if ($show_editor) {
+        $js[] = 'DIMP.conf_compose.show_editor = 1';
+    }
 }
 
 $t = $injector->createInstance('Horde_Template');
@@ -175,25 +194,17 @@ $t->set('title', $title);
 
 $compose_result = IMP_Views_Compose::showCompose(array(
     'composeCache' => $imp_compose->getCacheId(),
-    'folder' => $vars->folder,
-    'qreply' => false,
-    'uid' => $vars->uid
+    'redirect' => ($vars->type == 'redirect')
 ));
 
 $t->set('compose_html', $compose_result['html']);
 
-/* Javscript variables to be set immediately. */
-if ($show_editor) {
-    $js[] = 'DIMP.conf_compose.show_editor = 1';
-}
-if ($vars->popup) {
-    $js[] = 'DIMP.conf_compose.popup = 1';
-}
 Horde::addInlineScript(array_merge($compose_result['js'], $js));
 
-/* Javascript to be run on window load. */
-$fillform_opts['focus'] = ($vars->type == 'new' || $vars->type == 'forward') ? 'to' : 'composeMessage';
-$compose_result['jsonload'][] = 'DimpCompose.fillForm(' . Horde_Serialize::serialize($msg, Horde_Serialize::JSON) . ',' . Horde_Serialize::serialize($header, Horde_Serialize::JSON) . ',' . Horde_Serialize::serialize($fillform_opts, Horde_Serialize::JSON) . ')';
+$fillform_opts['focus'] = in_array($vars->type, array('forward', 'new', 'redirect')) ? 'to' : 'composeMessage';
+if ($vars->type != 'redirect') {
+    $compose_result['jsonload'][] = 'DimpCompose.fillForm(' . Horde_Serialize::serialize($msg, Horde_Serialize::JSON) . ',' . Horde_Serialize::serialize($header, Horde_Serialize::JSON) . ',' . Horde_Serialize::serialize($fillform_opts, Horde_Serialize::JSON) . ')';
+}
 Horde::addInlineScript($compose_result['jsonload'], 'load');
 
 $scripts = array(
@@ -204,7 +215,7 @@ $scripts = array(
 );
 
 IMP::status();
-IMP_Dimp::header(_("Message Composition"), $scripts);
+IMP_Dimp::header($title, $scripts);
 echo $t->fetch(IMP_TEMPLATES . '/dimp/compose/compose.html');
 Horde::includeScriptFiles();
 Horde::outputInlineScript();
index 6a71a3e..2c9f54b 100644 (file)
@@ -38,6 +38,7 @@ $vars = Horde_Variables::getDefaultVariables();
 $expand = array();
 $header = array('to' => '', 'cc' => '', 'bcc' => '');
 $msg = '';
+$title = _("Compose Message");
 
 /* Get the list of headers to display. */
 $display_hdrs = array('to' => _("To: "));
@@ -150,6 +151,7 @@ case 'rl':
     $header = $reply_msg['headers'];
 
     $notification->push(_("Reply text will be automatically appended to your outgoing message."), 'horde.message');
+    $title = _("Reply");
     break;
 
 // 'f' = forward
@@ -161,17 +163,24 @@ case 'f':
     $header = $fwd_msg['headers'];
 
     $notification->push(_("Forwarded message will be automatically added to your outgoing message."), 'horde.message');
+    $title = _("Forward");
     break;
 
-case _("Redirect"):
-    if (!($imp_contents = $imp_ui->getIMPContents($imp_compose->getMetadata('uid'), $imp_compose->getMetadata('mailbox')))) {
+// 'rc' = redirect compose
+case 'rc':
+    $title = _("Redirect");
+    if (!($imp_contents = $imp_ui->getIMPContents($imp_mbox['uid'], $imp_mbox['thismailbox']))) {
+        // TODO: Error message
         break;
     }
+    $imp_compose->redirectMessage($imp_contents);
+    break;
 
-    $f_to = $imp_ui->getAddressList($header['to']);
-
+case _("Redirect"):
     try {
-        $imp_ui->redirectMessage($f_to, $imp_compose, $imp_contents);
+        $imp_compose->sendRedirectMessage($imp_ui->getAddressList($header['to']));
+        $imp_compose->destroy('send');
+
         if ($prefs->getValue('compose_confirm')) {
             $notification->push(_("Message redirected successfully."), 'horde.success');
         }
@@ -302,8 +311,8 @@ $t->set('to', htmlspecialchars($header['to']));
 $t->set('url', Horde::applicationUrl('compose-mimp.php'));
 
 if ($vars->a == 'rc') {
+    $t->set('redirect', true);
     unset($display_hdrs['cc'], $display_hdrs['bcc']);
-    $title = _("Redirect");
 } else {
     $t->set('compose_enable', !$compose_disable);
     $t->set('msg', htmlspecialchars($msg));
index 0a3ceb9..d0b8457 100644 (file)
@@ -307,18 +307,17 @@ case 'forward_both':
     break;
 
 case 'redirect_compose':
-    $title = _("Redirect this message");
-    break;
-
-case 'redirect_send':
     if (!($imp_contents = $imp_ui->getIMPContents($uid, $thismailbox))) {
         break;
     }
+    $imp_compose->redirectMessage($imp_contents);
+    $title = _("Redirect");
+    break;
 
-    $f_to = $imp_ui->getAddressList($vars->to);
-
+case 'redirect_send':
     try {
-        $imp_ui->redirectMessage($f_to, $imp_compose, $imp_contents);
+        $imp_compose->sendRedirectMessage($imp_ui->getAddressList($vars->to));
+
         $imp_compose->destroy('send');
         if ($isPopup) {
             if ($prefs->getValue('compose_confirm')) {
@@ -714,8 +713,7 @@ $t->set('allow_compose', !$compose_disable);
 
 if ($redirect) {
     /* Prepare the redirect template. */
-    $t->set('mailbox', htmlspecialchars($thismailbox));
-    $t->set('uid', htmlspecialchars($uid));
+    $t->set('cacheid', $composeCacheID);
     $t->set('status', Horde_Util::bufferOutput(array('IMP', 'status')));
     $t->set('title', htmlspecialchars($title));
     $t->set('token', Horde::getRequestToken('imp.compose'));
index e802fa3..31e6d1a 100644 (file)
@@ -2,6 +2,8 @@
 v5.0-git
 --------
 
+[mms] Properly redirect messages pursuant to RFC 5322 [3.6.6].
+[mms] Add redirect message capability to DIMP.
 [mms] Add ability to add attachments to composed messages for advanced mobile
       browsers - disabled by default (MIMP).
 [mms] Add checkbox interface to mailbox page for advanced mobile browsers -
index 9fbfce3..5fd7cb6 100644 (file)
@@ -810,6 +810,7 @@ var DimpBase = {
         case 'ctx_forward_attach':
         case 'ctx_forward_body':
         case 'ctx_forward_both':
+        case 'ctx_forward_redirect':
             this.composeMailbox(id.substring(4));
             break;
 
@@ -2952,9 +2953,7 @@ var DimpBase = {
         this._addMouseEvents({ id: 'folderopts', type: 'folderopts' }, $('folderopts').down(1));
 
         DM.addSubMenu('ctx_message_reply', 'ctx_reply');
-        if ($('ctx_forward')) {
-            DM.addSubMenu('ctx_message_forward', 'ctx_forward');
-        }
+        DM.addSubMenu('ctx_message_forward', 'ctx_forward');
         [ 'ctx_message_', 'oa_' ].each(function(i) {
             if ($(i + 'setflag')) {
                 DM.addSubMenu(i + 'setflag', 'ctx_flag');
@@ -2969,10 +2968,8 @@ var DimpBase = {
             this._addMouseEvents({ id: 'button_reply', type: 'reply' }, $('button_reply'));
             DM.disable('button_reply_img', true, true);
 
-            if ($('ctx_forward')) {
-                this._addMouseEvents({ id: 'button_forward', type: 'forward' }, $('button_forward'));
-                DM.disable('button_forward_img', true, true);
-            }
+            this._addMouseEvents({ id: 'button_forward', type: 'forward' }, $('button_forward'));
+            DM.disable('button_forward_img', true, true);
         }
 
         new Drop('dropbase', this._folderDropConfig);
index 24f0547..fb031db 100644 (file)
@@ -138,7 +138,9 @@ var DimpCompose = {
 
     uniqueSubmit: function(action)
     {
-        var c = $('compose');
+        var c = (action == 'redirectMessage')
+            ? $('redirect')
+            : $('compose');
 
         if (DIMP.SpellChecker &&
             DIMP.SpellChecker.isActive()) {
@@ -196,7 +198,7 @@ var DimpCompose = {
 
             // Can't disable until we send the message - or else nothing
             // will get POST'ed.
-            if (action == 'sendMessage' || action == 'saveDraft') {
+            if (action != 'autoSaveDraft') {
                 this.setDisabled(true);
             }
         }
@@ -259,6 +261,19 @@ var DimpCompose = {
                 }
                 return this.closeCompose();
 
+            case 'redirectMessage':
+                if (this.is_popup && DIMP.baseWindow.DimpBase) {
+                    if (d.log) {
+                        DIMP.baseWindow.DimpBase.updateMsgLog(d.log, { uid: d.uid, mailbox: d.mbox });
+                    }
+
+                    if (!DIMP.conf_compose.qreply) {
+                        DIMP.baseWindow.DimpCore.showNotifications(r.msgs);
+                        r.msgs = [];
+                    }
+                }
+                return this.closeCompose();
+
             case 'addAttachment':
                 this.uploading = false;
                 if (d.success) {
@@ -281,20 +296,27 @@ var DimpCompose = {
         }
 
         this.setDisabled(false);
-        $('compose').setStyle({ cursor: null });
+
+        $((d.action == 'redirectMessage') ? 'redirect' : 'compose').setStyle({ cursor: null });
     },
 
     setDisabled: function(disable)
     {
         this.disabled = disable;
-        DimpCore.loadingImg('sendingImg', 'composeMessageParent', disable);
-        DimpCore.toggleButtons($('compose').select('DIV.dimpActions A'), disable);
-        [ $('compose') ].invoke(disable ? 'disable' : 'enable');
-        if (DIMP.SpellChecker) {
-            DIMP.SpellChecker.disable(disable);
-        }
-        if (IMP_Compose_Base.editor_on) {
-            this.RTELoading(disable ? 'show' : 'hide', true);
+
+        if ($('redirect').visible()) {
+            DimpCore.loadingImg('sendingImg', 'redirect', disable);
+            DimpCore.toggleButtons($('redirect').select('DIV.dimpActions A'), disable);
+        } else {
+            DimpCore.loadingImg('sendingImg', 'composeMessageParent', disable);
+            DimpCore.toggleButtons($('compose').select('DIV.dimpActions A'), disable);
+            [ $('compose') ].invoke(disable ? 'disable' : 'enable');
+            if (DIMP.SpellChecker) {
+                DIMP.SpellChecker.disable(disable);
+            }
+            if (IMP_Compose_Base.editor_on) {
+                this.RTELoading(disable ? 'show' : 'hide', true);
+            }
         }
     },
 
@@ -425,11 +447,13 @@ var DimpCompose = {
         if (DIMP.conf_compose.auto_save_interval_val &&
             !this.auto_save_interval) {
             this.auto_save_interval = new PeriodicalExecuter(function() {
-                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');
+                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;
                 }
-                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();
@@ -662,9 +686,15 @@ var DimpCompose = {
     },
 
     /* Open the addressbook window. */
-    openAddressbook: function()
+    openAddressbook: function(params)
     {
-        window.open(DIMP.conf_compose.URI_ABOOK, 'contacts', 'toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes,width=550,height=300,left=100,top=100');
+        var uri = DIMP.conf_compose.URI_ABOOK;
+
+        if (params) {
+            uri = DimpCore.addURLParam(uri, params);
+        }
+
+        window.open(uri, 'contacts', 'toolbar=no,location=no,status=no,scrollbars=yes,resizable=yes,width=550,height=300,left=100,top=100');
     },
 
     /* Click observe handler. */
@@ -693,9 +723,20 @@ var DimpCompose = {
                 break;
 
             case 'draft_button':
+                if (!this.disabled) {
+                    this.uniqueSubmit('saveDraft');
+                }
+                break;
+
             case 'send_button':
                 if (!this.disabled) {
-                    this.uniqueSubmit(id == 'send_button' ? 'sendMessage' : 'saveDraft');
+                    this.uniqueSubmit('sendMessage');
+                }
+                break;
+
+            case 'send_button_redirect':
+                if (!this.disabled) {
+                    this.uniqueSubmit('redirectMessage');
                 }
                 break;
 
@@ -708,6 +749,16 @@ var DimpCompose = {
                 }
                 break;
 
+            case 'redirect_sendto':
+                if (orig.match('TD.label SPAN')) {
+                    this.openAddressbook({
+                        formfield: 'redirect_to',
+                        formname: 'redirect',
+                        to_only: 1
+                    });
+                }
+                break;
+
             case 'sendcc':
             case 'sendbcc':
             case 'sendto':
@@ -782,6 +833,20 @@ var DimpCompose = {
 
         this.is_popup = (DIMP.baseWindow && DIMP.baseWindow.DimpBase);
 
+        /* Initialize redirect elements (always needed). */
+        $('redirect').observe('submit', Event.stop);
+        new TextareaResize('redirect_to');
+        if (DIMP.conf_compose.URI_ABOOK) {
+            $('redirect_sendto').down('TD.label SPAN').addClassName('composeAddrbook');
+        }
+
+        /* Nothing more to do if this is strictly a redirect window. */
+        if (DIMP.conf_compose.redirect) {
+            $('dimpLoading').hide();
+            $('redirect', 'pageContainer').invoke('show');
+            return;
+        }
+
         /* Attach event handlers. */
         document.observe('change', this.changeHandler.bindAsEventListener(this));
         Event.observe(window, 'resize', this.resizeMsgArea.bind(this));
@@ -795,18 +860,6 @@ var DimpCompose = {
             document.observe('SpellChecker:before', this._onSpellCheckBefore.bind(this));
         }
 
-        // Automatically resize address fields.
-        new TextareaResize('to');
-        new TextareaResize('cc');
-        new TextareaResize('bcc');
-
-        /* Add addressbook link formatting. */
-        if (DIMP.conf_compose.URI_ABOOK) {
-            $('sendto', 'sendcc', 'sendbcc').each(function(a) {
-                a.down('TD.label SPAN').addClassName('composeAddrbook');
-            });
-        }
-
         /* Create folderlist. */
         if (DIMP.conf_compose.flist) {
             this.knl_sm = new KeyNavList('save_sent_mail', {
@@ -829,6 +882,18 @@ var DimpCompose = {
             $('priority_label').insert({ after: new Element('SPAN', { className: 'popdownImg' }).observe('click', function(e) { if (!this.disabled) { this.knl_p.show(); this.knl_p.ignoreClick(e); e.stop(); } }.bindAsEventListener(this)) });
         }
 
+        // Automatically resize compose address fields.
+        new TextareaResize('to');
+        new TextareaResize('cc');
+        new TextareaResize('bcc');
+
+        /* Add addressbook link formatting. */
+        if (DIMP.conf_compose.URI_ABOOK) {
+            $('sendto', 'sendcc', 'sendbcc', 'redirect_sendto').each(function(a) {
+                a.down('TD.label SPAN').addClassName('composeAddrbook');
+            });
+        }
+
         $('dimpLoading').hide();
         $('pageContainer').show();
 
index d9316cc..f5bf5ce 100644 (file)
@@ -13,14 +13,13 @@ var DimpFullmessage = {
         var func, ob = {};
         ob[this.mailbox] = [ this.uid ];
 
-        $('msgData').hide();
-        $('qreply').show();
-
         switch (type) {
         case 'reply':
         case 'reply_all':
         case 'reply_auto':
         case 'reply_list':
+            $('compose').show();
+            $('redirect').hide();
             func = 'getReplyData';
             break;
 
@@ -28,10 +27,21 @@ var DimpFullmessage = {
         case 'forward_attach':
         case 'forward_body':
         case 'forward_both':
+            $('compose').show();
+            $('redirect').hide();
             func = 'getForwardData';
             break;
+
+        case 'forward_redirect':
+            $('compose').hide();
+            $('redirect').show();
+            func = 'getRedirectData';
+            break;
         }
 
+        $('msgData').hide();
+        $('qreply').show();
+
         DimpCore.doAction(func,
                           { imp_compose: $F('composeCache'),
                             type: type },
@@ -45,24 +55,28 @@ var DimpFullmessage = {
             return;
         }
 
-        var i,
-            r = result.response,
-            id = (r.identity === null) ? $F('identity') : r.identity;
+        var i, id,
+            r = result.response;
 
-        if (!r.opts) {
-            r.opts = {};
-        }
-        r.opts.noupdate = true;
-        r.opts.show_editor = (r.format == 'html');
+        if (r.type == 'forward_redirect') {
+            $('redirect_composeCache').setValue(r.imp_compose);
+        } else {
+            if (!r.opts) {
+                r.opts = {};
+            }
+            r.opts.noupdate = true;
+            r.opts.show_editor = (r.format == 'html');
 
-        i = IMP_Compose_Base.getIdentity(id, r.opts.show_editor);
+            id = (r.identity === null) ? $F('identity') : r.identity;
+            i = IMP_Compose_Base.getIdentity(id, r.opts.show_editor);
 
-        $('identity', 'last_identity').invoke('setValue', id);
+            $('identity', 'last_identity').invoke('setValue', id);
 
-        DimpCompose.fillForm((i.id[2]) ? ("\n" + i.sig + r.body) : (r.body + "\n" + i.sig), r.header, r.opts);
+            DimpCompose.fillForm((i.id[2]) ? ("\n" + i.sig + r.body) : (r.body + "\n" + i.sig), r.header, r.opts);
 
-        if (r.imp_compose) {
-            $('composeCache').setValue(r.imp_compose);
+            if (r.imp_compose) {
+                $('composeCache').setValue(r.imp_compose);
+            }
         }
     },
 
@@ -157,6 +171,7 @@ var DimpFullmessage = {
         case 'ctx_forward_attach':
         case 'ctx_forward_body':
         case 'ctx_forward_both':
+        case 'ctx_forward_redirect':
             this.quickreply(id.substring(4));
             break;
 
@@ -190,9 +205,7 @@ var DimpFullmessage = {
             tmp = $('reply_link', 'forward_link').compact().invoke('up', 'SPAN').concat([ $('ctx_contacts_new') ]).compact().invoke('remove');
         } else {
             this.addPopdown('reply_link', 'replypopdown');
-            if ($('ctx_forwardpopdown')) {
-                this.addPopdown('forward_link', 'forwardpopdown');
-            }
+            this.addPopdown('forward_link', 'forwardpopdown');
         }
 
         /* Set up address linking. */
index 13c7e82..552e1b1 100644 (file)
@@ -940,12 +940,7 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
     public function getForwardData()
     {
         try {
-            $imp_compose = IMP_Compose::singleton($this->_vars->imp_compose);
-            if (!($imp_contents = $imp_compose->getContentsOb())) {
-                $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($this->_vars->uid);
-                $i = each($indices);
-                $imp_contents = IMP_Contents::singleton(reset($i['value']) . IMP::IDX_SEP . $i['key']);
-            }
+            list($imp_compose, $imp_contents) = $this->_initCompose();
 
             $fwd_msg = $imp_compose->forwardMessage($this->_vars->type, $imp_contents);
 
@@ -997,18 +992,14 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
      * 'identity' - (integer) The identity ID to use for this message.
      * 'imp_compose' - (string) The IMP_Compose cache identifier.
      * 'opts' - (array) Additional options needed for DimpCompose.fillForm().
+     * 'type' - (string) The input 'type' value.
      * 'ViewPort' - (object) See _viewPortData().
      * </pre>
      */
     public function getReplyData()
     {
         try {
-            $imp_compose = IMP_Compose::singleton($this->_vars->imp_compose);
-            if (!($imp_contents = $imp_compose->getContentsOb())) {
-                $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($this->_vars->uid);
-                $i = each($indices);
-                $imp_contents = IMP_Contents::singleton(reset($i['value']) . IMP::IDX_SEP . $i['key']);
-            }
+            list($imp_compose, $imp_contents) = $this->_initCompose();
 
             $reply_msg = $imp_compose->replyMessage($this->_vars->type, $imp_contents);
             $reply_msg['headers']['replytype'] = 'reply';
@@ -1017,6 +1008,7 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
              * cache id. */
             $result = new stdClass;
             $result->header = $reply_msg['headers'];
+            $result->type = $this->_vars->type;
             if (!$this->_vars->headeronly) {
                 $result->body = $reply_msg['body'];
                 $result->format = $reply_msg['format'];
@@ -1035,6 +1027,35 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
     }
 
     /**
+     * AJAX action: Get compose redirect data.
+     *
+     * Variables used:
+     * <pre>
+     * 'uid' - (string) Index of the message to redirect (IMAP sequence
+     *         string).
+     * </pre>
+     *
+     * @return mixed  False on failure, or an object with the following
+     *                entries:
+     * <pre>
+     * 'imp_compose' - (string) The IMP_Compose cache identifier.
+     * 'type' - (string) The input 'type' value.
+     * </pre>
+     */
+    public function getRedirectData()
+    {
+        list($imp_compose, $imp_contents) = $this->_initCompose();
+
+        $imp_compose->redirectMessage($imp_contents);
+
+        $ob = new stdClass;
+        $ob->imp_compose = $imp_compose->getCacheId();
+        $ob->type = $this->_vars->type;
+
+        return $ob;
+    }
+
+    /**
      * AJAX action: Cancel compose.
      *
      * Variables used:
@@ -1401,6 +1422,56 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
     }
 
     /**
+     * Redirect the message.
+     *
+     * Variables used:
+     * <pre>
+     * 'redirect_composeCache' - (string) The IMP_Compose cache identifier.
+     * 'redirect_to' - (string) The address(es) to redirect to.
+     * </pre>
+     *
+     * @return object  An object with the following entries:
+     * <pre>
+     * 'log' - (array) TODO
+     * 'mbox' - (array) TODO
+     * 'success' - (integer) 1 on success, 0 on failure.
+     * 'uid' - (integer) TODO
+     * </pre>
+     */
+    public function redirectMessage()
+    {
+        $result = new stdClass;
+        $result->action = $this->_action;
+        $result->success = 1;
+
+        try {
+            $imp_compose = IMP_Compose::singleton($this->_vars->redirect_composeCache);
+            $imp_compose->sendRedirectMessage($this->_vars->redirect_to);
+
+            $result->mbox = $imp_compose->getMetadata('mailbox');
+            $result->uid = $imp_compose->getMetadata('uid');
+
+            $contents = $imp_compose->getContentsOb();
+            $headers = $contents->getHeaderOb();
+
+            if ($GLOBALS['prefs']->getValue('compose_confirm')) {
+                $subject = $headers->getValue('subject');
+                $GLOBALS['notification']->push(empty($subject) ? _("Message redirected successfully.") : sprintf(_("Message \"%s\" redirected successfully."), Horde_String::truncate($subject)), 'horde.success');
+            }
+
+            if (!empty($GLOBALS['conf']['maillog']['use_maillog']) &&
+                ($tmp = IMP_Dimp::getMsgLogInfo($headers->getValue('message-id')))) {
+                $result->log = $tmp;
+            }
+        } catch (Horde_Exception $e) {
+            $GLOBALS['notification']->push($e);
+            $result->success = 0;
+        }
+
+        return $result;
+    }
+
+    /**
      * Setup environment for dimp compose actions.
      *
      * Variables used:
@@ -1458,6 +1529,21 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
     }
 
     /**
+     * TODO
+     */
+    protected function _initCompose()
+    {
+        $imp_compose = IMP_Compose::singleton($this->_vars->imp_compose);
+        if (!($imp_contents = $imp_compose->getContentsOb())) {
+            $indices = $GLOBALS['imp_imap']->ob()->utils->fromSequenceString($this->_vars->uid);
+            $i = each($indices);
+            $imp_contents = IMP_Contents::singleton(reset($i['value']) . IMP::IDX_SEP . $i['key']);
+        }
+
+        return array($imp_compose, $imp_contents);
+    }
+
+    /**
      * Save a draft composed message.
      *
      * See the list of variables needed for _dimpComposeSetup(). Additional
@@ -1584,7 +1670,7 @@ class IMP_Ajax_Application extends Horde_Ajax_Application_Base
      * 'view' - (string) The current ViewPort view (mailbox).
      * </pre>
      *
-     * @param boolean $rw            Open mailbox as READ+WRITE?
+     * @param boolean $rw  Open mailbox as READ+WRITE?
      *
      * @return boolean  True if the server state differs from the browser
      *                  state.
index 10f67a4..6859287 100644 (file)
@@ -748,9 +748,10 @@ class IMP_Compose
         $email = $this->_prepSendMessage($email, $headers, $message);
 
         $mail_driver = $this->getMailDriver();
-        $mailer = Mail::factory($mail_driver['driver'], $mail_driver['params']);
-        if ($mailer instanceof PEAR_Error) {
-            throw new IMP_Compose_Exception($mailer);
+        try {
+            $mailer = Horde_Mime_Mail::getMailOb($mail_driver['driver'], $mail_driver['params']);
+        } catch (Horde_Mime_Exception $e) {
+            throw new IMP_Compose_Exception($e);
         }
 
         try {
@@ -850,7 +851,10 @@ class IMP_Compose
             $params['password'] = $GLOBALS['imp_imap']->ob()->getParam('password');
         }
 
-        return array('driver' => $GLOBALS['conf']['mailer']['type'], 'params' => $params);
+        return array(
+            'driver' => $GLOBALS['conf']['mailer']['type'],
+            'params' => $params
+        );
     }
 
     /**
@@ -1640,6 +1644,74 @@ class IMP_Compose
     }
 
     /**
+     * Prepare a redirect message.
+     *
+     * @param IMP_Contents $contents  An IMP_Contents object.
+     */
+    public function redirectMessage($contents)
+    {
+        $this->_metadata['mailbox'] = $contents->getMailbox();
+        $this->_metadata['reply_type'] = 'redirect';
+        $this->_metadata['uid'] = $contents->getUid();
+        $this->_modified = true;
+    }
+
+    /**
+     * Send a redirect (a/k/a resent) message. See RFC 5322 [3.6.6].
+     *
+     * @param string $to  The addresses to redirect to.
+     *
+     * @throws IMP_Compose_Exception
+     */
+    public function sendRedirectMessage($to)
+    {
+        $recip = $this->recipientList(array('to' => $to));
+        $recipients = implode(', ', $recip['list']);
+
+        $identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
+        $from_addr = $identity->getFromAddress();
+
+        $contents = $this->getContentsOb();
+        $headers = $contents->getHeaderOb();
+
+        /* Generate the 'Resent' headers (RFC 5322 [3.6.6]). These headers are
+         * prepended to the message. */
+        $resent_headers = new Horde_Mime_Headers();
+        $resent_headers->addHeader('Resent-Date', date('r'));
+        $resent_headers->addHeader('Resent-From', $from_addr);
+        $resent_headers->addHeader('Resent-To', $recip['header']['to']);
+        $resent_headers->addHeader('Resent-Message-ID', Horde_Mime::generateMessageId());
+
+        $header_text = trim($resent_headers->toString(array('encode' => Horde_Nls::getCharset()))) . "\n" . trim($contents->getHeaderOb(false));
+
+        $mail_driver = $this->getMailDriver();
+        try {
+            $mailer = Horde_Mime_Mail::getMailOb($mail_driver['driver'], $mail_driver['params'], array('raw' => array('from' => $headers->getValue('from'), 'headertext' => $header_text)));
+        } catch (Horde_Mime_Exception $e) {
+            throw new IMP_Compose_Exception($e);
+        }
+
+        $to = $this->_prepSendMessage($recipients);
+
+        try {
+            Horde_Mime_Mail::sendPearMail($mailer, $to, $headers->toArray(array('charset' => Horde_Nls::getCharset())), $contents->getBody());
+        } catch (Horde_Mime_Exception $e) {
+            throw new IMP_Compose_Exception($e);
+        }
+
+        Horde::logMessage(sprintf("%s Redirected message sent to %s from %s", $_SERVER['REMOTE_ADDR'], $recipients, Horde_Auth::getAuth()), 'INFO');
+
+        /* Store history information. */
+        if (!empty($GLOBALS['conf']['maillog']['use_maillog'])) {
+            IMP_Maillog::log('redirect', $headers->getValue('message-id'), $recipients);
+        }
+
+        if ($GLOBALS['conf']['sentmail']['driver'] != 'none') {
+            $GLOBALS['injector']->getInstance('IMP_Sentmail')>log('redirect', $headers->getValue('message-id'), $recipients);
+        }
+    }
+
+    /**
      * Get "tieto" identity information.
      *
      * @param Horde_Mime_Headers $h  The headers object for the message.
@@ -1653,8 +1725,7 @@ class IMP_Compose
             $msgAddresses[] = $h->getValue($val);
         }
 
-        $user_identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
-        return $user_identity->getMatchingIdentity($msgAddresses);
+        return Horde_Prefs_Identity::singleton(array('imp', 'imp'))->getMatchingIdentity($msgAddresses);
     }
 
     /**
index 3cea778..bb47e04 100644 (file)
@@ -307,9 +307,13 @@ class IMP_Contents
     /**
      * Returns the header object.
      *
-     * @return Horde_Mime_Headers  The Horde_Mime_Headers object.
+     * @param boolean $parse  Parse the headers into a headers object?
+     *
+     * @return Horde_Mime_Headers|string  Either a Horde_Mime_Headers object
+     *                                    (if $parse is true) or the header
+     *                                    text (if $parse is false).
      */
-    public function getHeaderOb()
+    public function getHeaderOb($parse = true)
     {
         if (is_null($this->_message)) {
             return $this->_message->getMIMEHeaders();
@@ -317,11 +321,13 @@ class IMP_Contents
 
         try {
             $res = $GLOBALS['imp_imap']->ob()->fetch($this->_mailbox, array(
-                Horde_Imap_Client::FETCH_HEADERTEXT => array(array('parse' => true, 'peek' => true))
+                Horde_Imap_Client::FETCH_HEADERTEXT => array(array('parse' => $parse, 'peek' => true))
             ), array('ids' => array($this->_uid)));
             return $res[$this->_uid]['headertext'][0];
         } catch (Horde_Imap_Client_Exception $e) {
-            return new Horde_Mime_Headers();
+            return $parse
+                ? new Horde_Mime_Headers()
+                : '';
         }
     }
 
@@ -345,7 +351,7 @@ class IMP_Contents
      *            bodypart from the server.
      *            DEFAULT: All data is retrieved.
      * 'nocontents' - (boolean) If true, don't add the contents to the part
-     *              DEFAULT: Contents are added to the part
+     *                DEFAULT: Contents are added to the part
      * </pre>
      *
      * @return Horde_Mime_Part  The raw MIME part asked for (reference).
index 86db14e..bdddb09 100644 (file)
@@ -63,55 +63,6 @@ class IMP_Ui_Compose
     }
 
     /**
-     * Redirect a message.
-     *
-     * @param string $to                  The To address.
-     * @param IMP_Compose $imp_compose    An IMP_Compose object.
-     * @param IMP_Contents $imp_contents  An IMP_Contents object.
-     *
-     * @throws Horde_Exception
-     */
-    public function redirectMessage($to, $imp_compose, $contents)
-    {
-        try {
-            $recip = $imp_compose->recipientList(array('to' => $to));
-        } catch (IMP_Compose_Exception $e) {
-            throw new Horde_Exception_Prior($recip);
-        }
-        $recipients = implode(', ', $recip['list']);
-
-        $identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
-        $from_addr = $identity->getFromAddress();
-
-        $headers = $contents->getHeaderOb();
-        $headers->addResentHeaders($from_addr, $recip['header']['to']);
-
-        $mime_message = $contents->getMIMEMessage();
-
-        /* We need to set the Return-Path header to the current user - see
-           RFC 2821 [4.4]. */
-        $headers->removeHeader('return-path');
-        $headers->addHeader('Return-Path', $from_addr);
-
-        /* Store history information. */
-        if (!empty($GLOBALS['conf']['maillog']['use_maillog'])) {
-            IMP_Maillog::log('redirect', $headers->getValue('message-id'), $recipients);
-        }
-
-        try {
-            $imp_compose->sendMessage($recipients, $headers, $mime_message);
-        } catch (IMP_Compose_Exception $e) {
-            throw new Horde_Exception_Prior($e);
-        }
-
-        $entry = sprintf("%s Redirected message sent to %s from %s",
-                         $_SERVER['REMOTE_ADDR'], $recipients, Horde_Auth::getAuth());
-        Horde::logMessage($entry, 'INFO');
-
-        $GLOBALS['injector']->getInstance('IMP_Sentmail')>log('redirect', $headers->getValue('message-id'), $recipients);
-    }
-
-    /**
      * Attach the auto-completer to the current compose form.
      *
      * @param array $fields  The list of DOM IDs to attach the autocompleter
index c53bccd..470b812 100644 (file)
@@ -16,8 +16,9 @@ class IMP_Views_Compose
      *
      * @param array $args  Configuration parameters:
      * <pre>
-     * 'composeCache' - The cache ID of the IMP_Compose object.
-     * 'qreply' - Is this a quickreply view?
+     * 'composeCache' - (string) The cache ID of the IMP_Compose object.
+     * 'redirect' - (string) Display the redirect interface?
+     * 'qreply' - (boolean) Is this a quickreply view?
      * </pre>
      *
      * @return array  Array with the following keys:
@@ -31,67 +32,75 @@ class IMP_Views_Compose
     {
         $result = array(
             'html' => '',
-            'jsappend' => '',
+            'js' => array(),
             'jsonload' => array()
         );
 
-        /* Load Identity. */
-        $identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
-        $selected_identity = $identity->getDefault();
+        $compose_html = $redirect = $rte = false;
 
-        /* Generate identities list. */
-        $imp_ui = new IMP_Ui_Compose();
-        $result['js'] = array($imp_ui->identityJs());
-
-        $composeCache = null;
-        if (!empty($args['composeCache'])) {
+        if (empty($args['composeCache'])) {
+            $composeCache = null;
+        } else {
             $imp_compose = IMP_Compose::singleton($args['composeCache']);
             $composeCache = $args['composeCache'];
+        }
+
+        if (empty($args['redirect'])) {
+            /* Load Identity. */
+            $identity = Horde_Prefs_Identity::singleton(array('imp', 'imp'));
+            $selected_identity = $identity->getDefault();
 
-            if ($imp_compose->numberOfAttachments()) {
+            /* Generate identities list. */
+            $imp_ui = $GLOBALS['injector']->getInstance('IMP_Ui_Compose');
+            $result['js'][] = $imp_ui->identityJs();
+
+            if ($composeCache &&
+                $imp_compose->numberOfAttachments()) {
                 foreach ($imp_compose->getAttachments() as $num => $atc) {
                     $mime = $atc['part'];
                     $result['jsonload'][] = 'DimpCompose.addAttach(' . $num . ', \'' . addslashes($mime->getName(true)) . '\', \'' . addslashes($mime->getType()) . '\', \'' . addslashes($mime->getSize()) . "')";
                 }
             }
-        }
 
-        if (!empty($args['qreply'])) {
-            $result['js'][] = 'DIMP.conf_compose.qreply = 1';
-        }
+            if (!empty($args['qreply'])) {
+                $result['js'][] = 'DIMP.conf_compose.qreply = 1';
+            }
 
-        $compose_html = $rte = false;
-        if ($_SESSION['imp']['rteavail']) {
-            $compose_html = $GLOBALS['prefs']->getValue('compose_html');
-            $rte = true;
+            if ($_SESSION['imp']['rteavail']) {
+                $compose_html = $GLOBALS['prefs']->getValue('compose_html');
+                $rte = true;
 
-            $imp_ui->initRTE(!$compose_html);
-        }
+                $imp_ui->initRTE(!$compose_html);
+            }
 
-        /* Create list for sent-mail selection. */
-        if (!empty($GLOBALS['conf']['user']['select_sentmail_folder']) &&
-            !$GLOBALS['prefs']->isLocked('sent_mail_folder')) {
-            $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder');
+            /* Create list for sent-mail selection. */
+            if (!empty($GLOBALS['conf']['user']['select_sentmail_folder']) &&
+                !$GLOBALS['prefs']->isLocked('sent_mail_folder')) {
+                $imp_folder = $GLOBALS['injector']->getInstance('IMP_Folder');
 
-            /* Check to make sure the sent-mail folders are created - they
-             * need to exist to show up in drop-down list. */
-            foreach (array_keys($identity->getAllSignatures()) as $ident) {
-                $val = $identity->getValue('sent_mail_folder', $ident);
-                if (!$imp_folder->exists($val)) {
-                    $imp_folder->create($val, true);
+                /* Check to make sure the sent-mail folders are created - they
+                 * need to exist to show up in drop-down list. */
+                foreach (array_keys($identity->getAllSignatures()) as $ident) {
+                    $val = $identity->getValue('sent_mail_folder', $ident);
+                    if (!$imp_folder->exists($val)) {
+                        $imp_folder->create($val, true);
+                    }
                 }
-            }
 
-            $flist = array();
-            foreach ($imp_folder->flist() as $val) {
-                $tmp = array('l' => $val['abbrev'], 'v' => $val['val']);
-                $tmp2 = IMP::displayFolder($val['val']);
-                if ($val['val'] != $tmp2) {
-                    $tmp['f'] = $tmp2;
+                $flist = array();
+                foreach ($imp_folder->flist() as $val) {
+                    $tmp = array('l' => $val['abbrev'], 'v' => $val['val']);
+                    $tmp2 = IMP::displayFolder($val['val']);
+                    if ($val['val'] != $tmp2) {
+                        $tmp['f'] = $tmp2;
+                    }
+                    $flist[] = $tmp;
                 }
-                $flist[] = $tmp;
+                $result['js'][] = 'DIMP.conf_compose.flist = ' . Horde_Serialize::serialize($flist, Horde_Serialize::JSON);
             }
-            $result['js'][] = 'DIMP.conf_compose.flist = ' . Horde_Serialize::serialize($flist, Horde_Serialize::JSON);
+        } else {
+            $result['js'][] = 'DIMP.conf_compose.redirect = 1';
+            $redirect = true;
         }
 
         // Buffer output so that we can return a string from this function
index 69b2ef2..66add46 100644 (file)
@@ -69,7 +69,7 @@ if (!$disable_compose) {
 
     /* Attach spellchecker & auto completer. */
     $imp_ui = new IMP_Ui_Compose();
-    $imp_ui->attachAutoCompleter(array('to', 'cc', 'bcc'));
+    $imp_ui->attachAutoCompleter(array('to', 'cc', 'bcc', 'redirect_to'));
     $imp_ui->attachSpellChecker();
 
     $js_out = array_merge($js_out, $compose_result['js']);
index 32ec64c..1366e70 100644 (file)
@@ -19,6 +19,7 @@ $save_attach = $GLOBALS['prefs']->getValue('save_attachments');
 $compose_disable = !IMP::canCompose();
 
 ?>
+<?php if (!$redirect): ?>
 <form id="compose" name="compose" enctype="multipart/form-data" action="<?php echo Horde::getServiceLink('ajax', 'imp') ?>addAttachment" method="post" target="submit_frame">
 <?php echo Horde_Util::formInput() ?>
 <input type="hidden" id="last_identity" name="last_identity" value="<?php echo (int)$selected_identity ?>" />
@@ -140,6 +141,28 @@ $compose_disable = !IMP::canCompose();
  </div>
 </div>
 </form>
+<?php endif; // !$redirect ?>
+
+<?php if (!$compose_disable): ?>
+<form id="redirect" name="redirect" style="display:none">
+ <input type="hidden" id="redirect_composeCache" name="redirect_composeCache" value="<?php echo $composeCache ?>" />
+<?php echo Horde_Util::formInput() ?>
+ <div class="msgwrite">
+  <div class="dimpActions dimpActionsCompose">
+   <div><?php echo IMP_Dimp::actionButton(array('icon' => 'Forward', 'id' => 'send_button_redirect', 'title' => _("Redirect"))); ?></div>
+  </div>
+ <table>
+  <tr id="redirect_sendto">
+   <td class="label"><span><?php echo _("To: ") ?></span></td>
+   <td>
+    <span id="redirect_to_loading_img" class="loadingImg" style="display:none"></span>
+    <textarea id="redirect_to" name="redirect_to" rows="1" cols="75"></textarea>
+   </td>
+  </tr>
+ </table>
+ </div>
+</form>
+<?php endif; ?>
 
 <span id="sendingImg" class="loadingImg" style="display:none"></span>
 
index b0a4a8e..03065e6 100644 (file)
 <?php endif; ?>
 </div>
 
-<?php if (!$prefs->isLocked('forward_default')): ?>
 <div class="context" id="ctx_forwardpopdown" style="display:none;">
+<?php if (!$prefs->isLocked('forward_default')): ?>
  <a id="ctx_forward_attach"><span class="contextImg"></span><?php echo _("As Attachment") ?></a>
  <a id="ctx_forward_body"><span class="contextImg"></span><?php echo _("In Body Text") ?></a>
  <a id="ctx_forward_both"><span class="contextImg"></span><?php echo _("Attachment and Body Text") ?></a>
-</div>
+ <div class="sep"></div>
 <?php endif; ?>
+ <a id="ctx_forward_redirect"><span class="contextImg"></span><?php echo _("Redirect") ?></a>
+</div>
 <?php endif; ?>
 
 <div class="context" id="ctx_contacts" style="display:none">
index 730260b..f6f0a78 100644 (file)
@@ -403,13 +403,15 @@ function _simpleButton($id, $text, $image, $nodisplay = false)
  <a id="ctx_reply_reply_list"><span class="contextImg"></span><?php echo _("To List") ?></a>
 </div>
 
-<?php if (!$prefs->isLocked('forward_default')): ?>
 <div class="context" id="ctx_forward" style="display:none;">
+<?php if (!$prefs->isLocked('forward_default')): ?>
  <a id="ctx_forward_attach"><span class="contextImg"></span><?php echo _("As Attachment") ?></a>
  <a id="ctx_forward_body"><span class="contextImg"></span><?php echo _("In Body Text") ?></a>
  <a id="ctx_forward_both"><span class="contextImg"></span><?php echo _("Attachment and Body Text") ?></a>
-</div>
+ <div class="sep"></div>
 <?php endif; ?>
+ <a id="ctx_forward_redirect"><span class="contextImg"></span><?php echo _("Redirect") ?></a>
+</div>
 
 <div class="context" id="ctx_otheractions" style="display:none">
  <a id="oa_preview_hide"><span class="contextImg"></span><?php echo _("Hide Preview") ?></a>
index b96392e..230dca0 100644 (file)
@@ -1,6 +1,5 @@
 <form method="post" action="<tag:post_action />" id="redirect" name="redirect">
-<input type="hidden" name="thismailbox" value="<tag:mailbox />" />
-<input type="hidden" name="uid" value="<tag:uid />" />
+<input type="hidden" name="composeCache" value="<tag:cacheid />" />
 <input type="hidden" id="actionID" name="actionID" value="redirect_send" />
 <input type="hidden" name="compose_requestToken" value="<tag:token />" />
 
index b99734d..26c1fee 100644 (file)
@@ -906,7 +906,7 @@ span.dimpactionDrafts {
 #ctx_reply_reply span.contextImg, #ctx_reply_reply_all span.contextImg, #ctx_reply_reply_list span.contextImg {
     background-image: url("../graphics/replyall.png");
 }
-#ctx_message_forward span.contextImg, #ctx_forward_attach span.contextImg, #ctx_forward_body span.contextImg, #ctx_forward_both span.contextImg {
+#ctx_message_forward span.contextImg, #ctx_forward_attach span.contextImg, #ctx_forward_body span.contextImg, #ctx_forward_both span.contextImg, #ctx_forward_redirect span.contextImg {
     background-image: url("../graphics/forward.png");
 }
 #ctx_folder_empty span.contextImg, #ctx_message_deleted span.contextImg, #oa_purge_deleted span.contextImg {
index 89f744d..72d95a2 100644 (file)
@@ -82,7 +82,7 @@ span.dimpactionDrafts {
 #ctx_reply_reply span.contextImg, #ctx_reply_reply_all span.contextImg, #ctx_reply_reply_list span.contextImg {
     background-image: url("../graphics/replyall.png");
 }
-#ctx_message_forward span.contextImg, #ctx_forward_attach span.contextImg, #ctx_forward_body span.contextImg, #ctx_forward_both span.contextImg {
+#ctx_message_forward span.contextImg, #ctx_forward_attach span.contextImg, #ctx_forward_body span.contextImg, #ctx_forward_both span.contextImg, #ctx_forward_redirect span.contextImg {
     background-image: url("../graphics/forward.png");
 }
 #ctx_folder_empty span.contextImg, #ctx_message_deleted span.contextImg, #oa_purge_deleted span.contextImg {