From a640647edd0776555b9d2083fd968b2317143c8c Mon Sep 17 00:00:00 2001 From: alecpl Date: Sun, 19 Jul 2009 09:28:30 +0000 Subject: - handle big attachments with file pointers to not exceed memory_limit in rcmail_save_attachment() --- .../database_attachments/database_attachments.php | 4 +++ .../filesystem_attachments.php | 32 ++++++++++++---------- program/steps/mail/compose.inc | 29 +++++++++++++++++--- 3 files changed, 47 insertions(+), 18 deletions(-) diff --git a/plugins/database_attachments/database_attachments.php b/plugins/database_attachments/database_attachments.php index 28ccde4b3..a8ac62e26 100644 --- a/plugins/database_attachments/database_attachments.php +++ b/plugins/database_attachments/database_attachments.php @@ -63,6 +63,10 @@ class database_attachments extends filesystem_attachments $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 9a6c0a81d..f4b9b6d7d 100644 --- a/plugins/filesystem_attachments/filesystem_attachments.php +++ b/plugins/filesystem_attachments/filesystem_attachments.php @@ -73,21 +73,25 @@ class filesystem_attachments extends rcube_plugin 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 ($fp = fopen($tmp_path, 'w')) { - fwrite($fp, $args['data']); - fclose($fp); + + 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); + $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 99e925cdb..f8f7f08dd 100644 --- a/program/steps/mail/compose.inc +++ b/program/steps/mail/compose.inc @@ -601,7 +601,7 @@ function rcmail_create_draft_body($body, $bodyIsHtml) 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_write_inline_attachments(&$message) 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; } -- cgit v1.2.3