UNPKG

@geogirafe/lib-geoportal

Version:

GeoGirafe is a flexible application to build online geoportals.

75 lines (74 loc) 3.46 kB
import DOMPurify from 'dompurify'; /** * Use DOMPurify.sanitize to remove potentially harmful html/js code. * @param unsanitized the raw text to sanitize. * @param config Allowed tags and elements in a string. */ export const sanitize = (unsanitized, config) => { let sanitizeConfig = { ...config.query.sanitizeConfig }; if (config.query.legacy) { sanitizeConfig = { ...sanitizeConfig, ADD_ATTR: ['onclick', 'data-gopenwindow'], ADD_URI_SAFE_ATTR: ['onclick'] }; } if (unsanitized.includes('gOpenWindow')) { const unsanitizedWithDataGOpenWindow = transformOpenWindowLinksToData(unsanitized); const sanitized = DOMPurify.sanitize(unsanitizedWithDataGOpenWindow, sanitizeConfig); return transformDataOpenWindowToLinks(sanitized); } return DOMPurify.sanitize(unsanitized, sanitizeConfig); }; /** A join tmp marker used to split again a string. */ const gOpenWindowSplitArgChar = '°°°'; /** * Transforms a text (link) with <a href="javascript:gOpenWindow(args)">text</a> to a text without href and * with a new "data-gopenwindow='args'". This allows sanitizing a string and keeping the * GOpenWindow function arguments. */ const transformOpenWindowLinksToData = (text) => { // Long regexp because we want to capture all arguments, 4 are optional and can be text or number. // Title and or url can contain any character, including comma. const gOpenWindowLinkRegExp = /<a\b[^>]*\bhref\s*=\s*"javascript:(?:window\.)?gOpenWindow\(\s*'([^']*)'\s*,\s*'([^']*)'(?:\s*,\s*(?:'([^']*)'|(\d+)))?(?:\s*,\s*(?:'([^']*)'|(\d+)))?(?:\s*,\s*(?:'([^']*)'|(\d+)))?(?:\s*,\s*(?:'([^']*)'|(\d+)))?\s*\)\s*;"[^>]*>([\s\S]*?)<\/a>/gi; return text.replace(gOpenWindowLinkRegExp, (_, title, url, widthText, widthNumber, heightText, heightNumber, topText, topNumber, leftText, leftNumber, text) => { const width = widthText ? `'${widthText}'` : widthNumber; const height = heightText ? `'${heightText}'` : heightNumber; const top = topText ? `'${topText}'` : topNumber; const left = leftText ? `'${leftText}'` : leftNumber; const gOpenWindowArgs = [title, url]; if (width) gOpenWindowArgs.push(width); if (height) gOpenWindowArgs.push(height); if (top) gOpenWindowArgs.push(top); if (left) gOpenWindowArgs.push(left); return `<a data-gopenwindow="${gOpenWindowArgs.join(gOpenWindowSplitArgChar)}">${text}</a>`; }); }; /** * Transforms a text (link) with a new "data-gopenwindow='args'" to a text like * <a href="javascript:gOpenWindow(args)">text</a>.The args are split by * the gOpenWindowSplitArgChar. */ const transformDataOpenWindowToLinks = (text) => { const gOpenWindowDataRegExp = /<a\s+data-gopenwindow="([^"]*)">([^"]*)<\/a>/gi; return text.replace(gOpenWindowDataRegExp, (_, data, text) => { const [title, url, width, height, top, left] = data.split(gOpenWindowSplitArgChar); const urlParts = [`<a href="javascript:gOpenWindow('${title}', '${url}'`]; if (width) urlParts.push(`, ${width}`); if (height) urlParts.push(`, ${height}`); if (top) urlParts.push(`, ${top}`); if (left) urlParts.push(`, ${left}`); urlParts.push(`);">${text}</a>`); return urlParts.join(''); }); };