plugins/libkolab
Aleksander Machniak
machniak at kolabsys.com
Mon Nov 19 15:00:14 CET 2012
plugins/libkolab/lib/kolab_storage_folder.php | 74 ++++++++++++++++++++++----
1 file changed, 65 insertions(+), 9 deletions(-)
New commits:
commit 57f1d89fccc2df461a382e75123fbfff20bb0b66
Author: Aleksander Machniak <machniak at kolabsys.com>
Date: Mon Nov 19 14:58:36 2012 +0100
Implemented messages write handling with temp files
diff --git a/plugins/libkolab/lib/kolab_storage_folder.php b/plugins/libkolab/lib/kolab_storage_folder.php
index 2c58973..89b2b99 100644
--- a/plugins/libkolab/lib/kolab_storage_folder.php
+++ b/plugins/libkolab/lib/kolab_storage_folder.php
@@ -602,7 +602,13 @@ class kolab_storage_folder
}
if ($raw_msg = $this->build_message($object, $type)) {
- $result = $this->imap->save_message($this->name, $raw_msg, '', false);
+ if (is_array($raw_msg)) {
+ $result = $this->imap->save_message($this->name, $raw_msg[0], $raw_msg[1], true);
+ @unlink($raw_msg[0]);
+ }
+ else {
+ $result = $this->imap->save_message($this->name, $raw_msg);
+ }
// delete old message
if ($result && !empty($object['_msguid']) && !empty($object['_mailbox'])) {
@@ -620,7 +626,7 @@ class kolab_storage_folder
$this->cache->insert($result, $object);
}
}
-
+
return $result;
}
@@ -710,6 +716,9 @@ class kolab_storage_folder
/**
* Creates source of the configuration object message
+ *
+ * @return mixed Message as string or array with two elements
+ * (one for message file path, second for message headers)
*/
private function build_message(&$object, $type)
{
@@ -735,8 +744,8 @@ class kolab_storage_folder
return false;
}
- $mime = new Mail_mime("\r\n");
- $rcmail = rcube::get_instance();
+ $mime = new Mail_mime("\r\n");
+ $rcmail = rcube::get_instance();
$headers = array();
$part_id = 1;
@@ -751,12 +760,33 @@ class kolab_storage_folder
// $headers['Message-ID'] = $rcmail->gen_message_id();
$headers['User-Agent'] = $rcmail->config->get('useragent');
+ // Check if we have enough memory to handle the message in it
+ // It's faster than using files, so we'll do this if we only can
+ if (!empty($object['_attachments']) && ($mem_limit = parse_bytes(ini_get('memory_limit'))) > 0) {
+ $memory = function_exists('memory_get_usage') ? memory_get_usage() : 16*1024*1024; // safe value: 16MB
+
+ foreach ($object['_attachments'] as $id => $attachment) {
+ $memory += $attachment['size'];
+ }
+
+ // 1.33 is for base64, we need at least 2x more memory than the message size
+ if ($memory * 1.33 * 2 > $mem_limit) {
+ $is_file = true;
+ $temp_dir = unslashify($rcmail->config->get('temp_dir'));
+ $mime->setParam('delay_file_io', true);
+ }
+ }
+
$mime->headers($headers);
- $mime->setTXTBody('This is a Kolab Groupware object. '
- . 'To view this object you will need an email client that understands the Kolab Groupware format. '
+ $mime->setTXTBody("This is a Kolab Groupware object. "
+ . "To view this object you will need an email client that understands the Kolab Groupware format. "
. "For a list of such email clients please visit http://www.kolab.org/\n\n");
$ctype = kolab_storage::$version == 2.0 ? $format->CTYPEv2 : $format->CTYPE;
+ // Convert new lines to \r\n, to wrokaround "NO Message contains bare newlines"
+ // when APPENDing from temp file
+ $xml = preg_replace('/\r?\n/', "\r\n", $xml);
+
$mime->addAttachment($xml, // file
$ctype, // content-type
'kolab.xml', // filename
@@ -768,11 +798,21 @@ class kolab_storage_folder
$part_id++;
// save object attachments as separate parts
- // TODO: optimize memory consumption by using tempfiles for transfer
foreach ((array)$object['_attachments'] as $key => $att) {
if (empty($att['content']) && !empty($att['id'])) {
$msguid = !empty($object['_msguid']) ? $object['_msguid'] : $object['uid'];
- $att['content'] = $this->get_attachment($msguid, $att['id'], $object['_mailbox']);
+ if ($is_file) {
+ $att['path'] = tempnam($temp_dir, 'rcmAttmnt');
+ if (($fp = fopen($att['path'], 'w')) && $this->get_attachment($msguid, $att['id'], $object['_mailbox'], false, $fp)) {
+ fclose($fp);
+ }
+ else {
+ return false;
+ }
+ }
+ else {
+ $att['content'] = $this->get_attachment($msguid, $att['id'], $object['_mailbox']);
+ }
}
$headers = array('Content-ID' => Mail_mimePart::encodeHeader('Content-ID', '<' . $key . '>', RCMAIL_CHARSET, 'quoted-printable'));
@@ -790,7 +830,23 @@ class kolab_storage_folder
$object['_attachments'][$key]['id'] = $part_id;
}
- return $mime->getMessage();
+ if ($is_file) {
+ // use common temp dir
+ $body_file = tempnam($temp_dir, 'rcmMsg');
+
+ if (PEAR::isError($mime_result = $mime->saveMessageBody($body_file))) {
+ self::raise_error(array('code' => 650, 'type' => 'php',
+ 'file' => __FILE__, 'line' => __LINE__,
+ 'message' => "Could not create message: ".$mime_result->getMessage()),
+ true, false);
+ return false;
+ }
+
+ return array($body_file, $mime->txtHeaders());
+ }
+ else {
+ return $mime->getMessage();
+ }
}
More information about the commits
mailing list