From 20192063f3470f1740051895136504cabf2fec6a Mon Sep 17 00:00:00 2001 From: alexandraRamanenka Date: Mon, 4 Dec 2023 16:25:46 +0200 Subject: [PATCH 1/3] FIO-7544: Fixes an issue where scripts inside HTML component will be executed during interpolation --- src/components/html/HTML.js | 22 ++++++++++++++------ src/components/html/HTML.unit.js | 18 ++++++++++++++++- src/components/html/fixtures/comp3.js | 29 +++++++++++++++++++++++++++ src/components/html/fixtures/index.js | 3 ++- 4 files changed, 64 insertions(+), 8 deletions(-) create mode 100644 src/components/html/fixtures/comp3.js diff --git a/src/components/html/HTML.js b/src/components/html/HTML.js index cd4838da13..327f5b36de 100644 --- a/src/components/html/HTML.js +++ b/src/components/html/HTML.js @@ -26,6 +26,14 @@ export default class HTMLComponent extends Component { }; } + constructor(...args) { + const alert = window.alert; + window.alert = (msg) => { + return alert(msg); + }; + super(...args); + } + static savedValueTypes() { return []; } @@ -45,13 +53,15 @@ export default class HTMLComponent extends Component { } const submission = _.get(this.root, 'submission', {}); - const content = this.component.content ? this.interpolate(this.component.content, { - metadata: submission.metadata || {}, - submission: submission, - data: this.rootValue, - row: this.data + const content = this.component.content ? this.interpolate( + this.sanitize(this.component.content, this.shouldSanitizeValue), + { + metadata: submission.metadata || {}, + submission: submission, + data: this.rootValue, + row: this.data }) : ''; - return this.sanitize(content, this.shouldSanitizeValue); + return content; } get singleTags() { diff --git a/src/components/html/HTML.unit.js b/src/components/html/HTML.unit.js index 1ffe31ebb1..f5bac52a5c 100644 --- a/src/components/html/HTML.unit.js +++ b/src/components/html/HTML.unit.js @@ -1,3 +1,4 @@ +import Webform from '../../Webform'; import Harness from '../../../test/harness'; import HTMLComponent from './HTML'; import sinon from 'sinon'; @@ -5,7 +6,8 @@ import assert from 'power-assert'; import { comp1, - comp2 + comp2, + comp3, } from './fixtures'; describe('HTML Component', () => { @@ -30,4 +32,18 @@ describe('HTML Component', () => { assert.equal(emit.callCount, 0); }); }); + + it('Should not execute scripts inside HTML component', (done) => { + const formElement = document.createElement('div'); + const form = new Webform(formElement); + + const alert = sinon.spy(window, 'alert'); + form.setForm(comp3).then(() => { + setTimeout(() => { + assert.equal(alert.callCount, 0); + done(); + }, 200); + }) + .catch(done); + }); }); diff --git a/src/components/html/fixtures/comp3.js b/src/components/html/fixtures/comp3.js new file mode 100644 index 0000000000..12a0d3d6dd --- /dev/null +++ b/src/components/html/fixtures/comp3.js @@ -0,0 +1,29 @@ +export default { + type: 'form', + display: 'form', + components: [ + { + label: 'HTML', + attrs: [ + { + attr: '', + value: '', + }, + ], + content: '', + refreshOnChange: false, + key: 'html', + type: 'htmlelement', + input: false, + tableView: false, + }, + { + type: 'button', + label: 'Submit', + key: 'submit', + disableOnInvalid: true, + input: true, + tableView: false, + }, + ], +}; diff --git a/src/components/html/fixtures/index.js b/src/components/html/fixtures/index.js index 7c38dd8065..63f18da5cf 100644 --- a/src/components/html/fixtures/index.js +++ b/src/components/html/fixtures/index.js @@ -1,3 +1,4 @@ import comp1 from './comp1'; import comp2 from './comp2'; -export { comp1, comp2 }; +import comp3 from './comp3'; +export { comp1, comp2, comp3 }; From 0b458dfb58a8a3235b30769c38588d89c32dd449 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka Date: Thu, 14 Dec 2023 15:52:51 +0200 Subject: [PATCH 2/3] Refactoring --- src/components/html/HTML.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/components/html/HTML.js b/src/components/html/HTML.js index 327f5b36de..16653f32ea 100644 --- a/src/components/html/HTML.js +++ b/src/components/html/HTML.js @@ -26,14 +26,6 @@ export default class HTMLComponent extends Component { }; } - constructor(...args) { - const alert = window.alert; - window.alert = (msg) => { - return alert(msg); - }; - super(...args); - } - static savedValueTypes() { return []; } From 213b6a186a82dee240eae6ed6c49c08d8d362876 Mon Sep 17 00:00:00 2001 From: alexandraRamanenka Date: Tue, 9 Apr 2024 15:08:43 +0300 Subject: [PATCH 3/3] Added test for interpolation in HTML component --- src/components/html/HTML.unit.js | 16 ++++++++++++++-- src/components/html/fixtures/comp3.js | 13 +++++++++++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/components/html/HTML.unit.js b/src/components/html/HTML.unit.js index f5bac52a5c..73906c2cbd 100644 --- a/src/components/html/HTML.unit.js +++ b/src/components/html/HTML.unit.js @@ -33,7 +33,7 @@ describe('HTML Component', () => { }); }); - it('Should not execute scripts inside HTML component', (done) => { + it('Should not execute scripts inside HTML component, but execute interpolation properly', (done) => { const formElement = document.createElement('div'); const form = new Webform(formElement); @@ -41,7 +41,19 @@ describe('HTML Component', () => { form.setForm(comp3).then(() => { setTimeout(() => { assert.equal(alert.callCount, 0); - done(); + const div = form.element.querySelector('.myClass'); + assert.equal(div.innerHTML.trim(), 'No Text'); + + const textField = form.getComponent(['textField']); + textField.setValue('apple', { modified: true }); + + setTimeout(() => { + const div = form.element.querySelector('.myClass'); + + assert.equal(div.innerHTML.trim(), 'apple'); + assert.equal(div.className, 'myClass apple-class'); + done(); + }, 400); }, 200); }) .catch(done); diff --git a/src/components/html/fixtures/comp3.js b/src/components/html/fixtures/comp3.js index 12a0d3d6dd..bc9fcab428 100644 --- a/src/components/html/fixtures/comp3.js +++ b/src/components/html/fixtures/comp3.js @@ -2,6 +2,14 @@ export default { type: 'form', display: 'form', components: [ + { + label: 'Text Field', + applyMaskOn: 'change', + tableView: true, + key: 'textField', + type: 'textfield', + input: true, + }, { label: 'HTML', attrs: [ @@ -10,8 +18,9 @@ export default { value: '', }, ], - content: '', - refreshOnChange: false, + content: '\n
{{' + + ' data.textField ? data.textField : \'No Text\'}}
', + refreshOnChange: true, key: 'html', type: 'htmlelement', input: false,