diff --git a/dev/Common/Html.js b/dev/Common/Html.js
index 4df4538e9..8079a01c3 100644
--- a/dev/Common/Html.js
+++ b/dev/Common/Html.js
@@ -241,7 +241,7 @@ export const
)) {
skipStyle = true;
setAttribute('style', 'display:none');
- setAttribute('data-x-hidden-src', value);
+ setAttribute('data-x-src-hidden', value);
}
else if ((attachment = findLocationByCid(value)))
{
@@ -253,7 +253,9 @@ export const
}
else if ('cid:' === value.slice(0, 4))
{
- attachment = findAttachmentByCid(value.slice(4));
+ value = value.slice(4);
+ setAttribute('data-x-src-cid', value);
+ attachment = findAttachmentByCid(value);
if (attachment && attachment.download) {
oElement.src = attachment.linkPreview();
attachment.isInline(true);
@@ -267,16 +269,16 @@ export const
}
else if ('data:image/' === value.slice(0, 11))
{
- setAttribute('src', value);
+ oElement.src = value;
}
else
{
- setAttribute('data-x-broken-src', value);
+ setAttribute('data-x-src-broken', value);
}
}
else
{
- setAttribute('data-x-broken-src', value);
+ setAttribute('data-x-src-broken', value);
}
}
diff --git a/dev/View/Popup/Compose.js b/dev/View/Popup/Compose.js
index 60be08570..e192d7e2a 100644
--- a/dev/View/Popup/Compose.js
+++ b/dev/View/Popup/Compose.js
@@ -20,7 +20,7 @@ import { folderInformation, messagesDeleteHelper } from 'Common/Folders';
import { serverRequest } from 'Common/Links';
import { i18n, getNotification, getUploadErrorDescByCode, timestampToString } from 'Common/Translator';
import { MessageFlagsCache, setFolderHash } from 'Common/Cache';
-import { Settings, SettingsCapa, SettingsGet, elementById, addShortcut } from 'Common/Globals';
+import { Settings, SettingsCapa, SettingsGet, elementById, addShortcut, createElement } from 'Common/Globals';
//import { exitFullscreen, isFullscreen, toggleFullscreen } from 'Common/Fullscreen';
import { AppUserStore } from 'Stores/User/App';
@@ -50,9 +50,13 @@ import { ThemeStore } from 'Stores/Theme';
let alreadyFullscreen;
*/
+let oLastMessage;
+
const
ScopeCompose = 'Compose',
+ tpl = createElement('template'),
+
base64_encode = text => btoa(unescape(encodeURIComponent(text))).match(/.{1,76}/g).join('\r\n'),
email = new EmailModel(),
@@ -226,7 +230,6 @@ export class ComposePopupView extends AbstractViewPopup {
}
};
- this.oLastMessage = null;
this.oEditor = null;
this.aDraftInfo = null;
this.sInReplyTo = '';
@@ -828,7 +831,7 @@ export class ComposePopupView extends AbstractViewPopup {
this.editor(editor => {
let signature = identity.signature() || '',
isHtml = ':HTML:' === signature.slice(0, 6),
- fromLine = this.oLastMessage ? emailArrayToStringLineHelper(this.oLastMessage.from, true) : '';
+ fromLine = oLastMessage ? emailArrayToStringLineHelper(oLastMessage.from, true) : '';
if (fromLine) {
signature = signature.replace(/{{FROM-FULL}}/g, fromLine);
if (!fromLine.includes(' ') && 0 < fromLine.indexOf('@')) {
@@ -909,24 +912,20 @@ export class ComposePopupView extends AbstractViewPopup {
sText = '',
identity = null,
aDraftInfo = null,
- message = null;
+ message = 1 === arrayLength(oMessageOrArray)
+ ? oMessageOrArray[0]
+ : (isArray(oMessageOrArray) ? null : oMessageOrArray);
- const excludeEmail = {},
+ const
+// excludeEmail = new Set(),
+ excludeEmail = {},
mEmail = AccountUserStore.email(),
lineComposeType = sType || ComposeType.Empty;
- if (oMessageOrArray) {
- message =
- 1 === arrayLength(oMessageOrArray)
- ? oMessageOrArray[0]
- : isArray(oMessageOrArray)
- ? null
- : oMessageOrArray;
- }
+ oLastMessage = message;
- this.oLastMessage = message;
-
- if (null !== mEmail) {
+ if (mEmail) {
+// excludeEmail.add(mEmail);
excludeEmail[mEmail] = true;
}
@@ -934,6 +933,7 @@ export class ComposePopupView extends AbstractViewPopup {
identity = findIdentityByMessage(lineComposeType, message);
if (identity) {
+// excludeEmail.add(identity.email());
excludeEmail[identity.email()] = true;
}
@@ -1030,9 +1030,15 @@ export class ComposePopupView extends AbstractViewPopup {
// no default
}
- sText = message.bodyAsHTML().replace(/]+>/g, '').replace(/]+><\/a>/g, '');
let encrypted;
+ // https://github.com/the-djmaze/snappymail/issues/491
+ tpl.innerHTML = message.bodyAsHTML();
+ tpl.content.querySelectorAll('img').forEach(img =>
+ img.dataset.xSrcCid || img.dataset.xSrc || img.replaceWith(img.alt || img.title)
+ );
+ sText = tpl.innerHTML.trim();
+
switch (lineComposeType) {
case ComposeType.Reply:
case ComposeType.ReplyAll:
@@ -1068,6 +1074,7 @@ export class ComposePopupView extends AbstractViewPopup {
case ComposeType.ForwardAsAttachment:
sText = '';
break;
+
default:
encrypted = PgpUserStore.isEncrypted(sText);
if (encrypted) {
@@ -1131,7 +1138,8 @@ export class ComposePopupView extends AbstractViewPopup {
this.setFocusInPopup();
}
- const downloads = this.getAttachmentsDownloadsForUpload();
+ // item.CID item.isInline item.isLinked
+ const downloads = this.attachments.filter(item => item && !item.tempName()).map(item => item.id);
if (arrayLength(downloads)) {
Remote.request('MessageUploadAttachments',
(iError, oData) => {
@@ -1402,35 +1410,22 @@ export class ComposePopupView extends AbstractViewPopup {
if (message) {
if (ComposeType.ForwardAsAttachment === type) {
this.addMessageAsAttachment(message);
- } else {
+ } else if ([
+ ComposeType.Reply, ComposeType.ReplyAll,
+ ComposeType.Forward, ComposeType.Draft, ComposeType.EditAsNew
+ ].includes(type)) {
message.attachments.forEach(item => {
- let add = false;
- switch (type) {
- case ComposeType.Reply:
- case ComposeType.ReplyAll:
- break;
-
- case ComposeType.Forward:
- case ComposeType.Draft:
- case ComposeType.EditAsNew:
- add = true;
- break;
- // no default
- }
-
- if (add) {
- const attachment = new ComposeAttachmentModel(
- item.download,
- item.fileName,
- item.estimatedSize,
- item.isInline(),
- item.isLinked(),
- item.cid,
- item.contentLocation
- );
- attachment.fromMessage = true;
- this.addAttachment(attachment);
- }
+ const attachment = new ComposeAttachmentModel(
+ item.download,
+ item.fileName,
+ item.estimatedSize,
+ item.isInline(),
+ item.isLinked(),
+ item.cid,
+ item.contentLocation
+ );
+ attachment.fromMessage = true;
+ this.addAttachment(attachment);
});
}
}
@@ -1504,15 +1499,6 @@ export class ComposePopupView extends AbstractViewPopup {
this.dropMailvelope();
}
- /**
- * @returns {Array}
- */
- getAttachmentsDownloadsForUpload() {
- return this.attachments.filter(item => item && !item.tempName()).map(
- item => item.id
- );
- }
-
mailvelopeArea() {
if (!this.mailvelope) {
/**
diff --git a/snappymail/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php b/snappymail/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php
index 742782f9d..c4e67a674 100644
--- a/snappymail/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php
+++ b/snappymail/v/0.0.0/app/libraries/MailSo/Base/HtmlUtils.php
@@ -107,6 +107,8 @@ abstract class HtmlUtils
$aRemove = array();
+ $sIdRight = \md5(\microtime());
+
$aNodes = $oBody->getElementsByTagName('*');
foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement)
{
@@ -114,56 +116,30 @@ abstract class HtmlUtils
if (\in_array($sTagNameLower, $aRemoveTags))
{
- $aRemove[] = @$oElement;
+ $aRemove[] = $oElement;
continue;
}
- if ($oElement->hasAttribute('data-x-src-cid'))
- {
+ // images
+ if ($oElement->hasAttribute('data-x-src-broken') || $oElement->hasAttribute('data-x-src-hidden')) {
+ $aRemove[] = $oElement;
+ continue;
+ }
+ if ($oElement->hasAttribute('data-x-src-cid')) {
$sCid = $oElement->getAttribute('data-x-src-cid');
$oElement->removeAttribute('data-x-src-cid');
-
- if (!empty($sCid))
- {
+ if (!empty($sCid)) {
$aFoundCids[] = $sCid;
-
- @$oElement->removeAttribute('src');
$oElement->setAttribute('src', 'cid:'.$sCid);
}
}
-
- if ($oElement->hasAttribute('data-x-src-location'))
- {
- $sSrc = $oElement->getAttribute('data-x-src-location');
- $oElement->removeAttribute('data-x-src-location');
-
- if (!empty($sSrc))
- {
- $aFoundContentLocationUrls[] = $sSrc;
-
- @$oElement->removeAttribute('src');
- $oElement->setAttribute('src', $sSrc);
- }
- }
-
- if ($oElement->hasAttribute('data-x-broken-src'))
- {
- $oElement->setAttribute('src', $oElement->getAttribute('data-x-broken-src'));
- $oElement->removeAttribute('data-x-broken-src');
- }
-
- if ($oElement->hasAttribute('data-x-src'))
- {
+ if ($oElement->hasAttribute('data-x-src')) {
$oElement->setAttribute('src', $oElement->getAttribute('data-x-src'));
$oElement->removeAttribute('data-x-src');
}
// style attribute images
$aCid = array();
- if ($oElement->hasAttribute('data-x-style-cid')) {
- $aCid = \json_decode($oElement->getAttribute('data-x-style-cid'), true);
- $oElement->removeAttribute('data-x-style-cid');
- }
if ($oElement->hasAttribute('data-x-style-url')) {
$aCid = \array_merge($aCid, \json_decode($oElement->getAttribute('data-x-style-url'), true));
$oElement->removeAttribute('data-x-style-url');
@@ -205,7 +181,7 @@ abstract class HtmlUtils
$sSrc = $oElement->getAttribute('src');
if ('data:image/' === \strtolower(\substr($sSrc, 0, 11)))
{
- $sHash = \md5($sSrc);
+ $sHash = \md5($sSrc) . '@' . $sIdRight;
$aFoundDataURL[$sHash] = $sSrc;
$oElement->setAttribute('src', 'cid:'.$sHash);