diff --git a/api/src/Html/HtmLawed.php b/api/src/Html/HtmLawed.php index 8125e8f599..3c8f86c012 100644 --- a/api/src/Html/HtmLawed.php +++ b/api/src/Html/HtmLawed.php @@ -399,7 +399,9 @@ function hl_email_tag_transform($element, $attribute_array=0) } if (!preg_match('/^cid:.*/',$attribute_array['src'])) { - if (!$GLOBALS['egw_info']['user']['preferences']['mail']['allowExternalIMGs']) + $url = preg_replace('/^(http|https):\/\//','',$attribute_array['src']); + $url = explode('/', $url); + if (!in_array($url[0], $GLOBALS['egw_info']['user']['preferences']['mail']['allowExternalIMGs'])) { //the own webserver url is not external, so it should be allowed if (empty($GLOBALS['egw_info']['server']['webserver_url'])||!preg_match("$^".$GLOBALS['egw_info']['server']['webserver_url'].".*$",$attribute_array['src'])) diff --git a/mail/inc/class.mail_hooks.inc.php b/mail/inc/class.mail_hooks.inc.php index 3f1c5b867b..ef34d8b0eb 100644 --- a/mail/inc/class.mail_hooks.inc.php +++ b/mail/inc/class.mail_hooks.inc.php @@ -200,15 +200,6 @@ class mail_hooks 'admin' => False, 'forced' => 'always_display', ), - 'allowExternalIMGs' => array( - 'type' => 'check', - 'label' => 'Allow external images', - 'help' => 'allow images from external sources in html emails', - 'name' => 'allowExternalIMGs', - 'xmlrpc' => True, - 'admin' => True, - 'forced' => true, - ), 'message_forwarding' => array( 'type' => 'select', 'label' => 'how to forward messages', diff --git a/mail/js/app.js b/mail/js/app.js index 76d85bbabb..e0fbfd30a1 100644 --- a/mail/js/app.js +++ b/mail/js/app.js @@ -985,9 +985,12 @@ app.classes.mail = AppJS.extend( { this.mail_selectedMails.push(_id); } - + var self = this; // Request email body from server IframeHandle.set_src(egw.link('/index.php',{menuaction:'mail.mail_ui.loadEmailBody',_messageID:_id})); + jQuery(IframeHandle.getDOMNode()).on('load', function(e){ + self.resolveExternalImages (this.contentWindow.document); + }); } var messages = {}; @@ -1027,6 +1030,126 @@ app.classes.mail = AppJS.extend( } }, + resolveExternalImages: function (_node) + { + var external_images = jQuery(_node).find('img[alt*="[blocked external image:"]'); + if (external_images.length > 0 && jQuery(_node).find('.mail_externalImagesMsg').length == 0) + { + var container = jQuery(document.createElement('div')) + .addClass('mail_externalImagesMsg') + .css({ + "display": 'block', + "position": 'fixed', + "height": '50px', + "width": '100%', + "top": '0', + "left": '0', + "background":'#ffe5a5', + "border-top": '1px solid #8f8b8b', + "box-shadow": '0px 1px 13px 2px #8f8b8b' + }); + var button_style = { + "float": "right", + "margin": "15px", + "display": "inline-block", + "background-color": "transparent", + "border": "none", + "font-weight": "bold", + "color": "#30558c", + "cursor": "pointer", + "text-decoration": "underline" + }; + var getUrlParts = function (_rawUrl) { + var u = _rawUrl.split('[blocked external image:'); + u = u[1].replace(']',''); + var url = u; + if (u.substr(0,7) == 'http://') u = u.replace ('http://',''); + if (u.substr(0,8) == 'https://') u = u.replace ('https://',''); + var url_parts = u.split('/'); + return { + url: url, + domain: url_parts[0] + }; + } + + var host = getUrlParts(external_images[0].alt); + var showImages = function (_images) + { + _images.each(function(i, node){ + var parts = getUrlParts (node.alt); + node.src = parts.url; + }); + } + var pref = egw.preference('allowExternalIMGs', 'mail'); + pref = Object.values(pref); + if (pref.indexOf(host.domain)>-1) + { + showImages (external_images); + return; + } + + var text = jQuery(document.createElement('p')) + .css({ + "display": 'inline-block', + "width":'60%', + "font-size":'11pt', + "margin": '15px', + "color": '#1f1f1f' + }) + .text(egw.lang('In order to protect your privacy all external sources within this email are blocked.')) + .appendTo(container); + var closeBtn = jQuery(document.createElement('button')) + .css ({ + "float":'right', + "background-image":'url(pixelegg/images/close.png)', + "height": '50px', + "width": '50px', + "background-repeat": 'no-repeat', + "background-position": 'center', + "background-size": '22px', + "background-color": 'transparent', + "border": 'none', + "cursor": 'pointer', + "display": 'inline-block' + }) + .click (function (){ + container.remove(); + }) + .appendTo(container); + var alwaysBtn = jQuery(document.createElement('button')) + .css(button_style) + .text(egw.lang('Allow')) + .attr ('title', egw.lang('Always allow external sources from %1', host.domain)) + .click (function (){ + + + if (pref && pref.length) + { + pref.push(host.domain); + } + else + { + pref = [host.domain]; + } + egw.set_preference( 'mail', 'allowExternalIMGs', pref); + showImages(external_images); + container.remove(); + }) + .appendTo(container); + var alwaysBtn = jQuery(document.createElement('button')) + .css(button_style) + .text(egw.lang('Show')) + .attr ('title', egw.lang('Show them this time only')) + .click(function(){ + showImages(external_images); + container.remove(); + }) + .appendTo(container); + container.appendTo(_node.body); + + } + }, + /** * If a preview header is partially hidden, this is the handler for clicking the * expand button that shows all the content for that header.