support sandboxed markdown plugins

This commit is contained in:
ed 2023-01-29 00:57:08 +00:00
parent c50cb66aef
commit 2569005139
3 changed files with 39 additions and 17 deletions

View file

@ -6605,7 +6605,7 @@ function show_md(md, name, div, url, depth) {
md_plug = {} md_plug = {}
md = load_md_plug(md, 'pre'); md = load_md_plug(md, 'pre');
md = load_md_plug(md, 'post'); md = load_md_plug(md, 'post', sb_md);
var marked_opts = { var marked_opts = {
headerPrefix: 'md-', headerPrefix: 'md-',
@ -6618,7 +6618,8 @@ function show_md(md, name, div, url, depth) {
try { try {
clmod(div, 'mdo', 1); clmod(div, 'mdo', 1);
sandbox(div, sb_md, 'mdo', marked.parse(md, marked_opts)); if (sandbox(div, sb_md, 'mdo', marked.parse(md, marked_opts)))
return;
ext = md_plug.post; ext = md_plug.post;
ext = ext ? [ext[0].render, ext[0].render2] : []; ext = ext ? [ext[0].render, ext[0].render2] : [];
@ -6687,13 +6688,20 @@ function sandbox(tgt, rules, cls, html) {
want = hash.slice(1); want = hash.slice(1);
html = '<html class="' + document.documentElement.className + '"><head><style>' + globalcss() + html = '<html class="' + document.documentElement.className + '"><head><style>' + globalcss() +
'</style><base target="_parent"></head><body class="logue ' + cls + '">' + html + '</style><base target="_parent"></head><body id="b" class="logue ' + cls + '">' + html +
'<script>setTimeout(function(){var its=0,pih=-1,f=function(){' + '<script src="' + SR + '/.cpr/util.js?_={{ ts }}"></script>' +
'var d=document.documentElement,ih=2+Math.min(parseInt(getComputedStyle(d).height),d.scrollHeight);' + '<script>var ebi=document.getElementById.bind(document),d=document.documentElement,' +
'loc=new URL("' + location.href.split('?')[0] + '");' +
'setTimeout(function(){var its=0,pih=-1,f=function(){' +
'var ih=2+Math.min(parseInt(getComputedStyle(d).height),d.scrollHeight);' +
'if(ih!=pih){pih=ih;window.parent.postMessage("iheight #' + tid + '>iframe "+ih,"*")}' + 'if(ih!=pih){pih=ih;window.parent.postMessage("iheight #' + tid + '>iframe "+ih,"*")}' +
'if(++its<20)return setTimeout(f,20);if(its==20)setInterval(f,200)' + 'if(++its<20)return setTimeout(f,20);if(its==20)setInterval(f,200)' +
'};f();var el="' + want + '"&&document.getElementById("' + want + '");' + '};f();var el="' + want + '"&&ebi("' + want + '");' +
'if(el)window.parent.postMessage("iscroll #' + tid + ' "+el.offsetTop,"*")' + 'if(el)window.parent.postMessage("iscroll #' + tid + ' "+el.offsetTop,"*");' +
(cls == 'mdo' && md_plug.post ?
'const x={' + md_plug.post + '};' +
'if(x.render)x.render(ebi("b"));' +
'if(x.render2)x.render2(ebi("b"));' : '') +
'},1)</script></body></html>'; '},1)</script></body></html>';
var fr = mknod('iframe'); var fr = mknod('iframe');

View file

@ -1532,25 +1532,33 @@ var md_plug_err = function (ex, js) {
if (ex) if (ex)
console.log(ex, js); console.log(ex, js);
}; };
function load_md_plug(md_text, plug_type) { function load_md_plug(md_text, plug_type, defer) {
if (defer)
md_plug[plug_type] = null;
if (!have_emp) if (!have_emp)
return md_text; return md_text;
var find = '\n```copyparty_' + plug_type + '\n'; var find = '\n```copyparty_' + plug_type + '\n',
var ofs = md_text.indexOf(find); md = md_text.replace(/\r/g, ''),
if (ofs === -1) ofs = md.indexOf(find),
ofs2 = md.indexOf('\n```', ofs + 1);
if (ofs < 0 || ofs2 < 0)
return md_text; return md_text;
var ofs2 = md_text.indexOf('\n```', ofs + 1); var js = md.slice(ofs + find.length, ofs2 + 1);
if (ofs2 == -1) md = md.slice(0, ofs + 1) + md.slice(ofs2 + 4);
return md_text; md = md.replace(/$/g, '\r');
var js = md_text.slice(ofs + find.length, ofs2 + 1); if (defer) { // insert into sandbox
var md = md_text.slice(0, ofs + 1) + md_text.slice(ofs2 + 4); md_plug[plug_type] = js;
return md;
}
var old_plug = md_plug[plug_type]; var old_plug = md_plug[plug_type];
if (!old_plug || old_plug[1] != js) { if (!old_plug || old_plug[1] != js) {
js = 'const x = { ' + js + ' }; x;'; js = 'const loc = new URL("' + location.href + '"), x = { ' + js + ' }; x;';
try { try {
var x = eval(js); var x = eval(js);
if (x['ctor']) { if (x['ctor']) {

View file

@ -54,6 +54,8 @@ the values in the `ex:` columns are linkified to `example.com/$value`
and the table can be sorted by clicking the headers and the table can be sorted by clicking the headers
the sandbox also makes `location` unavailable but there is `loc` instead; this website's url is <big><big><b id="whereami">foo</b></big></big>
the difference is that with `copyparty_pre` you'll probably break various copyparty features but if you use `copyparty_post` then future copyparty versions will probably break you the difference is that with `copyparty_pre` you'll probably break various copyparty features but if you use `copyparty_post` then future copyparty versions will probably break you
@ -136,6 +138,10 @@ render(dom) {
} }
}, },
render2(dom) { render2(dom) {
// loc == window.location except available inside sandbox
ebi('whereami').innerHTML = loc.href;
// this one also works because util.js gets pulled into the sandbox
window.makeSortable(dom.getElementsByTagName('table')[0]); window.makeSortable(dom.getElementsByTagName('table')[0]);
} }
``` ```