From 737f657bade55fafdab68ea3b733114d51a2bf92 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Wed, 9 Aug 2023 09:05:23 +0800 Subject: [PATCH 1/3] MDL-78714 editor_tiny: Move TinyMCE import instructions to correct path --- lib/editor/tiny/{ => js/tinymce}/readme_moodle.md | 2 +- lib/editor/tiny/readme_moodle.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) rename lib/editor/tiny/{ => js/tinymce}/readme_moodle.md (99%) create mode 100644 lib/editor/tiny/readme_moodle.txt diff --git a/lib/editor/tiny/readme_moodle.md b/lib/editor/tiny/js/tinymce/readme_moodle.md similarity index 99% rename from lib/editor/tiny/readme_moodle.md rename to lib/editor/tiny/js/tinymce/readme_moodle.md index 72982c89cc5..592be1dfb43 100644 --- a/lib/editor/tiny/readme_moodle.md +++ b/lib/editor/tiny/js/tinymce/readme_moodle.md @@ -10,7 +10,7 @@ 2. Check out a clean copy of TinyMCE of the target version. - ``` + ```../../ tinymce=`mktemp -d` cd "${tinymce}" git clone https://github.com/tinymce/tinymce.git diff --git a/lib/editor/tiny/readme_moodle.txt b/lib/editor/tiny/readme_moodle.txt new file mode 100644 index 00000000000..016ae378cfa --- /dev/null +++ b/lib/editor/tiny/readme_moodle.txt @@ -0,0 +1 @@ +For instructions on how to import TinyMCE into Moodle, see js/tinymce/readme_moodle.md. From e8eb8943e1f2490c3d0a9fbcb475dc763f0d0fe0 Mon Sep 17 00:00:00 2001 From: Andrew Nicols Date: Tue, 8 Aug 2023 14:17:16 +0800 Subject: [PATCH 2/3] MDL-78714 editor_tiny: Add xss_sanitize option to TinyMCE To address a potential data loss issue, a feature introduced in TinyMCE 6.4.0 to disable client-side XSS sanitisation must be backported. --- .../tiny/js/tinymce/plugins/media/plugin.js | 7 ++- .../js/tinymce/plugins/media/plugin.min.js | 2 +- lib/editor/tiny/js/tinymce/readme_moodle.md | 48 ++++++++++++++++--- .../tiny/js/tinymce/themes/silver/theme.js | 20 ++++---- .../js/tinymce/themes/silver/theme.min.js | 2 +- lib/editor/tiny/js/tinymce/tinymce.d.ts | 3 ++ lib/editor/tiny/js/tinymce/tinymce.js | 48 +++++++++++-------- lib/editor/tiny/js/tinymce/tinymce.min.js | 2 +- 8 files changed, 88 insertions(+), 44 deletions(-) diff --git a/lib/editor/tiny/js/tinymce/plugins/media/plugin.js b/lib/editor/tiny/js/tinymce/plugins/media/plugin.js index 0b53bc86c8c..e2c21661c75 100644 --- a/lib/editor/tiny/js/tinymce/plugins/media/plugin.js +++ b/lib/editor/tiny/js/tinymce/plugins/media/plugin.js @@ -1044,8 +1044,13 @@ }; const parseAndSanitize = (editor, context, html) => { + const getEditorOption = editor.options.get; + const sanitize = getEditorOption('xss_sanitization'); const validate = shouldFilterHtml(editor); - return Parser(editor.schema, { validate }).parse(html, { context }); + return Parser(editor.schema, { + sanitize, + validate + }).parse(html, { context }); }; const setup$1 = editor => { diff --git a/lib/editor/tiny/js/tinymce/plugins/media/plugin.min.js b/lib/editor/tiny/js/tinymce/plugins/media/plugin.min.js index 400c66ef485..09a09302c5e 100644 --- a/lib/editor/tiny/js/tinymce/plugins/media/plugin.min.js +++ b/lib/editor/tiny/js/tinymce/plugins/media/plugin.min.js @@ -1,4 +1,4 @@ /** * TinyMCE version 6.2.0 (2022-09-08) */ -!function(){"use strict";var e=tinymce.util.Tools.resolve("tinymce.PluginManager");const t=e=>t=>(e=>{const t=typeof e;return null===e?"null":"object"===t&&Array.isArray(e)?"array":"object"===t&&(r=a=e,(o=String).prototype.isPrototypeOf(r)||a.constructor?.name===o.name)?"string":t;var r,a,o})(t)===e,r=t("string"),a=t("object"),o=t("array"),s=e=>!(e=>null==e)(e);class i{constructor(e,t){this.tag=e,this.value=t}static some(e){return new i(!0,e)}static none(){return i.singletonNone}fold(e,t){return this.tag?t(this.value):e()}isSome(){return this.tag}isNone(){return!this.tag}map(e){return this.tag?i.some(e(this.value)):i.none()}bind(e){return this.tag?e(this.value):i.none()}exists(e){return this.tag&&e(this.value)}forall(e){return!this.tag||e(this.value)}filter(e){return!this.tag||e(this.value)?this:i.none()}getOr(e){return this.tag?this.value:e}or(e){return this.tag?this:e}getOrThunk(e){return this.tag?this.value:e()}orThunk(e){return this.tag?this:e()}getOrDie(e){if(this.tag)return this.value;throw new Error(e??"Called getOrDie on None")}static from(e){return s(e)?i.some(e):i.none()}getOrNull(){return this.tag?this.value:null}getOrUndefined(){return this.value}each(e){this.tag&&e(this.value)}toArray(){return this.tag?[this.value]:[]}toString(){return this.tag?`some(${this.value})`:"none()"}}i.singletonNone=new i(!1);const c=Array.prototype.push,n=(e,t)=>{for(let r=0,a=e.length;r{const t=[];for(let r=0,a=e.length;rh(e,t)?i.from(e[t]):i.none(),h=(e,t)=>u.call(e,t),p=e=>t=>t.options.get(e),g=p("audio_template_callback"),b=p("video_template_callback"),w=p("iframe_template_callback"),f=p("media_live_embeds"),y=p("media_filter_html"),v=p("media_url_resolver"),x=p("media_alt_source"),_=p("media_poster"),j=p("media_dimensions");var k=tinymce.util.Tools.resolve("tinymce.util.Tools"),O=tinymce.util.Tools.resolve("tinymce.dom.DOMUtils"),A=tinymce.util.Tools.resolve("tinymce.html.DomParser");const S=O.DOM,C=e=>e.replace(/px$/,""),D=e=>{const t=e.attr("style"),r=t?S.parseStyle(t):{};return{type:"ephox-embed-iri",source:e.attr("data-ephox-embed-iri"),altsource:"",poster:"",width:d(r,"max-width").map(C).getOr(""),height:d(r,"max-height").map(C).getOr("")}},T=(e,t)=>{let r={};for(let a=A({validate:!1,forced_root_block:!1},t).parse(e);a;a=a.walk())if(1===a.type){const e=a.name;if(a.attr("data-ephox-embed-iri")){r=D(a);break}r.source||"param"!==e||(r.source=a.attr("movie")),"iframe"!==e&&"object"!==e&&"embed"!==e&&"video"!==e&&"audio"!==e||(r.type||(r.type=e),r=k.extend(a.attributes.map,r)),"script"===e&&(r={type:"script",source:a.attr("src")}),"source"===e&&(r.source?r.altsource||(r.altsource=a.attr("src")):r.source=a.attr("src")),"img"!==e||r.poster||(r.poster=a.attr("src"))}return r.source=r.source||r.src||"",r.altsource=r.altsource||"",r.poster=r.poster||"",r},$=e=>{const t=e.toLowerCase().split(".").pop()??"";return d({mp3:"audio/mpeg",m4a:"audio/x-m4a",wav:"audio/wav",mp4:"video/mp4",webm:"video/webm",ogg:"video/ogg",swf:"application/x-shockwave-flash"},t).getOr("")};var z=tinymce.util.Tools.resolve("tinymce.html.Node"),M=tinymce.util.Tools.resolve("tinymce.html.Serializer");const F=(e,t={})=>A({forced_root_block:!1,validate:!1,allow_conditional_comments:!0,...t},e),N=O.DOM,R=e=>/^[0-9.]+$/.test(e)?e+"px":e,U=(e,t)=>{const r=t.attr("style"),a=r?N.parseStyle(r):{};s(e.width)&&(a["max-width"]=R(e.width)),s(e.height)&&(a["max-height"]=R(e.height)),t.attr("style",N.serializeStyle(a))},P=["source","altsource"],E=(e,t,r,a)=>{let o=0,s=0;const i=F(a);i.addNodeFilter("source",(e=>o=e.length));const c=i.parse(e);for(let e=c;e;e=e.walk())if(1===e.type){const a=e.name;if(e.attr("data-ephox-embed-iri")){U(t,e);break}switch(a){case"video":case"object":case"embed":case"img":case"iframe":void 0!==t.height&&void 0!==t.width&&(e.attr("width",t.width),e.attr("height",t.height))}if(r)switch(a){case"video":e.attr("poster",t.poster),e.attr("src",null);for(let r=o;r<2;r++)if(t[P[r]]){const a=new z("source",1);a.attr("src",t[P[r]]),a.attr("type",t[P[r]+"mime"]||null),e.append(a)}break;case"iframe":e.attr("src",t.source);break;case"object":const r=e.getAll("img").length>0;if(t.poster&&!r){e.attr("src",t.poster);const r=new z("img",1);r.attr("src",t.poster),r.attr("width",t.width),r.attr("height",t.height),e.append(r)}break;case"source":if(s<2&&(e.attr("src",t[P[s]]),e.attr("type",t[P[s]+"mime"]||null),!t[P[s]])){e.remove();continue}s++;break;case"img":t.poster||e.remove()}}return M({},a).serialize(c)},L=[{regex:/youtu\.be\/([\w\-_\?&=.]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/youtube\.com(.+)v=([^&]+)(&([a-z0-9&=\-_]+))?/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$2?$4",allowFullscreen:!0},{regex:/youtube.com\/embed\/([a-z0-9\?&=\-_]+)/i,type:"iframe",w:560,h:314,url:"www.youtube.com/embed/$1",allowFullscreen:!0},{regex:/vimeo\.com\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$1?title=0&byline=0&portrait=0&color=8dc7dc",allowFullscreen:!0},{regex:/vimeo\.com\/(.*)\/([0-9]+)/,type:"iframe",w:425,h:350,url:"player.vimeo.com/video/$2?title=0&byline=0",allowFullscreen:!0},{regex:/maps\.google\.([a-z]{2,3})\/maps\/(.+)msid=(.+)/,type:"iframe",w:425,h:350,url:'maps.google.com/maps/ms?msid=$2&output=embed"',allowFullscreen:!1},{regex:/dailymotion\.com\/video\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0},{regex:/dai\.ly\/([^_]+)/,type:"iframe",w:480,h:270,url:"www.dailymotion.com/embed/video/$1",allowFullscreen:!0}],I=(e,t)=>{const r=(e=>{const t=e.match(/^(https?:\/\/|www\.)(.+)$/i);return t&&t.length>1?"www."===t[1]?"https://":t[1]:"https://"})(t),a=e.regex.exec(t);let o=r+e.url;if(s(a))for(let e=0;ea[e]?a[e]:""));return o.replace(/\?$/,"")},B=(e,t)=>{const r=k.extend({},t);if(!r.source&&(k.extend(r,T(r.embed??"",e.schema)),!r.source))return"";r.altsource||(r.altsource=""),r.poster||(r.poster=""),r.source=e.convertURL(r.source,"source"),r.altsource=e.convertURL(r.altsource,"source"),r.sourcemime=$(r.source),r.altsourcemime=$(r.altsource),r.poster=e.convertURL(r.poster,"poster");const a=(e=>{const t=L.filter((t=>t.regex.test(e)));return t.length>0?k.extend({},t[0],{url:I(t[0],e)}):null})(r.source);if(a&&(r.source=a.url,r.type=a.type,r.allowfullscreen=a.allowFullscreen,r.width=r.width||String(a.w),r.height=r.height||String(a.h)),r.embed)return E(r.embed,r,!0,e.schema);{const t=g(e),a=b(e),o=w(e);return r.width=r.width||"300",r.height=r.height||"150",k.each(r,((t,a)=>{r[a]=e.dom.encode(""+t)})),"iframe"===r.type?((e,t)=>{if(t)return t(e);{const t=e.allowfullscreen?' allowFullscreen="1"':"";return'"}})(r,o):"application/x-shockwave-flash"===r.sourcemime?(e=>{let t='';return e.poster&&(t+=''),t+="",t})(r):-1!==r.sourcemime.indexOf("audio")?((e,t)=>t?t(e):'")(r,t):"script"===r.type?(e=>'