From c062d0589b32459fa69359cb67a87eb63ba359d2 Mon Sep 17 00:00:00 2001 From: Karishma Chadha <kchadha@media.mit.edu> Date: Mon, 4 Feb 2019 21:31:37 -0500 Subject: [PATCH] Escape special characters in user defined strings that can appear in the toolbox xml. --- src/lib/make-toolbox-xml.js | 16 ++++++++++++++++ test/integration/blocks.test.js | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/src/lib/make-toolbox-xml.js b/src/lib/make-toolbox-xml.js index 4217b6e6b..3443e05d2 100644 --- a/src/lib/make-toolbox-xml.js +++ b/src/lib/make-toolbox-xml.js @@ -138,6 +138,18 @@ const motion = function (isStage, targetId) { `; }; +const xmlEscape = function (unsafe) { + return unsafe.replace(/[<>&'"]/g, c => { + switch (c) { + case '<': return '<'; + case '>': return '>'; + case '&': return '&'; + case '\'': return '''; + case '"': return '"'; + } + }); +}; + const looks = function (isStage, targetId, costumeName, backdropName) { const hello = ScratchBlocks.ScratchMsgs.translate('LOOKS_HELLO', 'Hello!'); const hmm = ScratchBlocks.ScratchMsgs.translate('LOOKS_HMM', 'Hmm...'); @@ -714,6 +726,10 @@ const makeToolboxXML = function (isStage, targetId, categoriesXML, costumeName = '', backdropName = '', soundName = '') { const gap = [categorySeparator]; + costumeName = xmlEscape(costumeName); + backdropName = xmlEscape(backdropName); + soundName = xmlEscape(soundName); + const everything = [ xmlOpen, motion(isStage, targetId), gap, diff --git a/test/integration/blocks.test.js b/test/integration/blocks.test.js index d70396032..b39f05a79 100644 --- a/test/integration/blocks.test.js +++ b/test/integration/blocks.test.js @@ -191,6 +191,24 @@ describe('Working with the blocks', () => { await clickText('newname', scope.blocksTab); }); + test('Renaming costume with a special character should not break toolbox', async () => { + await loadUri(uri); + await clickXpath('//button[@title="Try It"]'); + + // Rename the costume + await clickText('Costumes'); + const el = await findByXpath("//input[@value='costume1']"); + await el.sendKeys('<NewCostume>'); + + // Make sure it is updated in the block menu + await clickText('Code'); + await clickText('Looks', scope.blocksTab); + await driver.sleep(500); // Wait for scroll to finish + await clickText('<NewCostume>', scope.blocksTab); + + await clickText('Sound', scope.blocksTab); + }); + // NOTE: This test describes the current behavior so that changes are not // introduced inadvertly, but I know this is not the desired behavior test('Adding costumes DOES NOT update the default costume name in the toolbox', async () => { -- GitLab