diff --git a/mail/inc/class.mail_ui.inc.php b/mail/inc/class.mail_ui.inc.php index b9c61ae2fb..cc483c4159 100644 --- a/mail/inc/class.mail_ui.inc.php +++ b/mail/inc/class.mail_ui.inc.php @@ -2343,9 +2343,6 @@ $filter['before']= date("d-M-Y", $cutoffdate2); } if (is_array($attachments) && count($attachments) > 0) { - $url_img_vfs = Api\Html::image('filemanager','navbar', lang('Filemanager'), ' height="16"'); - $url_img_vfs_save_all = Api\Html::image('mail','save_all', lang('Save all')); - foreach ($attachments as $key => $value) { if (Mail\Smime::isSmime($value['mimeType'])) continue; @@ -2770,36 +2767,62 @@ $filter['before']= date("d-M-Y", $cutoffdate2); } /** - * Ajax function to save message(s) in the vfs + * Ajax function to save message(s)/attachment(s) in the vfs * - * @param array $ids array of mail ids + * @param array $params array of mail ids and action name + * params = array ( + * ids => array of string + * action => string + * ) * @param string $path path to save the emails */ - function ajax_vfsSaveMessage ($ids,$path) + function ajax_vfsSave ($params,$path) { - $result = $this->vfsSaveMessage($ids, $path); $response = Api\Json\Response::get(); - $response->data($result); + + switch ($params['action']) + { + case 'message': + $result = $this->vfsSaveMessages($params['ids'], $path); + break; + case 'attachment': + $result = $this->vfsSaveAttachments($params['ids'], $path); + break; + } + $response->call('app.mail.vfsSaveCallback', $result); } /** - * Save an Message in the vfs + * Save Message(s) in the vfs * * @param string|array $ids use splitRowID, to separate values * @param string $path path in vfs (no Vfs::PREFIX!), only directory for multiple id's ($ids is an array) - * @return string|boolean javascript eg. to close the selector window if $close is true, or success/fail if $close is false + * + * @return array returns an array including message and success result + * array ( + * 'msg' => STRING, + * 'success' => BOOLEAN + * ) */ - function vfsSaveMessage($ids,$path) + function vfsSaveMessages($ids,$path) { - //error_log(__METHOD__.' IDs:'.array2string($ids).' SaveToPath:'.$path); - - if (is_array($ids) && !Vfs::is_writable($path) || !is_array($ids) && !Vfs::is_writable(dirname($path))) - { - return 'alert("'.addslashes(lang('%1 is NOT writable by you!',$path)).'"); Egw(window).close();'; - } + // add mail translation Api\Translation::add_app('mail'); + $res = array (); - $rememberServerID = $this->mail_bo->profileID; + // extract dir from the path + $dir = Vfs::is_dir($path) ? $path : Vfs::dirname($path); + + // exit if user has no right to the dir + if (!Vfs::is_writable($dir)) + { + return array ( + 'msg' => lang('%1 is NOT writable by you!',$path), + 'success' => false + ); + } + + $preservedServerID = $this->mail_bo->profileID; foreach((array)$ids as $id) { $hA = self::splitRowID($id); @@ -2808,31 +2831,44 @@ $filter['before']= date("d-M-Y", $cutoffdate2); $icServerID = $hA['profileID']; if ($icServerID && $icServerID != $this->mail_bo->profileID) { - //error_log(__METHOD__.__LINE__.' change Profile to ->'.$icServerID); $this->changeProfile($icServerID); } $message = $this->mail_bo->getMessageRawBody($uid, $partID='', $mailbox); - $err=null; - if(Vfs::is_dir($path)) + + // is multiple messages + if (Vfs::is_dir($path)) { $headers = $this->mail_bo->getMessageHeader($uid,$partID,true,false,$mailbox); - $file = $path . '/'.preg_replace('/[\f\n\t\v\\:*#?<>\|]/',"_",$headers['SUBJECT']).'.eml'; + $file = $dir . '/'.preg_replace('/[\f\n\t\v\\:*#?<>\|]/',"_",$headers['SUBJECT']).'.eml'; } else { $file = $path; } + + // Check if file already exists, then try to assign a none existance filename + $counter = 1; + $tmp_file = $file; + while (Vfs::file_exists($tmp_file)) + { + $tmp_file = $file; + $pathinfo = pathinfo(Vfs::basename($tmp_file)); + $tmp_file = $dir . '/' . $pathinfo['filename'] . '(' . $counter . ')' . '.' . $pathinfo['extension']; + $counter++; + } + $file = $tmp_file; + if (!($fp = Vfs::fopen($file,'wb')) || !fwrite($fp,$message)) { - $err .= lang('Error saving %1!',$file); - $succeeded = false; + $res['msg'] = lang('Error saving %1!',$file); + $res['success'] = false; } else { - $succeeded = true; + $res['success'] = true; } if ($fp) fclose($fp); - if ($succeeded) + if ($res['success']) { unset($headers['SUBJECT']);//already in filename $infoSection = Mail::createHeaderInfoSection($headers, 'SUPPRESS', false); @@ -2840,45 +2876,44 @@ $filter['before']= date("d-M-Y", $cutoffdate2); Vfs::proppatch($file,$props); } } - if ($rememberServerID != $this->mail_bo->profileID) + if ($preservedServerID != $this->mail_bo->profileID) { - //error_log(__METHOD__.__LINE__.' change Profile back to where we came from ->'.$rememberServerID); - $this->changeProfile($rememberServerID); + //change Profile back to where we came from + $this->changeProfile($preservedServerID); } - - return $succeeded; + return $res; } /** - * Ajax function to store attachments in the vfs - * @param string|array $ids '::' delimited mailbox::uid::part-id::is_winmail::name (::name for multiple id's) - * @param string $path path in vfs (no Vfs::PREFIX!), only directory for multiple id's ($ids is an array) - */ - function ajax_vfsSaveAttachment($ids,$path) - { - $result = $this->vfsSaveAttachment($ids, $path); - $response = Api\Json\Response::get(); - $response->data($result); - } - - /** - * Save an attachment in the vfs + * Save attachment(s) in the vfs * * @param string|array $ids '::' delimited mailbox::uid::part-id::is_winmail::name (::name for multiple id's) * @param string $path path in vfs (no Vfs::PREFIX!), only directory for multiple id's ($ids is an array) - * @return string javascript eg. to close the selector window + * + * @return array returns an array including message and success result + * array ( + * 'msg' => STRING, + * 'success' => BOOLEAN + * ) */ - function vfsSaveAttachment($ids,$path) + function vfsSaveAttachments($ids,$path) { - //error_log(__METHOD__.__LINE__.'("'.array2string($ids).'","'.$path."\")');"); + $res = array ( + 'msg' => 'Attachment has been saved successfully.', + 'success' => true + ); - if (is_array($ids) && !Vfs::is_writable($path) || !is_array($ids) && !Vfs::is_writable(dirname($path))) + $dir = Vfs::is_dir($path) ? $path : Vfs::dirname($path); + + if (!Vfs::is_writable($dir)) { - return 'alert("'.addslashes(lang('%1 is NOT writable by you!',$path)).'"); Egw(window).close();'; + return array ( + 'msg' => lang('%1 is NOT writable by you!',$path), + 'success' => false + ); } - $err=null; - $dupe_count = array(); - $rememberServerID = $this->mail_bo->profileID; + + $preservedServerID = $this->mail_bo->profileID; /** * Extract all parameteres from the given id @@ -2903,7 +2938,6 @@ $filter['before']= date("d-M-Y", $cutoffdate2); //Examine the first attachment to see if attachment //is winmail.dat embedded attachments. - $isMultipleDownload=is_array($ids); $p = $getParams((is_array($ids)?$ids[0]:$ids)); if ($p['is_winmail']) { @@ -2921,21 +2955,27 @@ $filter['before']= date("d-M-Y", $cutoffdate2); foreach((array)$ids as $id) { $params = $getParams($id); - // when downloading a single file, name is not set - if (!$params['name']&&isset($_GET['name'])&&!$isMultipleDownload) $params['name'] = $_GET['name']; + if ($params['icServer'] && $params['icServer'] != $this->mail_bo->profileID) { - //error_log(__METHOD__.__LINE__.' change Profile to ->'.$icServerID); $this->changeProfile($params['icServer']); } - //error_log(__METHOD__.__LINE__.array2string($hA)); $this->mail_bo->reopen($params['mailbox']); - if ($params['is_winmail']) + + // is multiple attachments + if (Vfs::is_dir($path) || $params['is_winmail']) { - // Try to find the right content for file id - foreach ($attachments as $key => $val) + if ($params['is_winmail']) { - if ($key == $params['is_winmail']) $attachment = $val; + // 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); } } else @@ -2943,35 +2983,39 @@ $filter['before']= date("d-M-Y", $cutoffdate2); $attachment = $this->mail_bo->getAttachment($params['uid'],$params['part'],$params['is_winmail'],false); } - $file = $params['name']; - // when $isMultipleDownload the path holds no filename - while(Vfs::file_exists($path.($file && $isMultipleDownload ? '/'.$file : ''))) + $file = $dir. '/' . $attachment['filename']; + + $counter = 1; + $tmp_file = $file; + while (Vfs::file_exists($tmp_file)) { - $dupe_count[$params['name']]++; - $file = pathinfo($params['name'], PATHINFO_FILENAME) . - ' ('.($dupe_count[$params['name']] + 1).')' . '.' . - pathinfo($params['name'], PATHINFO_EXTENSION); + $tmp_file = $file; + $pathinfo = pathinfo(Vfs::basename($tmp_file)); + $tmp_file = $dir . '/' . $pathinfo['filename'] . '(' . $counter . ')' . '.' . $pathinfo['extension']; + $counter++; } - $params['name'] = $file; - //error_log(__METHOD__.__LINE__.array2string($attachment)); - // when $isMultipleDownload the path holds no filename - if (!($fp = Vfs::fopen($file=$path.($params['name'] && $isMultipleDownload ? '/'.$params['name'] : ''),'wb')) || + $file = $tmp_file; + + if (!($fp = Vfs::fopen($file,'wb')) || !fwrite($fp,$attachment['attachment'])) { - $err .= lang('Error saving %1!',$file); + $res['msg'] = lang('Error saving %1!',$file); + $res['success'] = false; } if ($fp) { fclose($fp); } } + $this->mail_bo->closeConnection(); - if ($rememberServerID != $this->mail_bo->profileID) + + if ($preservedServerID != $this->mail_bo->profileID) { - //error_log(__METHOD__.__LINE__.' change Profile back to where we came from ->'.$rememberServerID); - $this->changeProfile($rememberServerID); + //change Profile back to where we came from + $this->changeProfile($preservedServerID); } - Framework::window_close(($err?$err:null)); + return $res; } /** diff --git a/mail/js/app.js b/mail/js/app.js index dc98bed4b4..15f02808ff 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -2893,113 +2893,79 @@ app.classes.mail = AppJS.extend( egw.openPopup(egw.link('/index.php', get_param), width, height, windowName); }, - saveAttachment: function(tag_info, widget) + /** + * Callback function to handle vfsSave response messages + * + * @param {type} _data + */ + vfsSaveCallback: function (_data) { - var mailid; - var attgrid; - if (this.mail_isMainWindow) - { - mailid = this.mail_currentlyFocussed;//this.et2.getArrayMgr("content").getEntry('mail_id'); - var p = widget.getParent(); - var cont = p.getArrayMgr("content").data; - attgrid = cont[widget.id.replace(/\[save\]/,'')]; - } - else - { - mailid = this.et2.getArrayMgr("content").getEntry('mail_id'); - attgrid = this.et2.getArrayMgr("content").getEntry('mail_displayattachments')[widget.id.replace(/\[save\]/,'')]; - } - var url = window.egw_webserverUrl+'/index.php?'; - url += 'menuaction=mail.mail_ui.getAttachment'; // todo compose for Draft folder - url += '&mode=save'; - url += '&id='+mailid; - url += '&part='+attgrid.partID; - url += '&is_winmail='+attgrid.winmailFlag; - url += '&smime_type='+ (attgrid.smime_type?attgrid.smime_type:''); - this.et2._inst.download(url); + egw.message(_data.msg, _data.success ? "success": "error"); }, - saveAllAttachmentsToZip: function(tag_info, widget) + /** + * A handler for saving to VFS/downloading attachments + * + * @param {type} widget + * @param {type} action + * @param {type} row_id + */ + saveAttachmentHandler: function (widget, action, row_id) { - var mailid; - var attgrid; + var mail_id, attachments; + if (this.mail_isMainWindow) { - mailid = this.mail_currentlyFocussed;//this.et2.getArrayMgr("content").getEntry('mail_id'); + mail_id = this.mail_currentlyFocussed; var p = widget.getParent(); - var cont = p.getArrayMgr("content").data; - attgrid = cont[widget.id.replace(/\[save_zip\]/,'')]; + attachments = p.getArrayMgr("content").data; } else { - mailid = this.et2.getArrayMgr("content").getEntry('mail_id'); - attgrid = this.et2.getArrayMgr("content").getEntry('mail_displayattachments')[widget.id.replace(/\[save\]/,'')]; - } - var url = window.egw_webserverUrl+'/index.php?'; - url += 'menuaction=mail.mail_ui.download_zip'; // todo compose for Draft folder - url += '&mode=save'; - url += '&id='+mailid; - url += '&smime_type='+ (attgrid.smime_type?attgrid.smime_type:''); - this.et2._inst.download(url); - }, - - saveAttachmentToVFS: function(tag_info, widget) - { - var mailid; - var attgrid; - if (this.mail_isMainWindow) - { - mailid = this.mail_currentlyFocussed;//this.et2.getArrayMgr("content").getEntry('mail_id'); - var p = widget.getParent(); - var cont = p.getArrayMgr("content").data; - attgrid = cont[widget.id.replace(/\[saveAsVFS\]/,'')]; - } - else - { - mailid = this.et2.getArrayMgr("content").getEntry('mail_id'); - attgrid = this.et2.getArrayMgr("content").getEntry('mail_displayattachments')[widget.id.replace(/\[saveAsVFS\]/,'')]; - } - var vfs_select = et2_createWidget('vfs-select', { - mode: 'saveas', - method: 'mail.mail_ui.ajax_vfsSaveAttachment', - button_label: egw.lang('Save'), - dialog_title: "Save attchment", - method_id: mailid+'::'+attgrid.partID+'::'+attgrid.winmailFlag, - name: attgrid.filename - }); - vfs_select.click(); - }, - - saveAllAttachmentsToVFS: function(tag_info, widget) - { - var mailid; - var attgrid; - if (this.mail_isMainWindow) - { - mailid = this.mail_currentlyFocussed;//this.et2.getArrayMgr("content").getEntry('mail_id'); - var p = widget.getParent(); - attgrid = p.getArrayMgr("content").data; - } - else - { - mailid = this.et2.getArrayMgr("content").getEntry('mail_id'); - attgrid = this.et2.getArrayMgr("content").getEntry('mail_displayattachments'); + mail_id = this.et2.getArrayMgr("content").getEntry('mail_id'); + attachments = this.et2.getArrayMgr("content").getEntry('mail_displayattachments'); } - var ids = []; - for (var i=0;i 1 ? {ids:ids, action:'attachment'} : {ids: ids[0], action: 'attachment'}, + name: action === 'saveOneToVfs' ? attachments[0]['filename'] : null + }); + vfs_select.click(); + break; - var vfs_select = et2_createWidget('vfs-select', { - mode: 'select-dir', - method: 'mail.mail_ui.ajax_vfsSaveAttachment', - button_label: egw.lang('Save all'), - dialog_title: "Save attchments", - method_id: ids.length > 1 ? ids: ids[0] - }); - vfs_select.click(); + case 'downloadOneAsFile': + case 'downloadAllToZip': + var attachment = attachments[row_id]; + var url = window.egw_webserverUrl+'/index.php?'; + url += jQuery.param({ + menuaction: action === 'downloadOneAsFile' ? + 'mail.mail_ui.getAttachment' : 'mail.mail_ui.download_zip', + mode: 'save', + id: mail_id, + part: attachment.partID, + is_winmail: attachment.winmailFlag, + smime_type: (attachment.smime_type ? attachment.smime_type : '') + }); + this.et2._inst.download(url); + break; + } }, /** @@ -3039,10 +3005,10 @@ app.classes.mail = AppJS.extend( var vfs_select = et2_createWidget('vfs-select', { mode: _elems.length > 1 ? 'select-dir' : 'saveas', mime: 'message/rfc822', - method: 'mail.mail_ui.ajax_vfsSaveMessage', + method: 'mail.mail_ui.ajax_vfsSave', button_label: _elems.length>1 ? egw.lang('Save all') : egw.lang('save'), dialog_title: "Save email", - method_id: _elems.length > 1 ? ids: ids[0], + method_id: _elems.length > 1 ? {ids:ids, action:'message'}: {ids: ids[0], action: 'message'}, name: _elems.length > 1 ? names : names[0], }); vfs_select.click(); diff --git a/mail/templates/default/display.xet b/mail/templates/default/display.xet index 8b7156b440..66553808f4 100644 --- a/mail/templates/default/display.xet +++ b/mail/templates/default/display.xet @@ -78,10 +78,10 @@ - - - - + + + + diff --git a/mail/templates/default/index.xet b/mail/templates/default/index.xet index 6674d9681e..74922ea872 100644 --- a/mail/templates/default/index.xet +++ b/mail/templates/default/index.xet @@ -62,10 +62,10 @@ - - - - + + + +