diff options
Diffstat (limited to 'src/main.rs')
-rw-r--r-- | src/main.rs | 51 |
1 files changed, 38 insertions, 13 deletions
diff --git a/src/main.rs b/src/main.rs index a5b7ce0..58431a2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -265,17 +265,18 @@ async fn service<C: Controller>( }); // we rely on CSP to thwart XSS attacks, all modern browsers support it - resp.headers_mut().insert( - header::CONTENT_SECURITY_POLICY, - format!( - "default-src 'self'; frame-src {}; script-src {}; style-src {}", - frame_csp, - script_csp, - include_str!("static/style.css.sha"), - ) - .parse() - .unwrap(), - ); + resp.headers_mut() + .entry(header::CONTENT_SECURITY_POLICY) + .or_insert_with(|| { + format!( + "default-src 'self'; frame-src {}; script-src {}; style-src {}", + frame_csp, + script_csp, + include_str!("static/style.css.sha"), + ) + .parse() + .unwrap() + }); Ok(resp) } @@ -526,16 +527,40 @@ impl Context { } } -fn render_markdown(input: &str, page: &mut Page) { +#[derive(PartialEq)] +enum RenderMode { + View, + Preview, +} + +fn render_markdown(input: &str, page: &mut Page, _mode: RenderMode) { let parser = Parser::new_ext(input, Options::all()); page.body.push_str("<div class=markdown-output>"); html::push_html(&mut page.body, parser); page.body.push_str("</div>"); } -fn get_renderer(path: &Path) -> Option<fn(&str, &mut Page)> { +fn embed_html_as_iframe(input: &str, page: &mut Page, mode: RenderMode) { + if mode == RenderMode::View { + page.body.push_str("<iframe src='?action=run'></iframe>"); + page.frame_src = Some("'self'"); + } else { + page.body + .push_str("<div class=note>Note that JavaScript does not work in the preview.</div>"); + // sandbox=allow-scripts wouldn't work because the strict parent page CSP still applies + + // The sandbox attribute makes browsers treat the embedded page as a unique origin. + page.body.push_str(&format!( + "<iframe srcdoc='{}' sandbox></iframe>", + html_escape(input) + )); + } +} + +fn get_renderer(path: &Path) -> Option<fn(&str, &mut Page, RenderMode)> { match path.extension().map(|e| e.to_str().unwrap()) { Some("md") => Some(render_markdown), + Some("html") => Some(embed_html_as_iframe), _ => None, } } |