1
0
mirror of https://github.com/BookStackApp/BookStack.git synced 2025-08-09 10:22:51 +03:00

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.
This commit is contained in:
Dan Brown
2022-05-23 16:11:28 +01:00
parent 1d1186c901
commit 05f8034439
2 changed files with 24 additions and 9 deletions

View File

@@ -215,14 +215,13 @@ class ExportFormatter
*/ */
protected function containHtml(string $htmlContent): string protected function containHtml(string $htmlContent): string
{ {
// Replace image & embed src attributes with base64 encoded data strings
$imageTagsOutput = []; $imageTagsOutput = [];
preg_match_all("/\<img.*?src\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $imageTagsOutput); preg_match_all("/<(?:img|embed) .*?src=['\"](.*?)['\"].*?>/i", $htmlContent, $imageTagsOutput);
// Replace image src with base64 encoded image strings
if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) { if (isset($imageTagsOutput[0]) && count($imageTagsOutput[0]) > 0) {
foreach ($imageTagsOutput[0] as $index => $imgMatch) { foreach ($imageTagsOutput[0] as $index => $imgMatch) {
$oldImgTagString = $imgMatch; $oldImgTagString = $imgMatch;
$srcString = $imageTagsOutput[2][$index]; $srcString = $imageTagsOutput[1][$index];
$imageEncoded = $this->imageService->imageUriToBase64($srcString); $imageEncoded = $this->imageService->imageUriToBase64($srcString);
if ($imageEncoded === null) { if ($imageEncoded === null) {
$imageEncoded = $srcString; $imageEncoded = $srcString;
@@ -232,14 +231,13 @@ class ExportFormatter
} }
} }
// Replace any relative links with full system URL
$linksOutput = []; $linksOutput = [];
preg_match_all("/\<a.*href\=(\'|\")(.*?)(\'|\").*?\>/i", $htmlContent, $linksOutput); preg_match_all("/<a .*href=['\"](.*?)['\"].*?>/i", $htmlContent, $linksOutput);
// Replace image src with base64 encoded image strings
if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) { if (isset($linksOutput[0]) && count($linksOutput[0]) > 0) {
foreach ($linksOutput[0] as $index => $linkMatch) { foreach ($linksOutput[0] as $index => $linkMatch) {
$oldLinkString = $linkMatch; $oldLinkString = $linkMatch;
$srcString = $linksOutput[2][$index]; $srcString = $linksOutput[1][$index];
if (strpos(trim($srcString), 'http') !== 0) { if (strpos(trim($srcString), 'http') !== 0) {
$newSrcString = url($srcString); $newSrcString = url($srcString);
$newLinkString = str_replace($srcString, $newSrcString, $oldLinkString); $newLinkString = str_replace($srcString, $newSrcString, $oldLinkString);
@@ -248,7 +246,6 @@ class ExportFormatter
} }
} }
// Replace any relative links with system domain
return $htmlContent; return $htmlContent;
} }

View File

@@ -258,6 +258,24 @@ class ExportTest extends TestCase
unlink($testFilePath); unlink($testFilePath);
} }
public function test_page_export_contained_html_embed_element_srcs_are_inlined()
{
$page = Page::query()->first();
$page->html = '<embed src="http://localhost/uploads/images/gallery/svg_test.svg"/>';
$page->save();
$storageDisk = Storage::disk('local');
$storageDisk->makeDirectory('uploads/images/gallery');
$storageDisk->put('uploads/images/gallery/svg_test.svg', '<svg>good</svg>');
$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('<embed src="data:image/svg+xml;base64,PHN2Zz5nb29kPC9zdmc+">', false);
}
public function test_exports_removes_scripts_from_custom_head() public function test_exports_removes_scripts_from_custom_head()
{ {
$entities = [ $entities = [