diff --git a/typo3/sysext/backend/Resources/Private/TypeScript/Modal.ts b/typo3/sysext/backend/Resources/Private/TypeScript/Modal.ts index 24f9001eec7f..76d53ab9e1ee 100644 --- a/typo3/sysext/backend/Resources/Private/TypeScript/Modal.ts +++ b/typo3/sysext/backend/Resources/Private/TypeScript/Modal.ts @@ -16,6 +16,7 @@ import 'bootstrap'; import * as $ from 'jquery'; import Icons = require('./Icons'); import Severity = require('./Severity'); +import SecurityUtility = require('TYPO3/CMS/Core/SecurityUtility'); enum Identifiers { modal = '.t3js-modal', @@ -116,7 +117,10 @@ class Modal { ajaxTarget: null }; - constructor() { + private readonly securityUtility: SecurityUtility; + + constructor(securityUtility: SecurityUtility) { + this.securityUtility = securityUtility; $(document).on('modal-dismiss', this.dismiss); this.initializeMarkupTrigger(document); } @@ -250,9 +254,15 @@ class Modal { configuration.title = typeof configuration.title === 'string' ? configuration.title : this.defaultConfiguration.title; - configuration.content = typeof configuration.content === 'string' || typeof configuration.content === 'object' - ? configuration.content - : this.defaultConfiguration.content; + if (typeof configuration.content === 'string') { + // A string means, no markup allowed, let's ensure this + configuration.content = this.securityUtility.encodeHtml(configuration.content); + } else if (typeof configuration.content === 'object') { + // An object means, a valid jQuery object with markup, let's get the markup + configuration.content = configuration.content.html(); + } else { + configuration.content = this.defaultConfiguration.content; + } configuration.severity = typeof configuration.severity !== 'undefined' ? configuration.severity : this.defaultConfiguration.severity; @@ -375,10 +385,7 @@ class Modal { }); } else { if (typeof configuration.content === 'string') { - // we need html, check if we have to wrap content in

- if (!/^<[a-z][\s\S]*>/i.test(configuration.content)) { - configuration.content = $('

').html(configuration.content); - } + configuration.content = $('

').html(configuration.content); } currentModal.find(Identifiers.body).append(configuration.content); } @@ -488,7 +495,7 @@ try { } if (!modalObject) { - modalObject = new Modal(); + modalObject = new Modal(new SecurityUtility()); // expose as global object TYPO3.Modal = modalObject; diff --git a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js index d9c34caf70e5..b1ac6bfaecf0 100644 --- a/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js +++ b/typo3/sysext/backend/Resources/Public/JavaScript/Modal.js @@ -10,4 +10,4 @@ * * The TYPO3 project - inspiring people to share! */ -var __values=this&&this.__values||function(t){var e="function"==typeof Symbol&&t[Symbol.iterator],a=0;return e?e.call(t):{next:function(){return t&&a>=t.length&&(t=void 0),{value:t&&t[a++],done:!t}}}};define(["require","exports","./Enum/Severity","jquery","./Icons","./Severity","bootstrap"],function(t,e,a,n,o,i){"use strict";var l,s,r,d,c,u,f,m;(s=l||(l={})).modal=".t3js-modal",s.content=".t3js-modal-content",s.title=".t3js-modal-title",s.close=".t3js-modal-close",s.body=".t3js-modal-body",s.footer=".t3js-modal-footer",s.iframe=".t3js-modal-iframe",s.iconPlaceholder=".t3js-modal-icon-placeholder",(d=r||(r={})).small="small",d.default="default",d.medium="medium",d.large="large",d.full="full",(u=c||(c={})).default="default",u.light="light",u.dark="dark",(m=f||(f={})).default="default",m.ajax="ajax",m.iframe="iframe";var g=function(){function t(){this.sizes=r,this.styles=c,this.types=f,this.currentModal=null,this.instances=[],this.$template=n('

'),this.defaultConfiguration={type:f.default,title:"Information",content:"No content provided, please check your Modal configuration.",severity:a.SeverityEnum.notice,buttons:[],style:c.default,size:r.default,additionalCssClasses:[],callback:n.noop(),ajaxCallback:n.noop(),ajaxTarget:null},n(document).on("modal-dismiss",this.dismiss),this.initializeMarkupTrigger(document)}return t.prototype.dismiss=function(){this.currentModal&&this.currentModal.modal("hide")},t.prototype.confirm=function(t,e,o,l,s){return void 0===o&&(o=a.SeverityEnum.warning),void 0===l&&(l=[]),0===l.length&&l.push({text:n(this).data("button-close-text")||TYPO3.lang["button.cancel"]||"Cancel",active:!0,btnClass:"btn-default",name:"cancel"},{text:n(this).data("button-ok-text")||TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+i.getCssClass(o),name:"ok"}),this.advanced({title:t,content:e,severity:o,buttons:l,additionalCssClasses:s,callback:function(t){t.on("button.clicked",function(t){"cancel"===t.target.getAttribute("name")?n(t.currentTarget).trigger("confirm.button.cancel"):"ok"===t.target.getAttribute("name")&&n(t.currentTarget).trigger("confirm.button.ok")})}})},t.prototype.loadUrl=function(t,e,n,o,i,l){return void 0===e&&(e=a.SeverityEnum.info),this.advanced({type:f.ajax,title:t,severity:e,buttons:n,ajaxCallback:i,ajaxTarget:l})},t.prototype.show=function(t,e,n,o,i){return void 0===n&&(n=a.SeverityEnum.info),this.advanced({type:f.default,title:t,content:e,severity:n,buttons:o,additionalCssClasses:i})},t.prototype.advanced=function(t){return t.type="string"==typeof t.type&&t.type in f?t.type:this.defaultConfiguration.type,t.title="string"==typeof t.title?t.title:this.defaultConfiguration.title,t.content="string"==typeof t.content||"object"==typeof t.content?t.content:this.defaultConfiguration.content,t.severity=void 0!==t.severity?t.severity:this.defaultConfiguration.severity,t.buttons=t.buttons||this.defaultConfiguration.buttons,t.size="string"==typeof t.size&&t.size in r?t.size:this.defaultConfiguration.size,t.style="string"==typeof t.style&&t.style in c?t.style:this.defaultConfiguration.style,t.additionalCssClasses=t.additionalCssClasses||this.defaultConfiguration.additionalCssClasses,t.callback="function"==typeof t.callback?t.callback:this.defaultConfiguration.callback,t.ajaxCallback="function"==typeof t.ajaxCallback?t.ajaxCallback:this.defaultConfiguration.ajaxCallback,t.ajaxTarget="string"==typeof t.ajaxTarget?t.ajaxTarget:this.defaultConfiguration.ajaxTarget,this.generate(t)},t.prototype.initializeMarkupTrigger=function(t){var e=this;n(t).on("click",".t3js-modal-trigger",function(t){t.preventDefault();var o=n(t.currentTarget),l=o.data("content")||"Are you sure?",s=void 0!==a.SeverityEnum[o.data("severity")]?a.SeverityEnum[o.data("severity")]:a.SeverityEnum.info,r=o.data("url")||null;null!==r&&(r=r+(r.indexOf("?")>-1?"&":"?")+n.param({data:o.data()}));e.advanced({type:null!==r?f.ajax:f.default,title:o.data("title")||"Alert",content:null!==r?r:l,severity:s,buttons:[{text:o.data("button-close-text")||TYPO3.lang["button.close"]||"Close",active:!0,btnClass:"btn-default",trigger:function(){e.currentModal.trigger("modal-dismiss")}},{text:o.data("button-ok-text")||TYPO3.lang["button.ok"]||"OK",btnClass:"btn-"+i.getCssClass(s),trigger:function(){e.currentModal.trigger("modal-dismiss"),t.target.ownerDocument.location.href=o.data("href")||o.attr("href")}}]})})},t.prototype.generate=function(t){var e,a,s=this,r=this.$template.clone();if(t.additionalCssClasses.length>0)try{for(var d=__values(t.additionalCssClasses),c=d.next();!c.done;c=d.next()){var u=c.value;r.addClass(u)}}catch(t){e={error:t}}finally{try{c&&!c.done&&(a=d.return)&&a.call(d)}finally{if(e)throw e.error}}if(r.addClass("modal-type-"+t.type),r.addClass("modal-severity-"+i.getCssClass(t.severity)),r.addClass("modal-style-"+t.style),r.addClass("modal-size-"+t.size),r.attr("tabindex","-1"),r.find(l.title).text(t.title),r.find(l.close).on("click",function(){r.modal("hide")}),"ajax"===t.type){var f=t.ajaxTarget?t.ajaxTarget:l.body,m=r.find(f);o.getIcon("spinner-circle",o.sizes.default,null,null,o.markupIdentifiers.inline).done(function(e){m.html('"),n.get(t.content,function(e){s.currentModal.find(f).empty().append(e),t.ajaxCallback&&t.ajaxCallback(),s.currentModal.trigger("modal-loaded")},"html")})}else"iframe"===t.type?(r.find(l.body).append(n("