mirror of
https://github.com/BookStackApp/BookStack.git
synced 2024-10-01 01:36:00 -04:00
Made MD editor display a sandboxed iframe
- Also added escaping of srcdoc elements in escape logic. Related to #1531
This commit is contained in:
parent
2dfe6c2d56
commit
7cc17934a8
@ -766,7 +766,7 @@ class EntityRepo
|
||||
}
|
||||
|
||||
// Remove data or JavaScript iFrames
|
||||
$badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')]');
|
||||
$badIframes = $xPath->query('//*[contains(@src, \'data:\')] | //*[contains(@src, \'javascript:\')] | //*[@srcdoc]');
|
||||
foreach ($badIframes as $badIframe) {
|
||||
$badIframe->parentNode->removeChild($badIframe);
|
||||
}
|
||||
|
@ -18,6 +18,8 @@ class MarkdownEditor {
|
||||
this.markdown.use(mdTasksLists, {label: true});
|
||||
|
||||
this.display = this.elem.querySelector('.markdown-display');
|
||||
this.displayDoc = this.display.contentDocument;
|
||||
this.displayStylesLoaded = false;
|
||||
this.input = this.elem.querySelector('textarea');
|
||||
this.htmlInput = this.elem.querySelector('input[name=html]');
|
||||
this.cm = code.markdownEditor(this.input);
|
||||
@ -38,7 +40,7 @@ class MarkdownEditor {
|
||||
let lastClick = 0;
|
||||
|
||||
// Prevent markdown display link click redirect
|
||||
this.display.addEventListener('click', event => {
|
||||
this.displayDoc.addEventListener('click', event => {
|
||||
let isDblClick = Date.now() - lastClick < 300;
|
||||
|
||||
let link = event.target.closest('a');
|
||||
@ -96,17 +98,37 @@ class MarkdownEditor {
|
||||
|
||||
// Update the input content and render the display.
|
||||
updateAndRender() {
|
||||
let content = this.cm.getValue();
|
||||
const content = this.cm.getValue();
|
||||
this.input.value = content;
|
||||
let html = this.markdown.render(content);
|
||||
const html = this.markdown.render(content);
|
||||
window.$events.emit('editor-html-change', html);
|
||||
window.$events.emit('editor-markdown-change', content);
|
||||
this.display.innerHTML = html;
|
||||
|
||||
// Set body content
|
||||
this.displayDoc.body.className = 'page-content';
|
||||
this.displayDoc.body.innerHTML = html;
|
||||
this.htmlInput.value = html;
|
||||
|
||||
// Copy styles from page head and set custom styles for editor
|
||||
this.loadStylesIntoDisplay();
|
||||
}
|
||||
|
||||
loadStylesIntoDisplay() {
|
||||
if (this.displayStylesLoaded) return;
|
||||
this.displayDoc.documentElement.className = 'markdown-editor-display';
|
||||
|
||||
this.displayDoc.head.innerHTML = '';
|
||||
const styles = document.head.querySelectorAll('style,link[rel=stylesheet]');
|
||||
for (let style of styles) {
|
||||
const copy = style.cloneNode(true);
|
||||
this.displayDoc.head.appendChild(copy);
|
||||
}
|
||||
|
||||
this.displayStylesLoaded = true;
|
||||
}
|
||||
|
||||
onMarkdownScroll(lineCount) {
|
||||
const elems = this.display.children;
|
||||
const elems = this.displayDoc.body.children;
|
||||
if (elems.length <= lineCount) return;
|
||||
|
||||
const topElem = (lineCount === -1) ? elems[elems.length-1] : elems[lineCount];
|
||||
|
@ -93,13 +93,15 @@
|
||||
}
|
||||
|
||||
.markdown-display {
|
||||
padding: 0 $-m 0;
|
||||
margin-left: -1px;
|
||||
overflow-y: scroll;
|
||||
&.page-content {
|
||||
margin: 0 auto;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown-editor-display {
|
||||
background-color: #FFFFFF;
|
||||
body {
|
||||
background-color: #FFFFFF;
|
||||
padding-left: 16px;
|
||||
padding-right: 16px;
|
||||
}
|
||||
[drawio-diagram]:hover {
|
||||
outline: 2px solid var(--color-primary);
|
||||
|
@ -116,6 +116,7 @@ body.flexbox {
|
||||
min-height: 0;
|
||||
max-width: 100%;
|
||||
position: relative;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.flex {
|
||||
|
@ -28,8 +28,7 @@
|
||||
<div class="editor-toolbar">
|
||||
<div class="editor-toolbar-label">{{ trans('entities.pages_md_preview') }}</div>
|
||||
</div>
|
||||
<div class="markdown-display page-content">
|
||||
</div>
|
||||
<iframe class="markdown-display" sandbox="allow-same-origin"></iframe>
|
||||
</div>
|
||||
<input type="hidden" name="html"/>
|
||||
|
||||
|
@ -118,7 +118,7 @@ class PageContentTest extends TestCase
|
||||
'<iframe SRC=" javascript: alert(document.cookie)"></iframe>',
|
||||
'<iframe src="data:text/html;base64,PHNjcmlwdD5hbGVydCgnaGVsbG8nKTwvc2NyaXB0Pg==" frameborder="0"></iframe>',
|
||||
'<iframe src=" data:text/html;base64,PHNjcmlwdD5hbGVydCgnaGVsbG8nKTwvc2NyaXB0Pg==" frameborder="0"></iframe>',
|
||||
|
||||
'<iframe srcdoc="<script>window.alert(document.cookie)</script>"></iframe>'
|
||||
];
|
||||
|
||||
$this->asEditor();
|
||||
|
Loading…
Reference in New Issue
Block a user