From a208a4fa68d3c26c34ca3dae250267fec761675c Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Fri, 13 May 2011 12:29:19 -0400
Subject: [PATCH] - Add forward-as-attachment feature

---
 CHANGELOG                               |    1 
 skins/default/templates/mail.html       |    7 +++
 program/include/rcube_imap.php          |   11 +++--
 program/steps/mail/compose.inc          |   66 ++++++++++++++++++++++++++++++++-
 program/localization/en_US/labels.inc   |    2 +
 skins/default/includes/forwardmenu.html |    7 +++
 program/localization/pl_PL/labels.inc   |    2 +
 skins/default/functions.js              |    1 
 skins/default/templates/message.html    |    7 +++
 program/js/app.js                       |    8 ++-
 10 files changed, 101 insertions(+), 11 deletions(-)

diff --git a/CHANGELOG b/CHANGELOG
index 69be4af..879bc74 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
 CHANGELOG Roundcube Webmail
 ===========================
 
+- Add forward-as-attachment feature
 - jQuery-1.6.1 (#1487913, #1487144)
 - Improve display name composition when saving contacts (#1487143)
 - Fixed handling of folder with name "0" in folder selector
diff --git a/program/include/rcube_imap.php b/program/include/rcube_imap.php
index ab2bc2a..eb987dc 100644
--- a/program/include/rcube_imap.php
+++ b/program/include/rcube_imap.php
@@ -2521,14 +2521,17 @@
 
 
     /**
-     * Returns the whole message source as string
+     * Returns the whole message source as string (or saves to a file)
      *
-     * @param int $uid Message UID
+     * @param int      $uid Message UID
+     * @param resource $fp  File pointer to save the message
+     *
      * @return string Message source string
      */
-    function &get_raw_body($uid)
+    function &get_raw_body($uid, $fp=null)
     {
-        return $this->conn->handlePartBody($this->mailbox, $uid, true);
+        return $this->conn->handlePartBody($this->mailbox, $uid,
+            true, null, null, false, $fp);
     }
 
 
diff --git a/program/js/app.js b/program/js/app.js
index 99446d6..aac432f 100644
--- a/program/js/app.js
+++ b/program/js/app.js
@@ -211,7 +211,7 @@
 
         this.env.message_commands = ['show', 'reply', 'reply-all', 'reply-list', 'forward',
           'moveto', 'copy', 'delete', 'open', 'mark', 'edit', 'viewsource', 'download',
-          'print', 'load-attachment', 'load-headers'];
+          'print', 'load-attachment', 'load-headers', 'forward-attachment'];
 
         if (this.env.action=='show' || this.env.action=='preview') {
           this.enable_command(this.env.message_commands, this.env.uid);
@@ -929,10 +929,12 @@
         }
         break;
 
+      case 'forward-attachment':
       case 'forward':
         var uid;
         if (uid = this.get_single_uid())
-          this.goto_url('compose', '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox), true);
+          this.goto_url('compose', '_forward_uid='+uid+'&_mbox='+urlencode(this.env.mailbox)
+            + (command == 'forward-attachment' ? '&_attachment=1' : ''), true);
         break;
 
       case 'print':
@@ -1431,7 +1433,7 @@
     if (selected) {
       // Hide certain command buttons when Drafts folder is selected
       if (this.env.mailbox == this.env.drafts_mailbox)
-        this.enable_command('reply', 'reply-all', 'reply-list', 'forward', false);
+        this.enable_command('reply', 'reply-all', 'reply-list', 'forward', 'forward-attachment', false);
       // Disable reply-list when List-Post header is not set
       else {
         var msg = this.env.messages[list.get_single_selection()];
diff --git a/program/localization/en_US/labels.inc b/program/localization/en_US/labels.inc
index 2175aea..e9d6b6b 100644
--- a/program/localization/en_US/labels.inc
+++ b/program/localization/en_US/labels.inc
@@ -123,6 +123,8 @@
 $labels['replytoallmessage'] = 'Reply to list or to sender and all recipients';
 $labels['replyall']         = 'Reply all';
 $labels['replylist']        = 'Reply list';
+$labels['forwardinline']    = 'Forward inline';
+$labels['forwardattachment'] = 'Forward as attachment';
 $labels['forwardmessage']   = 'Forward the message';
 $labels['deletemessage']    = 'Delete message';
 $labels['movemessagetotrash'] = 'Move message to trash';
diff --git a/program/localization/pl_PL/labels.inc b/program/localization/pl_PL/labels.inc
index 8607f95..d51b59e 100644
--- a/program/localization/pl_PL/labels.inc
+++ b/program/localization/pl_PL/labels.inc
@@ -346,6 +346,8 @@
 $labels['followupto'] = 'Kontynuacja do';
 $labels['replyall'] = 'Odpowiedz wszystkim';
 $labels['replylist'] = 'Odpowiedz na listę';
+$labels['forwardinline'] = 'Prześlij w treści';
+$labels['forwardattachment'] = 'Prześlij jako załącznik';
 $labels['editidents'] = 'Edytuj tożsamości';
 $labels['addfollowupto'] = 'Dodaj Followup-To';
 $labels['dsn'] = 'Status dostarczenia (DSN)';
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 4fe9244..943c800 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -214,6 +214,9 @@
   {
     $_SESSION['compose']['forward_uid'] = $msg_uid;
     $OUTPUT->set_env('compose_mode', 'forward');
+
+    if (!empty($_SESSION['compose']['param']['attachment']))
+      $MESSAGE->forward_attachment = true;
   }
 }
 
@@ -559,6 +562,13 @@
   else if ($_SESSION['compose']['param']['body']) {
     $body = $_SESSION['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']))
+      rcmail_write_forward_attachment($MESSAGE);
   }
   // reply/edit/draft/forward
   else if ($compose_mode) {
@@ -960,8 +970,61 @@
   return $cid_map;
 }
 
+// Creates an attachment from the forwarded message
+function rcmail_write_forward_attachment(&$message)
+{
+  global $RCMAIL;
+
+  if (strlen($message->subject)) {
+    $name = mb_substr($message->subject, 0, 64) . '.eml';
+  }
+  else {
+    $name = 'message_rfc822.eml';
+  }
+
+  $mem_limit = parse_bytes(ini_get('memory_limit'));
+  $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
+  $data = $path = null;
+
+  // don't load too big attachments into memory
+  if ($mem_limit > 0 && $message->size > $mem_limit - $curr_mem) {
+    $temp_dir = unslashify($RCMAIL->config->get('temp_dir'));
+    $path = tempnam($temp_dir, 'rcmAttmnt');
+    if ($fp = fopen($path, 'w')) {
+      $RCMAIL->imap->get_raw_body($message->uid, $fp);
+      fclose($fp);
+    } else
+      return false;
+  } else {
+    $data = $RCMAIL->imap->get_raw_body($message->uid);
+  }
+
+  $attachment = array(
+    'group' => $_SESSION['compose']['id'],
+    'name' => $name,
+    'mimetype' => 'message/rfc822',
+    'data' => $data,
+    'path' => $path,
+    'size' => $path ? filesize($path) : strlen($data),
+  );
+
+  $attachment = $RCMAIL->plugins->exec_hook('attachment_save', $attachment);
+
+  if ($attachment['status']) {
+    unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
+    $_SESSION['compose']['attachments'][$attachment['id']] = $attachment;
+    return true;
+  } else if ($path) {
+    @unlink($path);
+  }
+
+  return false;
+}
+
+
 function rcmail_save_attachment(&$message, $pid)
 {
+  $rcmail = rcmail::get_instance();
   $part = $message->mime_parts[$pid];
   $mem_limit = parse_bytes(ini_get('memory_limit'));
   $curr_mem = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
@@ -969,7 +1032,6 @@
 
   // don't load too big attachments into memory
   if ($mem_limit > 0 && $part->size > $mem_limit - $curr_mem) {
-    $rcmail = rcmail::get_instance();
     $temp_dir = unslashify($rcmail->config->get('temp_dir'));
     $path = tempnam($temp_dir, 'rcmAttmnt');
     if ($fp = fopen($path, 'w')) {
@@ -991,7 +1053,7 @@
     'size' => $path ? filesize($path) : strlen($data),
   );
 
-  $attachment = rcmail::get_instance()->plugins->exec_hook('attachment_save', $attachment);
+  $attachment = $rcmail->plugins->exec_hook('attachment_save', $attachment);
 
   if ($attachment['status']) {
     unset($attachment['data'], $attachment['status'], $attachment['content_id'], $attachment['abort']);
diff --git a/skins/default/functions.js b/skins/default/functions.js
index 65ac39d..344abd2 100644
--- a/skins/default/functions.js
+++ b/skins/default/functions.js
@@ -82,6 +82,7 @@
   this.popups = {
     markmenu:       {id:'markmessagemenu'},
     replyallmenu:   {id:'replyallmenu'},
+    forwardmenu:    {id:'forwardmenu'},
     searchmenu:     {id:'searchmenu', editable:1},
     messagemenu:    {id:'messagemenu'},
     listmenu:       {id:'listmenu', editable:1},
diff --git a/skins/default/includes/forwardmenu.html b/skins/default/includes/forwardmenu.html
new file mode 100644
index 0000000..685d67e
--- /dev/null
+++ b/skins/default/includes/forwardmenu.html
@@ -0,0 +1,7 @@
+<div id="forwardmenu" class="popupmenu">
+    <ul>
+        <li><roundcube:button command="forward" label="forwardinline" prop="sub" classAct="forwardlink active" class="forwardlink" /></li>
+        <li><roundcube:button command="forward-attachment" label="forwardattachment" prop="sub" classAct="forwardattachmentlink active" class="forwardattachmentlink" /></li>
+        <roundcube:container name="forwardmenu" id="forwardmenu" />
+    </ul>
+</div>
diff --git a/skins/default/templates/mail.html b/skins/default/templates/mail.html
index 597a905..7ea9314 100644
--- a/skins/default/templates/mail.html
+++ b/skins/default/templates/mail.html
@@ -112,8 +112,12 @@
 <roundcube:button command="reply" type="link" class="buttonPas reply" classAct="button reply" classSel="button replySel" title="replytomessage" content=" " />
 <span class="dropbutton">
 <roundcube:button command="reply-all" type="link" class="buttonPas replyAll" classAct="button replyAll" classSel="button replyAllSel" title="replytoallmessage" content=" " />
-<span id="replyallmenulink" onclick="rcmail_ui.show_popup('replyallmenu');return false"></span></span>
+<span id="replyallmenulink" onclick="rcmail_ui.show_popup('replyallmenu');return false"></span>
+</span>
+<span class="dropbutton">
 <roundcube:button command="forward" type="link" class="buttonPas forward" classAct="button forward" classSel="button forwardSel" title="forwardmessage" content=" " />
+<span id="forwardmenulink" onclick="rcmail_ui.show_popup('forwardmenu');return false"></span>
+</span>
 <roundcube:button command="delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="deletemessage" content=" " />
 <roundcube:container name="toolbar" id="messagetoolbar" />
 <roundcube:button name="markmenulink" id="markmenulink" type="link" class="button markmessage" title="markmessages" onclick="rcmail_ui.show_popup('markmenu');return false" content=" " />
@@ -131,6 +135,7 @@
 </div>
 
 <roundcube:include file="/includes/replyallmenu.html" />
+<roundcube:include file="/includes/forwardmenu.html" />
 <roundcube:include file="/includes/messagemenu.html" />
 
 <div id="searchmenu" class="popupmenu">
diff --git a/skins/default/templates/message.html b/skins/default/templates/message.html
index 8e4824d..3fd14e4 100644
--- a/skins/default/templates/message.html
+++ b/skins/default/templates/message.html
@@ -23,8 +23,12 @@
 <roundcube:button command="reply" type="link" class="buttonPas reply" classAct="button reply" classSel="button replySel" title="replytomessage" content=" " />
 <span class="dropbutton">
 <roundcube:button command="reply-all" type="link" class="buttonPas replyAll" classAct="button replyAll" classSel="button replyAllSel" title="replytoallmessage" content=" " />
-<span id="replyallmenulink" onclick="rcmail_ui.show_popup('replyallmenu');return false"></span></span>
+<span id="replyallmenulink" onclick="rcmail_ui.show_popup('replyallmenu');return false"></span>
+</span>
+<span class="dropbutton">
 <roundcube:button command="forward" type="link" class="buttonPas forward" classAct="button forward" classSel="button forwardSel" title="forwardmessage" content=" " />
+<span id="forwardmenulink" onclick="rcmail_ui.show_popup('forwardmenu');return false"></span>
+</span>
 <roundcube:button command="delete" type="link" class="buttonPas delete" classAct="button delete" classSel="button deleteSel" title="deletemessage" content=" " />
 <roundcube:container name="toolbar" id="messagetoolbar" />
 <roundcube:button name="messagemenulink" id="messagemenulink" type="link" class="button messagemenu" title="messageactions" onclick="rcmail_ui.show_popup('messagemenu');return false" content=" " />
@@ -32,6 +36,7 @@
 </div>
 
 <roundcube:include file="/includes/replyallmenu.html" />
+<roundcube:include file="/includes/forwardmenu.html" />
 <roundcube:include file="/includes/messagemenu.html" />
 
 <div id="mainscreen">

--
Gitblit v1.9.1