mirror of
https://github.com/the-djmaze/snappymail.git
synced 2026-08-31 21:19:21 +03:00
Redesign Raw handling as encodeRawKey/decodeRawKey doesn't need encryption
This commit is contained in:
parent
402de0d569
commit
bd7f9856f2
8 changed files with 73 additions and 115 deletions
|
|
@ -35,9 +35,7 @@ export function MimeToMessage(data, message)
|
|||
attachment.url = part.dataUrl;
|
||||
attachment.estimatedSize = part.body.length;
|
||||
/*
|
||||
attachment.isThumbnail = false;
|
||||
attachment.contentLocation = '';
|
||||
attachment.download = '';
|
||||
attachment.folder = '';
|
||||
attachment.uid = '';
|
||||
attachment.mimeIndex = part.id;
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import ko from 'ko';
|
||||
|
||||
import { FileInfo, FileType } from 'Common/File';
|
||||
import { stopEvent } from 'Common/Globals';
|
||||
import { stopEvent, SettingsGet, SettingsCapa } from 'Common/Globals';
|
||||
import { b64EncodeJSONSafe } from 'Common/Utils';
|
||||
import {
|
||||
attachmentDownload,
|
||||
serverRequestRaw
|
||||
|
|
@ -23,10 +24,8 @@ export class AttachmentModel extends AbstractModel {
|
|||
this.fileName = '';
|
||||
this.fileNameExt = '';
|
||||
this.fileType = FileType.Unknown;
|
||||
this.isThumbnail = false;
|
||||
this.cId = '';
|
||||
this.contentLocation = '';
|
||||
this.download = '';
|
||||
this.folder = '';
|
||||
this.uid = '';
|
||||
this.url = '';
|
||||
|
|
@ -126,6 +125,17 @@ export class AttachmentModel extends AbstractModel {
|
|||
);
|
||||
}
|
||||
|
||||
get download() {
|
||||
return b64EncodeJSONSafe({
|
||||
folder: this.folder,
|
||||
uid: this.uid,
|
||||
mimeIndex: this.mimeIndex,
|
||||
mimeType: this.mimeType,
|
||||
fileName: this.fileName,
|
||||
accountHash: SettingsGet('accountHash')
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string}
|
||||
*/
|
||||
|
|
@ -144,7 +154,7 @@ export class AttachmentModel extends AbstractModel {
|
|||
* @returns {boolean}
|
||||
*/
|
||||
hasThumbnail() {
|
||||
return this.isThumbnail && !this.isLinked();
|
||||
return SettingsCapa('AttachmentThumbnails') && this.isImage() && !this.isLinked();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import { i18n } from 'Common/Translator';
|
|||
|
||||
import { doc, SettingsGet } from 'Common/Globals';
|
||||
import { encodeHtml, plainToHtml, htmlToPlain, cleanHtml } from 'Common/Html';
|
||||
import { forEachObjectEntry } from 'Common/Utils';
|
||||
import { forEachObjectEntry, b64EncodeJSONSafe } from 'Common/Utils';
|
||||
import { serverRequestRaw, proxy } from 'Common/Links';
|
||||
import { addObservablesTo, addComputablesTo } from 'External/ko';
|
||||
|
||||
|
|
@ -59,7 +59,6 @@ export class MessageModel extends AbstractModel {
|
|||
this.folder = '';
|
||||
this.uid = 0;
|
||||
this.hash = '';
|
||||
this.requestHash = '';
|
||||
this.from = new EmailCollectionModel;
|
||||
this.to = new EmailCollectionModel;
|
||||
this.cc = new EmailCollectionModel;
|
||||
|
|
@ -178,6 +177,16 @@ export class MessageModel extends AbstractModel {
|
|||
});
|
||||
}
|
||||
|
||||
get requestHash() {
|
||||
return b64EncodeJSONSafe({
|
||||
folder: this.folder,
|
||||
uid: this.uid,
|
||||
mimeType: 'message/rfc822',
|
||||
fileName: (this.subject() || 'message-' + this.hash) + '.eml',
|
||||
accountHash: SettingsGet('accountHash')
|
||||
});
|
||||
}
|
||||
|
||||
toggleTag(keyword) {
|
||||
toggleTag(this, keyword);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,24 +18,6 @@ namespace MailSo\Base;
|
|||
abstract class Utils
|
||||
{
|
||||
|
||||
public static function fileHasThumbnail(string $sFileName) : bool
|
||||
{
|
||||
static $aCache = array();
|
||||
|
||||
$sExt = static::GetFileExtension($sFileName);
|
||||
if (isset($aCache[$sExt])) {
|
||||
return $aCache[$sExt];
|
||||
}
|
||||
|
||||
$aCache[$sExt] = (
|
||||
\extension_loaded('gd')
|
||||
|| \extension_loaded('gmagick')
|
||||
|| \extension_loaded('imagick')
|
||||
) && \in_array($sExt, ['png', 'gif', 'jpg', 'jpeg', 'webp']);
|
||||
|
||||
return $aCache[$sExt];
|
||||
}
|
||||
|
||||
public static function NormalizeCharset(string $sEncoding, bool $bAsciAsUtf8 = false) : string
|
||||
{
|
||||
$sEncoding = \preg_replace('/^iso8/', 'iso-8', \strtolower($sEncoding));
|
||||
|
|
|
|||
|
|
@ -59,20 +59,10 @@ class Attachment implements \JsonSerializable
|
|||
#[\ReturnTypeWillChange]
|
||||
public function jsonSerialize()
|
||||
{
|
||||
$aResult = \array_merge([
|
||||
return \array_merge([
|
||||
'@Object' => 'Object/Attachment',
|
||||
'folder' => $this->sFolder,
|
||||
'uid' => $this->iUid
|
||||
], $this->oBodyStructure->jsonSerialize());
|
||||
$aResult['isThumbnail'] = \MailSo\Base\Utils::fileHasThumbnail($aResult['fileName']);
|
||||
$oActions = \RainLoop\Api::Actions();
|
||||
$aResult['download'] = $oActions->encodeRawKey(array(
|
||||
'folder' => $aResult['folder'],
|
||||
'uid' => $aResult['uid'],
|
||||
'mimeIndex' => $aResult['mimeIndex'],
|
||||
'mimeType' => $aResult['mimeType'],
|
||||
'fileName' => $aResult['fileName']
|
||||
));
|
||||
return $aResult;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1080,13 +1080,19 @@ class Actions
|
|||
|
||||
public function encodeRawKey(array $aValues): string
|
||||
{
|
||||
return \SnappyMail\Crypt::EncryptUrlSafe($aValues, \sha1(APP_SALT . $this->getAccountFromToken()->Hash()));
|
||||
$aValues['accountHash'] = $this->getAccountFromToken()->Hash();
|
||||
return \MailSo\Base\Utils::UrlSafeBase64Encode(\json_encode($aValues));
|
||||
}
|
||||
|
||||
protected function decodeRawKey(string $sRawKey): array
|
||||
{
|
||||
return empty($sRawKey) ? []
|
||||
: (\SnappyMail\Crypt::DecryptUrlSafe($sRawKey, \sha1(APP_SALT . $this->getAccountFromToken()->Hash())) ?: []);
|
||||
: (\json_decode(\MailSo\Base\Utils::UrlSafeBase64Decode($sRawKey), true) ?: []);
|
||||
/*
|
||||
if (empty($aValues['accountHash']) || $aValues['accountHash'] !== $oAccount->Hash()) {
|
||||
return [];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
public function StaticCache(): string
|
||||
|
|
|
|||
|
|
@ -9,21 +9,28 @@ trait Raw
|
|||
*/
|
||||
public function RawViewAsPlain() : bool
|
||||
{
|
||||
$oAccount = $this->initMailClientConnection();
|
||||
|
||||
$aValues = $this->decodeRawKey((string) $this->GetActionParam('RawKey', ''));
|
||||
|
||||
$sFolder = isset($aValues['folder']) ? (string) $aValues['folder'] : '';
|
||||
$iUid = isset($aValues['uid']) ? (int) $aValues['uid'] : 0;
|
||||
$sMimeIndex = isset($aValues['mimeIndex']) ? (string) $aValues['mimeIndex'] : '';
|
||||
|
||||
\header('Content-Type: text/plain');
|
||||
|
||||
return $this->MailClient()->MessageMimeStream(function ($rResource) {
|
||||
if (\is_resource($rResource)) {
|
||||
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
|
||||
}
|
||||
}, $sFolder, $iUid, $sMimeIndex);
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
$sRawKey = $this->GetActionParam('RawKey', '');
|
||||
$aValues = $this->decodeRawKey($sRawKey);
|
||||
if (!empty($aValues['folder']) && !empty($aValues['uid'])
|
||||
&& !empty($aValues['accountHash']) && $aValues['accountHash'] === $oAccount->Hash()
|
||||
) {
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
$this->initMailClientConnection();
|
||||
\header('Content-Type: text/plain');
|
||||
return $this->MailClient()->MessageMimeStream(
|
||||
function ($rResource) use ($sRawKey) {
|
||||
if (\is_resource($rResource)) {
|
||||
$this->cacheByKey($sRawKey);
|
||||
\MailSo\Base\Utils::FpassthruWithTimeLimitReset($rResource);
|
||||
}
|
||||
},
|
||||
(string) $aValues['folder'],
|
||||
(int) $aValues['uid'],
|
||||
isset($aValues['mimeIndex']) ? (string) $aValues['mimeIndex'] : ''
|
||||
);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function RawDownload() : bool
|
||||
|
|
@ -69,71 +76,36 @@ trait Raw
|
|||
return false;
|
||||
}
|
||||
|
||||
public function RawPublic() : bool
|
||||
{
|
||||
$sRawKey = (string) $this->GetActionParam('RawKey', '');
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
|
||||
$sHash = $sRawKey;
|
||||
$sData = '';
|
||||
|
||||
if (!empty($sHash)) {
|
||||
$sData = $this->StorageProvider()->Get(null,
|
||||
\RainLoop\Providers\Storage\Enumerations\StorageType::NOBODY,
|
||||
\RainLoop\KeyPathHelper::PublicFile($sHash)
|
||||
);
|
||||
}
|
||||
|
||||
$aMatch = array();
|
||||
if (!empty($sData) && 0 === \strpos($sData, 'data:') &&
|
||||
\preg_match('/^data:([^:]+):/', $sData, $aMatch) && !empty($aMatch[1]))
|
||||
{
|
||||
$sContentType = \trim($aMatch[1]);
|
||||
if (\in_array($sContentType, array('image/png', 'image/jpg', 'image/jpeg'))) {
|
||||
$this->cacheByKey($sRawKey);
|
||||
|
||||
\header('Content-Type: '.$sContentType);
|
||||
echo \preg_replace('/^data:[^:]+:/', '', $sData);
|
||||
unset($sData);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Message, Message Attachment or Zip
|
||||
*/
|
||||
private function rawSmart(bool $bDownload, bool $bThumbnail = false) : bool
|
||||
{
|
||||
$sRawKey = (string) $this->GetActionParam('RawKey', '');
|
||||
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
$aValues = $this->decodeRawKey($sRawKey);
|
||||
if (empty($aValues['accountHash']) || $aValues['accountHash'] !== $oAccount->Hash()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$sRange = \MailSo\Base\Http::GetHeader('Range');
|
||||
|
||||
$aMatch = array();
|
||||
$sRangeStart = $sRangeEnd = '';
|
||||
$bIsRangeRequest = false;
|
||||
|
||||
if (!empty($sRange) && 'bytes=0-' !== \strtolower($sRange)
|
||||
&& \preg_match('/^bytes=([0-9]+)-([0-9]*)/i', \trim($sRange), $aMatch))
|
||||
{
|
||||
$sRangeStart = $aMatch[1];
|
||||
$sRangeEnd = $aMatch[2];
|
||||
|
||||
$bIsRangeRequest = true;
|
||||
}
|
||||
|
||||
$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'] : '';
|
||||
$sFileHashIn = isset($aValues['fileHash']) ? (string) $aValues['fileHash'] : '';
|
||||
|
||||
if (!empty($sFileHashIn)) {
|
||||
if (!empty($aValues['fileHash'])) {
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
|
||||
// https://github.com/the-djmaze/snappymail/issues/144
|
||||
|
|
@ -147,7 +119,7 @@ trait Raw
|
|||
|
||||
$sFileNameOut = $this->MainClearFileName($sFileNameIn, $sContentTypeIn, $sMimeIndex);
|
||||
|
||||
$rResource = $this->FilesProvider()->GetFile($oAccount, $sFileHashIn);
|
||||
$rResource = $this->FilesProvider()->GetFile($oAccount, (string) $aValues['fileHash']);
|
||||
if (\is_resource($rResource)) {
|
||||
\header('Content-Type: '.$sContentTypeOut);
|
||||
\header('Content-Disposition: attachment; '.
|
||||
|
|
@ -162,11 +134,15 @@ trait Raw
|
|||
|
||||
return false;
|
||||
}
|
||||
else if (!empty($sFolder) && 0 < $iUid)
|
||||
{
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
|
||||
$sFolder = isset($aValues['folder']) ? (string) $aValues['folder'] : '';
|
||||
$iUid = isset($aValues['uid']) ? (int) $aValues['uid'] : 0;
|
||||
if (empty($sFolder) || 1 > $iUid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->verifyCacheByKey($sRawKey);
|
||||
|
||||
$this->initMailClientConnection();
|
||||
|
||||
$self = $this;
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ trait Response
|
|||
if ($mResponse instanceof \MailSo\Mail\Message) {
|
||||
$aResult = $mResponse->jsonSerialize();
|
||||
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
if (!$aResult['dateTimeStampInUTC'] || $this->Config()->Get('labs', 'date_from_headers', true)) {
|
||||
$iDateTimeStampInUTC = $mResponse->HeaderTimeStampInUTC;
|
||||
if ($iDateTimeStampInUTC) {
|
||||
|
|
@ -103,20 +101,9 @@ trait Response
|
|||
}
|
||||
}
|
||||
|
||||
// \MailSo\Mime\EmailCollection
|
||||
foreach (['replyTo','from','to','cc','bcc','sender','deliveredTo'] as $prop) {
|
||||
$aResult[$prop] = $this->responseObject($aResult[$prop], $prop);
|
||||
}
|
||||
|
||||
$sSubject = $aResult['subject'];
|
||||
$aResult['requestHash'] = $this->encodeRawKey(array(
|
||||
'folder' => $aResult['folder'],
|
||||
'uid' => $aResult['uid'],
|
||||
'mimeType' => 'message/rfc822',
|
||||
'fileName' => (\strlen($sSubject) ? \MailSo\Base\Utils::SecureFileName($sSubject) : 'message-'.$aResult['uid']) . '.eml'
|
||||
));
|
||||
|
||||
if (!$sParent) {
|
||||
$oAccount = $this->getAccountFromToken();
|
||||
|
||||
$aResult['draftInfo'] = $mResponse->DraftInfo;
|
||||
$aResult['unsubsribeLinks'] = $mResponse->UnsubsribeLinks;
|
||||
$aResult['references'] = $mResponse->References;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue