From b240c266673fe276198a6b59fefe944d1993248f Mon Sep 17 00:00:00 2001 From: the-djmaze <> Date: Thu, 16 Feb 2023 14:02:55 +0100 Subject: [PATCH] Resolve #962 --- dev/Styles/User/MessageView.less | 4 + .../app/libraries/MailSo/Base/HtmlUtils.php | 95 ++++++++++--------- vendors/squire/build/squire-raw.js | 34 +++---- 3 files changed, 63 insertions(+), 70 deletions(-) diff --git a/dev/Styles/User/MessageView.less b/dev/Styles/User/MessageView.less index d84d14533..3d71f9604 100644 --- a/dev/Styles/User/MessageView.less +++ b/dev/Styles/User/MessageView.less @@ -382,6 +382,10 @@ html.rl-bottom-preview-pane #V-MailMessageView .top-toolbar { opacity: 0.8; padding: 0 10px; margin: 0; + + blockquote { + opacity: 1; + } } &.html { 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 6ae0e13ec..d5f09b84a 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 @@ -101,44 +101,46 @@ abstract class HtmlUtils 'object', 'embed', 'applet', 'mocha', 'iframe', 'frame', 'frameset', 'video', 'audio', 'area', 'map', 'head', 'style' ); - - $aRemove = array(); - - $sIdRight = \md5(\microtime()); - - $aNodes = $oBody->getElementsByTagName('*'); - foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) { - $sTagNameLower = \strtolower($oElement->nodeName); - - if (\in_array($sTagNameLower, $aRemoveTags)) { - $aRemove[] = $oElement; - continue; - } - - // 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)) { - $aFoundCids[] = $sCid; - $oElement->setAttribute('src', 'cid:'.$sCid); + foreach ($aRemoveTags as $name) { + $aNodes = $oBody->getElementsByTagName($name); + foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) { + if (isset($oElement->parentNode)) { + @$oElement->parentNode->removeChild($oElement); } } - 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-url')) { - $aCid = \array_merge($aCid, \json_decode($oElement->getAttribute('data-x-style-url'), true)); - $oElement->removeAttribute('data-x-style-url'); + $xpath = new \DomXpath($oDoc); + foreach ($xpath->query('//*[@data-x-src-broken]') as $oElement) { + if (isset($oElement->parentNode)) { + @$oElement->parentNode->removeChild($oElement); } + } + + foreach ($xpath->query('//*[@data-x-src-hidden]') as $oElement) { + if (isset($oElement->parentNode)) { + @$oElement->parentNode->removeChild($oElement); + } + } + + foreach ($xpath->query('//*[@data-x-src-cid]') as $oElement) { + $sCid = $oElement->getAttribute('data-x-src-cid'); + $oElement->removeAttribute('data-x-src-cid'); + if (!empty($sCid)) { + $aFoundCids[] = $sCid; + $oElement->setAttribute('src', 'cid:'.$sCid); + } + } + + foreach ($xpath->query('//*[@data-x-src]') as $oElement) { + $oElement->setAttribute('src', $oElement->getAttribute('data-x-src')); + $oElement->removeAttribute('data-x-src'); + } + + foreach ($xpath->query('//*[@data-x-style-url]') as $oElement) { + // style attribute images + $aCid = \array_merge($aCid, \json_decode($oElement->getAttribute('data-x-style-url'), true)); + $oElement->removeAttribute('data-x-style-url'); if ($aCid) { foreach ($aCid as $sCidName => $sCid) { $sCidName = \strtolower(\preg_replace('/([A-Z])/', '-\1', $sCidName)); @@ -158,8 +160,11 @@ abstract class HtmlUtils } } } + } - // Remove all remaining data-* attributes + // Remove all remaining data-* attributes + foreach ($xpath->query('//*[@*[starts-with(name(), "data-")]]') as $oElement) { + $sTagNameLower = \strtolower($oElement->nodeName); if ($oElement->hasAttributes()) { foreach ($oElement->attributes as $oAttr) { if ('data-' === \substr(\strtolower($oAttr->nodeName), 0, 5)) { @@ -167,20 +172,16 @@ abstract class HtmlUtils } } } - - if ('img' === $sTagNameLower) { - $sSrc = $oElement->getAttribute('src'); - if ('data:image/' === \strtolower(\substr($sSrc, 0, 11))) { - $sHash = \md5($sSrc) . '@' . $sIdRight; - $aFoundDataURL[$sHash] = $sSrc; - $oElement->setAttribute('src', 'cid:'.$sHash); - } - } } - foreach ($aRemove as /* @var $oElement \DOMElement */ $oElement) { - if (isset($oElement->parentNode)) { - @$oElement->parentNode->removeChild($oElement); + $sIdRight = \md5(\microtime()); + $aNodes = $oBody->getElementsByTagName('IMG'); + foreach ($aNodes as /* @var $oElement \DOMElement */ $oElement) { + $sSrc = $oElement->getAttribute('src'); + if ('data:image/' === \strtolower(\substr($sSrc, 0, 11))) { + $sHash = \md5($sSrc) . '@' . $sIdRight; + $aFoundDataURL[$sHash] = $sSrc; + $oElement->setAttribute('src', 'cid:'.$sHash); } } diff --git a/vendors/squire/build/squire-raw.js b/vendors/squire/build/squire-raw.js index 4ba322311..97a16a840 100644 --- a/vendors/squire/build/squire-raw.js +++ b/vendors/squire/build/squire-raw.js @@ -280,6 +280,8 @@ const // Recursively examine container nodes and wrap any inline children. fixContainer = ( container, root ) => { +/* + // Live, but very slow let children = container.childNodes; let wrapper = null; let i = 0, l = children.length, child, isBR; @@ -290,16 +292,12 @@ const if ( !isBR && isInline( child ) // && (root.__squire__._config.blockTag !== 'DIV' || (child.matches && !child.matches(phrasingElements))) ) { - if ( !wrapper ) { - wrapper = createElement( 'div' ); - } + wrapper = wrapper || createElement( 'div' ); wrapper.append( child ); --i; --l; } else if ( isBR || wrapper ) { - if ( !wrapper ) { - wrapper = createElement( 'div' ); - } + wrapper = wrapper || createElement( 'div' ); fixCursor( wrapper, root ); if ( isBR ) { child.replaceWith( wrapper ); @@ -312,34 +310,24 @@ const } isContainer( child ) && fixContainer( child, root ); } -/* - // Not live +*/ + let wrapper, isBR; + // Not live, and fast [...container.children].forEach(child => { isBR = child.nodeName === 'BR'; if ( !isBR && isInline( child ) // && (root.__squire__._config.blockTag !== 'DIV' || (child.matches && !child.matches(phrasingElements))) ) { - if ( !wrapper ) { - wrapper = createElement( 'div' ); - } + wrapper = wrapper || createElement( 'div' ); wrapper.append( child ); } else if ( isBR || wrapper ) { - if ( !wrapper ) { - wrapper = createElement( 'div' ); - } + wrapper = wrapper || createElement( 'div' ); fixCursor( wrapper, root ); - if ( isBR ) { - child.replaceWith( wrapper ); - } else { - child.before( wrapper ); - } + isBR ? child.replaceWith( wrapper ) : child.before( wrapper ); wrapper = null; } - if ( isContainer( child ) ) { - fixContainer( child, root ); - } + isContainer( child ) && fixContainer( child, root ); }); -*/ wrapper && container.append( fixCursor( wrapper, root ) ); return container; },