diff --git a/dev/Model/Attachment.js b/dev/Model/Attachment.js index 834f2264b..93fbc42f4 100644 --- a/dev/Model/Attachment.js +++ b/dev/Model/Attachment.js @@ -126,7 +126,10 @@ export class AttachmentModel extends AbstractModel { } get download() { - return b64EncodeJSONSafe({ + return b64EncodeJSONSafe(this.url ? { + fileName: this.fileName, + data: this.url.replace(/^.+,/, '') + } : { folder: this.folder, uid: this.uid, mimeIndex: this.mimeIndex, diff --git a/dev/View/User/MailBox/MessageView.js b/dev/View/User/MailBox/MessageView.js index 8593e6055..bb31475fc 100644 --- a/dev/View/User/MailBox/MessageView.js +++ b/dev/View/User/MailBox/MessageView.js @@ -146,7 +146,7 @@ export class MailMessageView extends AbstractViewRight { downloadAsZipAllowed: () => this.attachmentsActions.includes('zip') && (currentMessage()?.attachments || []) - .filter(item => item?.download /*&& !item?.isLinked()*/ && item?.checked()) + .filter(item => item?.checked() && item?.download /*&& !item?.isLinked()*/) .length, tagsAllowed: () => FolderUserStore.currentFolder()?.tagsAllowed(), diff --git a/plugins/nextcloud/index.php b/plugins/nextcloud/index.php index 7dfabbacf..66ca84838 100644 --- a/plugins/nextcloud/index.php +++ b/plugins/nextcloud/index.php @@ -4,11 +4,11 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin { const NAME = 'Nextcloud', - VERSION = '2.33', - RELEASE = '2024-03-14', + VERSION = '2.34', + RELEASE = '2024-03-16', CATEGORY = 'Integrations', DESCRIPTION = 'Integrate with Nextcloud v20+', - REQUIRED = '2.35.3'; + REQUIRED = '2.35.4'; public function Init() : void { @@ -170,10 +170,14 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin $oFiles->is_dir($sSaveFolder) || $oFiles->mkdir($sSaveFolder); $data->result = true; foreach ($data->items as $aItem) { - $sSavedFileName = isset($aItem['fileName']) ? $aItem['fileName'] : 'file.dat'; - $sSavedFileHash = !empty($aItem['fileHash']) ? $aItem['fileHash'] : ''; - if (!empty($sSavedFileHash)) { - $fFile = $data->filesProvider->GetFile($data->account, $sSavedFileHash, 'rb'); + $sSavedFileName = empty($aItem['fileName']) ? 'file.dat' : $aItem['fileName']; + if (!empty($aItem['data'])) { + $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); + if (!$oFiles->file_put_contents($sSavedFileNameFull, $aItem['data'])) { + $data->result = false; + } + } else if (!empty($aItem['fileHash'])) { + $fFile = $data->filesProvider->GetFile($data->account, $aItem['fileHash'], 'rb'); if (\is_resource($fFile)) { $sSavedFileNameFull = static::SmartFileExists($sSaveFolder.'/'.$sSavedFileName, $oFiles); if (!$oFiles->file_put_contents($sSavedFileNameFull, $fFile)) { @@ -186,13 +190,6 @@ class NextcloudPlugin extends \RainLoop\Plugins\AbstractPlugin } } } - - foreach ($data->items as $aItem) { - $sFileHash = (string) (isset($aItem['fileHash']) ? $aItem['fileHash'] : ''); - if (!empty($sFileHash)) { - $data->filesProvider->Clear($data->account, $sFileHash); - } - } } } diff --git a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Attachments.php b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Attachments.php index 8647b6a0d..b8f2d2691 100644 --- a/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Attachments.php +++ b/snappymail/v/0.0.0/app/libraries/RainLoop/Actions/Attachments.php @@ -30,7 +30,7 @@ trait Attachments if (\is_array($aHashes) && \count($aHashes)) { foreach ($aHashes as $sZipHash) { $aResult = $this->getMimeFileByHash($oAccount, $sZipHash); - if (empty($aResult['fileHash'])) { + if (empty($aResult['data']) && empty($aResult['fileHash'])) { $bError = true; break; } @@ -60,10 +60,16 @@ trait Attachments $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 ($aItem['data']) { + if (!$oZip->addFromString($sFileName, $aItem['data'])) { + $bError = true; + } + } else { + $sFullFileNameHash = $oFilesProvider->GetFileName($oAccount, $aItem['fileHash']); + if (!$oZip->addFile($sFullFileNameHash, $sFileName)) { + $bError = true; + } } } @@ -92,20 +98,22 @@ trait Attachments $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'] - ); + if ($aItem['data']) { + if (!$oZip->addFromString($sFileName, \MailSo\Base\Utils::UrlSafeBase64Decode($aItem['data']))) { + $bError = true; + } + } else { + $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' => $this->encodeRawKey(array( @@ -129,46 +137,49 @@ trait Attachments break; } + foreach ($aData as $aItem) { + $aItem['fileHash'] && $oFilesProvider->Clear($oAccount, $aItem['fileHash']); + } + return $this->DefaultResponse($bError ? false : $mResult); } private function getMimeFileByHash(\RainLoop\Model\Account $oAccount, string $sHash) : array { $aValues = $this->decodeRawKey($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 (-1 < \MailSo\Base\Utils::WriteStream($rResource, $rTempResource)) { - $sResultHash = $sHash; + $aValues['fileName'] = empty($aValues['fileName']) ? 'file.dat' : (string) $aValues['fileName']; + $aValues['fileHash'] = null; + if (isset($aValues['data'])) { + $aValues['data'] = \MailSo\Base\Utils::UrlSafeBase64Decode($aValues['data']); + } else { + $sFolder = isset($aValues['folder']) ? (string) $aValues['folder'] : ''; + $iUid = isset($aValues['uid']) ? (int) $aValues['uid'] : 0; + $sMimeIndex = isset($aValues['mimeIndex']) ? (string) $aValues['mimeIndex'] : ''; + if ($sFolder && $iUid && $sMimeIndex) { + $oFileProvider = $this->FilesProvider(); + $mResult = $this->MailClient()->MessageMimeStream( + function ($rResource, $sContentType, $sFileName, $sMimeIndex = '') + use ($oAccount, $oFileProvider, &$aValues) { + unset($sContentType, $sFileName, $sMimeIndex); + if (\is_resource($rResource)) { + $sContentTypeIn = isset($aValues['mimeType']) ? (string) $aValues['mimeType'] : ''; + $sHash = \MailSo\Base\Utils::Sha1Rand($aValues['fileName'].'~'.$sContentTypeIn); + $rTempResource = $oFileProvider->GetFile($oAccount, $sHash, 'wb+'); + if (\is_resource($rTempResource)) { + if (-1 < \MailSo\Base\Utils::WriteStream($rResource, $rTempResource)) { + $sResultHash = $sHash; + $aValues['fileHash'] = $sHash; + } + \fclose($rTempResource); + } } - - \fclose($rTempResource); - } - } - - }, $sFolder, $iUid, $sMimeIndex); - - $aValues['fileName'] = $sFileNameIn; - $aValues['fileHash'] = $mResult ? $sResultHash : ''; + }, + $sFolder, + $iUid, + $sMimeIndex + ); + } + } return $aValues; }