@geogirafe/lib-geoportal
Version:
GeoGirafe is a flexible application to build online geoportals.
75 lines (74 loc) • 3.46 kB
JavaScript
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('');
});
};