feat: experimental version of sanboxing

This commit is contained in:
Knut Sveidqvist
2022-01-20 19:37:52 +01:00
parent 3a2f6659a6
commit 4081d7f5f6
7 changed files with 138 additions and 34 deletions

View File

@@ -232,10 +232,40 @@ const render = function (id, _txt, cb, container) {
txt = 'graph TB;a[Maximum text size in diagram exceeded];style a fill:#faa';
}
// let d3Iframe;
let root;
if (cnf.securityLevel === 'sandbox') {
// IF we are in sandboxed mode, we do everyting mermaid related
// in a sandboxed div
const iframe = select('body')
.append('iframe')
.attr('id', 'i' + id)
.attr('sandbox', '');
// const iframeBody = ;
root = select(iframe.nodes()[0].contentDocument.body);
} else {
root = select('body');
}
// In regular execurtion the container will be the div with a mermaid class
if (typeof container !== 'undefined') {
// A container was provided by the caller
container.innerHTML = '';
select(container)
if (cnf.securityLevel === 'sandbox') {
// IF we are in sandboxed mode, we do everyting mermaid related
// in a sandboxed div
const iframe = select(container)
.append('iframe')
.attr('id', 'i' + id)
.attr('sandbox', '');
// const iframeBody = ;
root = select(iframe.nodes()[0].contentDocument.body);
} else {
root = select(container);
}
root
.append('div')
.attr('id', 'd' + id)
.attr('style', 'font-family: ' + cnf.fontFamily)
@@ -245,18 +275,42 @@ const render = function (id, _txt, cb, container) {
.attr('xmlns', 'http://www.w3.org/2000/svg')
.append('g');
} else {
// No container was provided
// If there is an existsing element with the id, we remove it
// this likley a previously rendered diagram
const existingSvg = document.getElementById(id);
if (existingSvg) {
existingSvg.remove();
}
const element = document.querySelector('#' + 'd' + id);
// Remove previous tpm element if it exists
let element;
if (cnf.securityLevel === 'sandbox') {
element = document.querySelector('#' + 'd' + id);
} else {
element = document.querySelector('#' + 'i' + id);
}
if (element) {
element.remove();
}
select('body')
// if (cnf.securityLevel === 'sandbox') {
// const iframe = select('body')
// .append('iframe')
// .attr('id', 'i' + id)
// .attr('sandbox', '');
// // const iframeBody = ;
// root = select(iframe.nodes()[0].contentDocument.body);
// }
// Add the tmp div used for rendering with the id `d${id}`
// d+id it will contain a svg with the id "id"
// This is the temporary div
root
.append('div')
.attr('id', 'd' + id)
// this is the seed of the svg to be rendered
.append('svg')
.attr('id', id)
.attr('width', '100%')
@@ -264,10 +318,10 @@ const render = function (id, _txt, cb, container) {
.append('g');
}
window.txt = txt;
txt = encodeEntities(txt);
const element = select('#d' + id).node();
// Get the tmp element containing the the svg
const element = root.select('#d' + id).node();
const graphType = utils.detectType(txt, cnf);
// insert inline style into svg
@@ -430,22 +484,51 @@ const render = function (id, _txt, cb, container) {
throw e;
}
select(`[id="${id}"]`)
root
.select(`[id="${id}"]`)
.selectAll('foreignobject > *')
.attr('xmlns', 'http://www.w3.org/1999/xhtml');
// Fix for when the base tag is used
let svgCode = select('#d' + id).node().innerHTML;
let svgCode = root.select('#d' + id).node().innerHTML;
log.debug('cnf.arrowMarkerAbsolute', cnf.arrowMarkerAbsolute);
if (!cnf.arrowMarkerAbsolute || cnf.arrowMarkerAbsolute === 'false') {
svgCode = svgCode.replace(/marker-end="url\(.*?#/g, 'marker-end="url(#', 'g');
}
// const iframe = document.createElement('iframe');
// iframe.setAttribute('frameBorder', '0');
// iframe.setAttribute('id', id);
// iframe.setAttribute('sanbox', '');
// iframe.setAttribute('src', 'about:blank');
// iframe.contentWindow.document.body = svgCode;
// element.innerHTML = '';
// // element.appendChild(iframe);
// // element.innerHTML = '<iframe sandbox>' + svgCode + '</iframe>';
svgCode = decodeEntities(svgCode);
// Fix for when the br tag is used
svgCode = svgCode.replace(/<br>/g, '<br/>');
if (cnf.securityLevel === 'sandbox') {
// const newSvgCode =
// '<iframe id="' +
// id +
// '" sandbox src="data:text/html;base64,' +
// btoa(btoa(unescape(encodeURIComponent(svgCode)))) +
// '"></iframe>';
// svgCode = newSvgCode;
// svgCode = `<iframe src="data:text/html;base64,V2VsY29tZSB0byA8Yj5iYXNlNjQuZ3VydTwvYj4h">
// The “iframe” tag is not supported by your browser.
// </iframe>`;
svgCode = `<iframe style="width:100%;height:100%;" src="data:text/html;base64,${btoa(
svgCode
)}" sandbox>
The “iframe” tag is not supported by your browser.
</iframe>`;
}
if (typeof cb !== 'undefined') {
switch (graphType) {
case 'flowchart':
@@ -467,11 +550,10 @@ const render = function (id, _txt, cb, container) {
}
attachFunctions();
const node = select('#d' + id).node();
const tmpElementSelector = cnf.securityLevel === 'sandbox' ? '#i' + id : '#d' + id;
const node = select(tmpElementSelector).node();
if (node !== null && typeof node.remove === 'function') {
select('#d' + id)
.node()
.remove();
select(tmpElementSelector).node().remove();
}
return svgCode;
@@ -570,6 +652,7 @@ function updateRendererConfigs(conf) {
errorRenderer.setConf(conf.class);
}
/** To be removed */
function reinitialize() {
// `mermaidAPI.reinitialize: v${pkg.version}`,
// JSON.stringify(options),