From: Dan Brown Date: Mon, 23 May 2022 15:11:28 +0000 (+0100) Subject: Added embed support for contained HTML exports X-Git-Url: http://source.bookstackapp.com/bookstack/commitdiff_plain/05f8034439e528fad272ab46e3698e998fa01cf1 Added embed support for contained HTML exports Unfortunately CSP rules will block embeds anyway. Need to either relax CSP rules on exports, or instead convert to img tags? Also cleaned up existing regexes. --- diff --git a/app/Entities/Tools/ExportFormatter.php b/app/Entities/Tools/ExportFormatter.php index 99aa4536f..ed3e8d326 100644 --- a/app/Entities/Tools/ExportFormatter.php +++ b/app/Entities/Tools/ExportFormatter.php @@ -215,14 +215,13 @@ class ExportFormatter */ protected function containHtml(string $htmlContent): string { + // Replace image & embed src attributes with base64 encoded data strings $imageTagsOutput = []; - preg_match_all("/\/i", $htmlContent, $imageTagsOutput); - - // Replace image src with base64 encoded image strings + preg_match_all("/<(?:img|embed) .*?src=['\"](.*?)['\"].*?>/i", $htmlContent, $imageTagsOutput); if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) { foreach ($imageTagsOutput[0] as $index => $imgMatch) { $oldImgTagString = $imgMatch; - $srcString = $imageTagsOutput[2][$index]; + $srcString = $imageTagsOutput[1][$index]; $imageEncoded = $this->imageService->imageUriToBase64($srcString); if ($imageEncoded === null) { $imageEncoded = $srcString; @@ -232,14 +231,13 @@ class ExportFormatter } } + // Replace any relative links with full system URL $linksOutput = []; - preg_match_all("/\/i", $htmlContent, $linksOutput); - - // Replace image src with base64 encoded image strings + preg_match_all("//i", $htmlContent, $linksOutput); if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) { foreach ($linksOutput[0] as $index => $linkMatch) { $oldLinkString = $linkMatch; - $srcString = $linksOutput[2][$index]; + $srcString = $linksOutput[1][$index]; if (strpos(trim($srcString), 'http') !== 0) { $newSrcString = url($srcString); $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString); @@ -248,7 +246,6 @@ class ExportFormatter } } - // Replace any relative links with system domain return $htmlContent; } diff --git a/tests/Entity/ExportTest.php b/tests/Entity/ExportTest.php index 08d092111..9debec12b 100644 --- a/tests/Entity/ExportTest.php +++ b/tests/Entity/ExportTest.php @@ -258,6 +258,24 @@ class ExportTest extends TestCase unlink($testFilePath); } + public function test_page_export_contained_html_embed_element_srcs_are_inlined() + { + $page = Page::query()->first(); + $page->html = ''; + $page->save(); + + $storageDisk = Storage::disk('local'); + $storageDisk->makeDirectory('uploads/images/gallery'); + $storageDisk->put('uploads/images/gallery/svg_test.svg', 'good'); + + $resp = $this->asEditor()->get($page->getUrl('/export/html')); + + $storageDisk->delete('uploads/images/gallery/svg_test.svg'); + + $resp->assertDontSee('http://localhost/uploads/images/gallery/svg_test.svg', false); + $resp->assertSee('', false); + } + public function test_exports_removes_scripts_from_custom_head() { $entities = [