From af1c2928e565c6c7bb0b02150110b091533ff7fe Mon Sep 17 00:00:00 2001 From: Johannes Raggam Date: Thu, 14 Mar 2024 18:19:44 +0100 Subject: [PATCH] Improve contenttype detection logic for unregistered but common types. Change get_contenttype to support common types which are or were not registered with IANA, like image/webp or audio/midi. Note: image/webp is already a IANA registered type and also added by Products.MimetypesRegistry. --- news/157-2.feature | 8 ++++ plone/namedfile/tests/test_image.py | 20 --------- plone/namedfile/tests/test_utils.py | 64 +++++++++++++++++++++++++++++ plone/namedfile/utils/__init__.py | 4 +- 4 files changed, 73 insertions(+), 23 deletions(-) create mode 100644 news/157-2.feature create mode 100644 plone/namedfile/tests/test_utils.py diff --git a/news/157-2.feature b/news/157-2.feature new file mode 100644 index 00000000..3de1ec23 --- /dev/null +++ b/news/157-2.feature @@ -0,0 +1,8 @@ +Improve contenttype detection logic for unregistered but common types. + +Change get_contenttype to support common types which are or were not registered +with IANA, like image/webp or audio/midi. + +Note: image/webp is already a IANA registered type and also added by +Products.MimetypesRegistry. +[thet] diff --git a/plone/namedfile/tests/test_image.py b/plone/namedfile/tests/test_image.py index 8aa7f273..5c4db43c 100644 --- a/plone/namedfile/tests/test_image.py +++ b/plone/namedfile/tests/test_image.py @@ -89,23 +89,3 @@ def test_extract_media_type(self): self.assertEqual(extract("TEXT/PLAIN"), "text/plain") self.assertEqual(extract("text / plain"), "text/plain") self.assertEqual(extract(" text/plain ; charset=utf-8"), "text/plain") - - def test_get_contenttype(self): - self.assertEqual( - get_contenttype(NamedImage(getFile("image.gif"), contentType="image/gif")), - "image/gif", - ) - self.assertEqual( - get_contenttype(NamedImage(getFile("image.gif"), filename="image.gif")), - "image/gif", - ) - self.assertEqual( - get_contenttype(NamedImage(getFile("image.tif"), filename="image.tif")), - "image/tiff", - ) - self.assertEqual( - get_contenttype( - NamedImage(getFile("notimage.doc"), filename="notimage.doc") - ), - "application/msword", - ) diff --git a/plone/namedfile/tests/test_utils.py b/plone/namedfile/tests/test_utils.py new file mode 100644 index 00000000..4ef9bff7 --- /dev/null +++ b/plone/namedfile/tests/test_utils.py @@ -0,0 +1,64 @@ +from plone.namedfile.file import NamedImage +from plone.namedfile.tests import getFile +from plone.namedfile.utils import get_contenttype + +import unittest + + +class TestUtils(unittest.TestCase): + + def test_get_contenttype(self): + self.assertEqual( + get_contenttype( + NamedImage( + getFile("image.gif"), + contentType="image/gif", + ) + ), + "image/gif", + ) + self.assertEqual( + get_contenttype( + NamedImage( + getFile("image.gif"), + filename="image.gif", + ) + ), + "image/gif", + ) + self.assertEqual( + get_contenttype( + NamedImage( + getFile("image.tif"), + filename="image.tif", + ) + ), + "image/tiff", + ) + self.assertEqual( + get_contenttype( + NamedImage( + getFile("notimage.doc"), + filename="notimage.doc", + ) + ), + "application/msword", + ) + + # Filename only detection of a non-IANA registered type. + self.assertEqual( + get_contenttype(filename="image.webp"), + "image/webp", + ) + + # Filename only detection of a non-IANA registered type. + self.assertEqual( + get_contenttype(filename="song.midi"), + "audio/midi", + ) + + # Detection of a surely not registered type. + self.assertEqual( + get_contenttype(filename="nothing.plonenamedfile"), + "application/octet-stream", + ) diff --git a/plone/namedfile/utils/__init__.py b/plone/namedfile/utils/__init__.py index b27c8820..2f17ead9 100644 --- a/plone/namedfile/utils/__init__.py +++ b/plone/namedfile/utils/__init__.py @@ -14,7 +14,6 @@ from ZPublisher.Iterators import IStreamIterator import mimetypes -import os.path import piexif import PIL.Image import re @@ -126,8 +125,7 @@ def get_contenttype(file=None, filename=None, default="application/octet-stream" filename = getattr(file, "filename", filename) if filename: - extension = os.path.splitext(filename)[1].lower() - return mimetypes.types_map.get(extension, "application/octet-stream") + return mimetypes.guess_type(filename, strict=False)[0] or default return default