From a640647edd0776555b9d2083fd968b2317143c8c Mon Sep 17 00:00:00 2001
From: alecpl <alec@alec.pl>
Date: Sun, 19 Jul 2009 05:28:30 -0400
Subject: [PATCH] - handle big attachments with file pointers to not exceed memory_limit in rcmail_save_attachment()

---
 plugins/filesystem_attachments/filesystem_attachments.php |   30 ++++++++------
 program/steps/mail/compose.inc                            |   29 ++++++++++++--
 plugins/database_attachments/database_attachments.php     |    4 ++
 3 files changed, 46 insertions(+), 17 deletions(-)

diff --git a/plugins/database_attachments/database_attachments.php b/plugins/database_attachments/database_attachments.php
index 28ccde4..a8ac62e 100644
--- a/plugins/database_attachments/database_attachments.php
+++ b/plugins/database_attachments/database_attachments.php
@@ -63,6 +63,10 @@
         $rcmail = rcmail::get_instance();
 
         $key = $this->_key($args['name']);
+
+	if ($args['path'])
+	    $args['data'] = file_get_contents($args['path']);
+
         $data = base64_encode($args['data']);
 
         $status = $rcmail->db->query(
diff --git a/plugins/filesystem_attachments/filesystem_attachments.php b/plugins/filesystem_attachments/filesystem_attachments.php
index 9a6c0a8..f4b9b6d 100644
--- a/plugins/filesystem_attachments/filesystem_attachments.php
+++ b/plugins/filesystem_attachments/filesystem_attachments.php
@@ -73,21 +73,25 @@
     function save($args)
     {
         $args['status'] = false;
-        $rcmail = rcmail::get_instance();
-        $temp_dir = unslashify($rcmail->config->get('temp_dir'));
-        $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
+	
+	if (!$args['path']) {
+    	    $rcmail = rcmail::get_instance();
+            $temp_dir = unslashify($rcmail->config->get('temp_dir'));
+    	    $tmp_path = tempnam($temp_dir, 'rcmAttmnt');
 
-        if ($fp = fopen($tmp_path, 'w')) {
-            fwrite($fp, $args['data']);
-            fclose($fp);
+    	    if ($fp = fopen($tmp_path, 'w')) {
+        	fwrite($fp, $args['data']);
+        	fclose($fp);
+        	$args['path'] = $tmp_path;
+    	    } else
+		return $args;
+	}
+        
+	$args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1;
+        $args['status'] = true;
             
-            $args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1;
-            $args['path'] = $tmp_path;
-            $args['status'] = true;
-            
-            // Note the file for later cleanup
-            $_SESSION['plugins']['filesystem_attachments']['tmp_files'][] = $tmp_path;
-        }
+        // Note the file for later cleanup
+        $_SESSION['plugins']['filesystem_attachments']['tmp_files'][] = $args['path'];
 
         return $args;
     }
diff --git a/program/steps/mail/compose.inc b/program/steps/mail/compose.inc
index 99e925c..f8f7f08 100644
--- a/program/steps/mail/compose.inc
+++ b/program/steps/mail/compose.inc
@@ -601,7 +601,7 @@
 function rcmail_write_compose_attachments(&$message, $bodyIsHtml)
 {
   global $OUTPUT;
-  
+echo "^^^^^";  
   $cid_map = array();
   foreach ((array)$message->mime_parts as $pid => $part)
   {
@@ -643,20 +643,41 @@
 function rcmail_save_attachment(&$message, $pid)
 {
   $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
+  $data = $path = null;
+
+  // 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')) {
+      $message->get_part_content($pid, $fp);
+      fclose($fp);
+    } else
+      return false;
+  } else {
+    $data = $message->get_part_content($pid);
+  }
+
   $attachment = array(
     'name' => $part->filename ? $part->filename : 'Part_'.$pid.'.'.$part->ctype_secondary,
     'mimetype' => $part->ctype_primary . '/' . $part->ctype_secondary,
     'content_id' => $part->content_id,
-    'data' => $message->get_part_content($pid),
+    'data' => $data,
+    'path' => $path
   );
   
   $attachment = rcmail::get_instance()->plugins->exec_hook('save_attachment', $attachment);
+
   if ($attachment['status']) {
     unset($attachment['data'], $attachment['status']);
     return $attachment;
+  } else if ($path) {
+    @unlink($path);
   }
-
+  
   return false;
 }
 

--
Gitblit v1.9.1