From 97d240fcab92b4c20116bd0316b807b53f27c70b Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Wed, 2 Dec 2015 11:10:26 +0000 Subject: [PATCH] W.I.P. of new approach for mail winmail.dat attachment handling - Restructure save attachments to vfs, and try to read the winmail.dat only once and store them all, as fetching content of winmail.dat is very expensive operation - Fix failure of save all embedded attachments into filemanager --- mail/inc/class.mail_ui.inc.php | 84 ++++++++++++++++++++++++++-------- 1 file changed, 64 insertions(+), 20 deletions(-) diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index 782613044b..46af02d962 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -2493,7 +2493,7 @@ class mail_ui function vfsSaveAttachment($ids,$path) { //error_log(__METHOD__.__LINE__.'("'.array2string($ids).'","'.$path."\")');"); - + if (is_array($ids) && !egw_vfs::is_writable($path) || !is_array($ids) && !egw_vfs::is_writable(dirname($path))) { return 'alert("'.addslashes(lang('%1 is NOT writable by you!',$path)).'"); egw(window).close();'; @@ -2501,34 +2501,79 @@ class mail_ui $err=null; $dupe_count = array(); $rememberServerID = $this->mail_bo->profileID; - foreach((array)$ids as $id) - { + + /** + * Extract all parameteres from the given id + * @param int $id message id ('::' delimited mailbox::uid::part-id::is_winmail::name) + * + * @return array an array of parameters + */ + $getParams = function ($id) { list($app,$user,$serverID,$mailbox,$uid,$part,$is_winmail,$name) = explode('::',$id,8); $lId = implode('::',array($app,$user,$serverID,$mailbox,$uid)); $hA = self::splitRowID($lId); - $uid = $hA['msgUID']; - $mailbox = $hA['folder']; - $icServerID = $hA['profileID']; - if ($icServerID && $icServerID != $this->mail_bo->profileID) + return array( + 'is_winmail' => $is_winmail == "null" || !$is_winmail?false:$is_winmail, + 'user' => $user, + 'name' => $name, + 'part' => $part, + 'uid' => $hA['msgUID'], + 'mailbox' => $hA['folder'], + 'icServer' => $hA['profileID'] + ); + }; + + //Examine the first attachment to see if attachment + //is winmail.dat embedded attachments. + $p = $getParams($ids[0]); + if ($p['is_winmail']) + { + if ($p['icServer'] && $p['icServer'] != $this->mail_bo->profileID) + { + $this->changeProfile($p['icServer']); + } + $this->mail_bo->reopen($p['mailbox']); + // Retrive all embedded attachments at once + // avoids to fetch heavy winmail.dat content + // for each file. + $attachments = $this->mail_bo->getTnefAttachments($p['uid'],$p['part']); + } + + foreach((array)$ids as $id) + { + $params = $getParams($id); + if ($params['icServer'] && $params['icServer'] != $this->mail_bo->profileID) { //error_log(__METHOD__.__LINE__.' change Profile to ->'.$icServerID); - $this->changeProfile($icServerID); + $this->changeProfile($params['icServer']); } //error_log(__METHOD__.__LINE__.array2string($hA)); - $this->mail_bo->reopen($mailbox); - $attachment = $this->mail_bo->getAttachment($uid,$part,$is_winmail,false); + $this->mail_bo->reopen($params['mailbox']); + + if ($params['is_winmail']) + { + // Try to find the right content for file id + foreach ($attachments as $key => $val) + { + if ($key == $params['is_winmail']) $attachment = $val; + } + } + else + { + $attachment = $this->mail_bo->getAttachment($params['uid'],$params['part'],$params['is_winmail'],false); + } - $file = $name; + $file = $params['name']; while(egw_vfs::file_exists($path.($file ? '/'.$file : ''))) { - $dupe_count[$name]++; - $file = pathinfo($name, PATHINFO_FILENAME) . - ' ('.($dupe_count[$name] + 1).')' . '.' . - pathinfo($name, PATHINFO_EXTENSION); + $dupe_count[$params['name']]++; + $file = pathinfo($params['name'], PATHINFO_FILENAME) . + ' ('.($dupe_count[$params['name']] + 1).')' . '.' . + pathinfo($params['name'], PATHINFO_EXTENSION); } - $name = $file; + $params['name'] = $file; //error_log(__METHOD__.__LINE__.array2string($attachment)); - if (!($fp = egw_vfs::fopen($file=$path.($name ? '/'.$name : ''),'wb')) || + if (!($fp = egw_vfs::fopen($file=$path.($params['name'] ? '/'.$params['name'] : ''),'wb')) || !fwrite($fp,$attachment['attachment'])) { $err .= lang('Error saving %1!',$file); @@ -2536,7 +2581,6 @@ class mail_ui if ($fp) { fclose($fp); - $file_list[] = $name; } } $this->mail_bo->closeConnection(); @@ -3660,7 +3704,7 @@ class mail_ui /** * ResolveWinmail fetches the encoded attachments - * from winmail.data and will response expected structure back + * from winmail.dat and will response expected structure back * to client in order to display them. * * Note: this ajax function should only be called via @@ -3686,7 +3730,7 @@ class mail_ui } else { - $response->call('egw.message', lang('Can not resolve the winmail.data attachment!')); + $response->call('egw.message', lang('Can not resolve the winmail.dat attachment!')); } }