diff --git a/python/semantic_kernel/contents/utils/data_uri.py b/python/semantic_kernel/contents/utils/data_uri.py index 22f514fac9b0..bdbbdbc7d351 100644 --- a/python/semantic_kernel/contents/utils/data_uri.py +++ b/python/semantic_kernel/contents/utils/data_uri.py @@ -135,7 +135,16 @@ def from_data_uri(cls: type[_T], data_uri: str | Url, default_mime_type: str = " if not data or "," not in data: raise ContentInitializationError("Invalid data uri format. The data is missing.") - pattern = "(((?P[a-zA-Z]+/[a-zA-Z-]+)(?P(;[a-zA-Z0-9]+=+[a-zA-Z0-9]+)*))?(;+(?P.*)))?(,(?P.*))" # noqa: E501 + # Media types and parameters use the RFC 6838/RFC 2045 token character set, which + # includes characters such as "+" (image/svg+xml) and "-" (charset=utf-8). Keeping + # the data format as a token prevents unparsed parameters from being silently + # treated as part of the format (for example "charset=utf-8;base64"). + pattern = ( + r"(((?P[a-zA-Z0-9!#$&^_.+-]+/[a-zA-Z0-9!#$&^_.+-]+)" + r"(?P(;[a-zA-Z0-9!#$&^_.+-]+=+[a-zA-Z0-9!#$&^_.+-]+)*))?" + r"(;+(?P[a-zA-Z0-9!#$&^_.+-]*))?)?" + r"(,(?P.*))" + ) match = re.match(pattern, data) if not match: raise ContentInitializationError("Invalid data uri format.") diff --git a/python/tests/unit/contents/test_data_uri.py b/python/tests/unit/contents/test_data_uri.py index fc98679a9765..28decca895a9 100644 --- a/python/tests/unit/contents/test_data_uri.py +++ b/python/tests/unit/contents/test_data_uri.py @@ -66,6 +66,33 @@ "base64", id="with_params", ), + pytest.param( + "data:image/svg+xml;base64,PHN2Zy8+", + b"", + "PHN2Zy8+", + "image/svg+xml", + {}, + "base64", + id="mime_type_with_plus", + ), + pytest.param( + "data:text/plain;charset=utf-8;base64,SGVsbG8=", + b"Hello", + "SGVsbG8=", + "text/plain", + {"charset": "utf-8"}, + "base64", + id="parameter_before_data_format", + ), + pytest.param( + "data:application/vnd.ms-excel;base64,AAAA", + b"\x00\x00\x00", + "AAAA", + "application/vnd.ms-excel", + {}, + "base64", + id="vendor_mime_type", + ), ], ) def test_data_uri_from_data_uri_str( diff --git a/python/tests/unit/contents/test_image_content.py b/python/tests/unit/contents/test_image_content.py index 7d84a1746271..aeec05f6f1dd 100644 --- a/python/tests/unit/contents/test_image_content.py +++ b/python/tests/unit/contents/test_image_content.py @@ -38,6 +38,12 @@ def test_create_data(): assert image.data == b"test_data" +def test_create_svg_data_uri(): + image = ImageContent(data_uri="data:image/svg+xml;base64,PHN2Zy8+") + assert image.mime_type == "image/svg+xml" + assert image.data == b"" + + def test_to_str_uri(): image = ImageContent(uri="http://test_uri") assert str(image) == "http://test_uri/"