diff --git a/frappe/tests/test_utils.py b/frappe/tests/test_utils.py
index 496083de18..3093fba8b0 100644
--- a/frappe/tests/test_utils.py
+++ b/frappe/tests/test_utils.py
@@ -1679,3 +1679,19 @@ class TestDataUtils(UnitTestCase):
self.assertEqual(comma_or(["a", "b", "c"]), "'a', 'b' ou 'c'")
self.assertEqual(comma_or(["a", "b", "c"], add_quotes=False), "a, b ou c")
+
+
+class TestMsgPrint(UnitTestCase):
+ def tearDown(self) -> None:
+ super().tearDown()
+ frappe.clear_messages()
+
+ def test_msgprint(self):
+ frappe.msgprint("Validate: ")
+ message = frappe.get_message_log()[-1]
+
+ self.assertNotIn("script", message.message)
+
+ frappe.msgprint("
")
+ message = frappe.get_message_log()[-1]
+ self.assertIn("- ", message.message)
diff --git a/frappe/utils/messages.py b/frappe/utils/messages.py
index b7bb665387..3ced869043 100644
--- a/frappe/utils/messages.py
+++ b/frappe/utils/messages.py
@@ -1,4 +1,3 @@
-import functools
import sys
from collections.abc import Sequence
from typing import Literal
@@ -8,8 +7,6 @@ from frappe import _
from frappe.utils import strip_html_tags
from frappe.utils.data import safe_decode
-_strip_html_tags = functools.lru_cache(maxsize=1024)(strip_html_tags)
-
def msgprint(
msg: str | Sequence[str] | Sequence[Sequence[str]],
@@ -24,6 +21,7 @@ def msgprint(
wide: bool = False,
*,
realtime=False,
+ allow_dangerous_html=False,
) -> None:
"""Print a message to the user (via HTTP response).
Messages are sent in the `__server_messages` property in the
@@ -38,9 +36,12 @@ def msgprint(
:param is_minimizable: [optional] Allow users to minimize the modal
:param wide: [optional] Show wide modal
:param realtime: Publish message immediately using websocket.
+ :param allow_dangerous_html: Allow arbitrary HTML in message.
"""
import inspect
+ from frappe.utils.html_utils import clean_html
+
msg = safe_decode(msg)
out = frappe._dict(message=msg)
@@ -67,13 +68,21 @@ def msgprint(
else:
out.as_table = as_table
+ if not allow_dangerous_html:
+ if out.as_list:
+ out.message = [clean_html(cell) for cell in msg]
+ elif out.as_table:
+ out.message = [[clean_html(cell) for cell in row] for row in msg]
+ else:
+ out.message = clean_html(msg)
+
if sys.stdin and sys.stdin.isatty():
if out.as_list:
- msg = [_strip_html_tags(cell) for cell in msg]
+ msg = [strip_html_tags(cell) for cell in msg]
elif out.as_table:
- msg = [[_strip_html_tags(cell) for cell in row] for row in msg]
+ msg = [[strip_html_tags(cell) for cell in row] for row in msg]
else:
- msg = _strip_html_tags(msg)
+ msg = strip_html_tags(msg)
if frappe.flags.print_messages and out.message:
print(f"Message: {msg}")
@@ -134,6 +143,8 @@ def throw(
wide: bool = False,
as_list: bool = False,
primary_action=None,
+ *,
+ allow_dangerous_html=False,
) -> None:
"""Throw execption and show message (`msgprint`).
@@ -154,6 +165,7 @@ def throw(
wide=wide,
as_list=as_list,
primary_action=primary_action,
+ allow_dangerous_html=allow_dangerous_html,
)