Skip to content

Commit

Permalink
Resolve #717
Browse files Browse the repository at this point in the history
  • Loading branch information
the-djmaze committed Nov 29, 2022
1 parent 4ebde92 commit 0863976
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 176 deletions.
36 changes: 33 additions & 3 deletions dev/View/User/MailBox/MessageList.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { leftPanelDisabled, toggleLeftPanel,
addShortcut, registerShortcut, formFieldFocused
} from 'Common/Globals';

import { arrayLength } from 'Common/Utils';
import { computedPaginatorHelper, showMessageComposer, populateMessageBody, download, moveAction } from 'Common/UtilsUser';
import { FileInfo } from 'Common/File';
import { isFullscreen, toggleFullscreen } from 'Common/Fullscreen';
Expand Down Expand Up @@ -102,6 +103,9 @@ export class MailMessageList extends AbstractViewRight {
this.dragOver = ko.observable(false).extend({ throttle: 1 });
this.dragOverEnter = ko.observable(false).extend({ throttle: 1 });

const attachmentsActions = Settings.app('attachmentsActions');
this.attachmentsActions = ko.observableArray(arrayLength(attachmentsActions) ? attachmentsActions : []);

addComputablesTo(this, {

sortSupported: () =>
Expand Down Expand Up @@ -148,7 +152,9 @@ export class MailMessageList extends AbstractViewRight {
return '𝐒' + (desc ? '⬆' : '⬇');
}
return (mode.includes('SIZE') ? '✉' : '📅') + (desc ? '⬇' : '⬆');
}
},

downloadAsZipAllowed: () => this.attachmentsActions.includes('zip')
});

this.selector = new Selector(
Expand Down Expand Up @@ -259,7 +265,8 @@ export class MailMessageList extends AbstractViewRight {
).throttle(50));

decorateKoCommands(this, {
downloadCommand: canBeMovedHelper,
downloadAttachCommand: canBeMovedHelper,
downloadZipCommand: canBeMovedHelper,
forwardCommand: canBeMovedHelper,
deleteWithoutMoveCommand: canBeMovedHelper,
deleteCommand: canBeMovedHelper,
Expand Down Expand Up @@ -292,7 +299,30 @@ export class MailMessageList extends AbstractViewRight {
]);
}

downloadCommand() {
downloadZipCommand() {
let hashes = []/*, uids = []*/;
// MessagelistUserStore.forEach(message => message.checked() && uids.push(message.uid));
MessagelistUserStore.forEach(message => message.checked() && hashes.push(message.requestHash));
if (hashes.length) {
Remote.post('AttachmentsActions', null, {
Do: 'Zip',
Folder: MessagelistUserStore().Folder,
// Uids: uids,
Hashes: hashes
})
.then(result => {
let hash = result?.Result?.FileHash;
if (hash) {
download(attachmentDownload(hash), hash+'.zip');
} else {
alert('Download failed');
}
})
.catch(() => alert('Download failed'));
}
}

downloadAttachCommand() {
let hashes = [];
MessagelistUserStore.forEach(message => {
if (message.checked()) {
Expand Down
179 changes: 179 additions & 0 deletions snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Attachments.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,179 @@
<?php

namespace RainLoop\Actions;

use RainLoop\Enumerations\Capa;
use RainLoop\Utils;

trait Attachments
{
/**
* @throws \MailSo\RuntimeException
*/
public function DoAttachmentsActions() : array
{
$sAction = $this->GetActionParam('Do', '');
$sFolder = $this->GetActionParam('Folder', '');
$aHashes = $this->GetActionParam('Hashes', null);
$oFilesProvider = $this->FilesProvider();
if (empty($sAction) || !$this->GetCapa(Capa::ATTACHMENTS_ACTIONS) || !$oFilesProvider || !$oFilesProvider->IsActive()) {
return $this->FalseResponse(__FUNCTION__);
}

$oAccount = $this->initMailClientConnection();

$bError = false;
$aData = [];
$mUIDs = [];

if (\is_array($aHashes) && \count($aHashes)) {
foreach ($aHashes as $sZipHash) {
$aResult = $this->getMimeFileByHash($oAccount, $sZipHash);
if (empty($aResult['FileHash'])) {
$bError = true;
break;
}
$aData[] = $aResult;
if (!empty($aResult['MimeIndex'])) {
$mUIDs[$aResult['Uid']] = $aResult['Uid'];
}
}
}
$mUIDs = 1 < \count($mUIDs);

if ($bError || !\count($aData)) {
return $this->FalseResponse(__FUNCTION__);
}

$mResult = false;
switch (\strtolower($sAction))
{
case 'zip':

$sZipHash = \MailSo\Base\Utils::Sha1Rand();
$sZipFileName = $oFilesProvider->GenerateLocalFullFileName($oAccount, $sZipHash);

if (!empty($sZipFileName)) {
if (\class_exists('ZipArchive')) {
$oZip = new \ZipArchive();
$oZip->open($sZipFileName, \ZIPARCHIVE::CREATE | \ZIPARCHIVE::OVERWRITE);
$oZip->setArchiveComment('SnappyMail/'.APP_VERSION);
foreach ($aData as $aItem) {
$sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $aItem['FileHash']);
$sFileName = ($mUIDs ? "{$aItem['Uid']}/" : ($sFolder ? "{$aItem['Uid']}-" : '')) . $aItem['FileName'];
if (!$oZip->addFile($sFullFileNameHash, $sFileName)) {
$bError = true;
}
}

if ($bError) {
$oZip->close();
} else {
$bError = !$oZip->close();
}
/*
} else {
@\unlink($sZipFileName);
$oZip = new \SnappyMail\Stream\ZIP($sZipFileName);
// $oZip->setArchiveComment('SnappyMail/'.APP_VERSION);
foreach ($aData as $aItem) {
if ($aItem['FileHash']) {
$sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $aItem['FileHash']);
if (!$oZip->addFile($sFullFileNameHash, $aItem['FileName'])) {
$bError = true;
}
}
}
$oZip->close();
*/
} else {
@\unlink($sZipFileName);
$oZip = new \PharData($sZipFileName . '.zip', 0, null, \Phar::ZIP);
$oZip->compressFiles(\Phar::GZ);
foreach ($aData as $aItem) {
$oZip->addFile(
$oFilesProvider->GetFileName($oAccount, $aItem['FileHash']),
($mUIDs ? "{$aItem['Uid']}/" : ($sFolder ? "{$aItem['Uid']}-" : '')) . $aItem['FileName']
);
}
$oZip->compressFiles(\Phar::GZ);
unset($oZip);
\rename($sZipFileName . '.zip', $sZipFileName);
}

foreach ($aData as $aItem) {
$oFilesProvider->Clear($oAccount, $aItem['FileHash']);
}

if (!$bError) {
$mResult = array(
'FileHash' => Utils::EncodeKeyValuesQ(array(
'Account' => $oAccount ? $oAccount->Hash() : '',
'FileName' => ($sFolder ? 'messages' : 'attachments') . \date('-YmdHis') . '.zip',
'MimeType' => 'application/zip',
'FileHash' => $sZipHash
))
);
}
}
break;

default:
$data = new \SnappyMail\AttachmentsAction;
$data->action = $sAction;
$data->items = $aData;
$data->filesProvider = $oFilesProvider;
$data->account = $oAccount;
$this->Plugins()->RunHook('json.attachments', array($data));
$mResult = $data->result;
break;
}

// $this->requestSleep();
return $this->DefaultResponse(__FUNCTION__, $bError ? false : $mResult);
}

private function getMimeFileByHash(\RainLoop\Model\Account $oAccount, string $sHash) : array
{
$aValues = $this->getDecodedRawKeyValue($sHash);

$sFolder = isset($aValues['Folder']) ? (string) $aValues['Folder'] : '';
$iUid = isset($aValues['Uid']) ? (int) $aValues['Uid'] : 0;
$sMimeIndex = isset($aValues['MimeIndex']) ? (string) $aValues['MimeIndex'] : '';

$sContentTypeIn = isset($aValues['MimeType']) ? (string) $aValues['MimeType'] : '';
$sFileNameIn = isset($aValues['FileName']) ? (string) $aValues['FileName'] : 'file.dat';

$oFileProvider = $this->FilesProvider();

$sResultHash = '';

$mResult = $this->MailClient()->MessageMimeStream(function ($rResource, $sContentType, $sFileName, $sMimeIndex = '')
use ($oAccount, $oFileProvider, $sFileNameIn, $sContentTypeIn, &$sResultHash) {

unset($sContentType, $sFileName, $sMimeIndex);

if (\is_resource($rResource))
{
$sHash = \MailSo\Base\Utils::Sha1Rand($sFileNameIn.'~'.$sContentTypeIn);
$rTempResource = $oFileProvider->GetFile($oAccount, $sHash, 'wb+');

if (\is_resource($rTempResource))
{
if (false !== \MailSo\Base\Utils::MultipleStreamWriter($rResource, array($rTempResource)))
{
$sResultHash = $sHash;
}

\fclose($rTempResource);
}
}

}, $sFolder, $iUid, $sMimeIndex);

$aValues['FileName'] = $sFileNameIn;
$aValues['FileHash'] = $mResult ? $sResultHash : '';

return $aValues;
}
}
Loading

0 comments on commit 0863976

Please sign in to comment.