fix: handle invalid images in HTML (#27095)

* fix: handle invalid image

* refactor: simplify broken image replacement

* fix: add alt attribute to broken image
This commit is contained in:
Raffael Meyer 2024-07-16 14:15:43 +02:00 committed by GitHub
parent 5a1d670f0b
commit 1fe0f6e20b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 31 additions and 2 deletions

View file

@ -17,7 +17,7 @@ from frappe.core.api.file import (
unzip_file,
)
from frappe.core.doctype.file.exceptions import FileTypeNotAllowed
from frappe.core.doctype.file.utils import get_extension
from frappe.core.doctype.file.utils import get_corrupted_image_msg, get_extension
from frappe.desk.form.utils import add_comment
from frappe.exceptions import ValidationError
from frappe.tests.utils import FrappeTestCase, change_settings
@ -768,6 +768,25 @@ class TestFileUtils(FrappeTestCase):
)
self.assertRegex(communication.content, r"<img src=\"(.*)/files/pix\.png(.*)\">")
def test_broken_image(self):
"""Ensure that broken inline images don't cause errors."""
is_private = not frappe.get_meta("Communication").make_attachments_public
communication = frappe.get_doc(
doctype="Communication",
communication_type="Communication",
communication_medium="Email",
content='<div class="ql-editor read-mode"><img src="data:image/png;filename=pix.png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CY="></div>',
recipients="to <to@test.com>",
cc=None,
bcc=None,
sender="sender@test.com",
).insert(ignore_permissions=True)
self.assertFalse(
frappe.db.exists("File", {"attached_to_name": communication.name, "is_private": is_private})
)
self.assertIn(f'<img src="#broken-image" alt="{get_corrupted_image_msg()}">', communication.content)
def test_create_new_folder(self):
folder = create_new_folder("test_folder", "Home")
self.assertTrue(folder.is_folder)

View file

@ -2,6 +2,7 @@ import hashlib
import mimetypes
import os
import re
from binascii import Error as BinasciiError
from io import BytesIO
from typing import TYPE_CHECKING, Optional
from urllib.parse import unquote
@ -234,7 +235,12 @@ def extract_images_from_html(doc: "Document", content: str, is_private: bool = F
content = content.encode("utf-8")
if b"," in content:
content = content.split(b",")[1]
content = safe_b64decode(content)
try:
content = safe_b64decode(content)
except BinasciiError:
frappe.flags.has_dataurl = True
return f'<img src="#broken-image" alt="{get_corrupted_image_msg()}"'
if "filename=" in headers:
filename = headers.split("filename=")[-1]
@ -273,6 +279,10 @@ def extract_images_from_html(doc: "Document", content: str, is_private: bool = F
return content
def get_corrupted_image_msg():
return _("Image: Corrupted Data Stream")
def get_random_filename(content_type: str | None = None) -> str:
extn = None
if content_type: