X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/d0fd1b7f5cabcae1809ef98ca9483c90a8899f29..refs/pull/3391/head:/app/Entities/Tools/PageContent.php diff --git a/app/Entities/Tools/PageContent.php b/app/Entities/Tools/PageContent.php index 9e2b6a7b6..b1c750adb 100644 --- a/app/Entities/Tools/PageContent.php +++ b/app/Entities/Tools/PageContent.php @@ -80,7 +80,7 @@ class PageContent */ protected function extractBase64ImagesFromHtml(string $htmlText): string { - if (empty($htmlText) || mb_strpos($htmlText, 'data:image') === false) { + if (empty($htmlText) || strpos($htmlText, 'data:image') === false) { return $htmlText; } @@ -109,15 +109,35 @@ class PageContent /** * Convert all inline base64 content to uploaded image files. + * Regex is used to locate the start of data-uri definitions then + * manual looping over content is done to parse the whole data uri. + * Attempting to capture the whole data uri using regex can cause PHP + * PCRE limits to be hit with larger, multi-MB, files. */ protected function extractBase64ImagesFromMarkdown(string $markdown) { $matches = []; - preg_match_all('/!\[.*?]\(.*?(data:image\/.*?)[)"\s]/', $markdown, $matches); + $contentLength = strlen($markdown); + $replacements = []; + preg_match_all('/!\[.*?]\(.*?(data:image\/.{1,6};base64,)/', $markdown, $matches, PREG_OFFSET_CAPTURE); + + foreach ($matches[1] as $base64MatchPair) { + [$dataUri, $index] = $base64MatchPair; + + for ($i = strlen($dataUri) + $index; $i < $contentLength; $i++) { + $char = $markdown[$i]; + if ($char === ')' || $char === ' ' || $char === "\n" || $char === '"') { + break; + } + $dataUri .= $char; + } + + $newUrl = $this->base64ImageUriToUploadedImageUrl($dataUri); + $replacements[] = [$dataUri, $newUrl]; + } - foreach ($matches[1] as $base64Match) { - $newUrl = $this->base64ImageUriToUploadedImageUrl($base64Match); - $markdown = str_replace($base64Match, $newUrl, $markdown); + foreach ($replacements as [$dataUri, $newUrl]) { + $markdown = str_replace($dataUri, $newUrl, $markdown); } return $markdown; @@ -219,6 +239,9 @@ class PageContent $html .= $doc->saveHTML($childNode); } + // Perform required string-level tweaks + $html = str_replace(' ', ' ', $html); + return $html; }