From 4494a40500e66c56006b545e5b57054d038e4fb4 Mon Sep 17 00:00:00 2001 From: renaud gaudin Date: Fri, 29 Jul 2022 14:58:57 +0000 Subject: [PATCH] Fixed `filesystem.get_content_mimetype()` crashing on non-guessable byte stream --- CHANGELOG.md | 6 ++ src/zimscraperlib/VERSION | 2 +- src/zimscraperlib/filesystem.py | 5 +- tests/conftest.py | 136 ++++++++++++++++++++++++++++ tests/filesystem/test_filesystem.py | 4 +- 5 files changed, 150 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a73eab3..e177cf08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project are documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) (as of version 1.5.0). +## [1.6.2] - 2022-07-29 + +### Changed + +- Fixed `filesystem.get_content_mimetype()` crashing on non-guessable byte stream + ## [1.6.1] - 2022-07-26 ### Changed diff --git a/src/zimscraperlib/VERSION b/src/zimscraperlib/VERSION index 9c6d6293..fdd3be6d 100644 --- a/src/zimscraperlib/VERSION +++ b/src/zimscraperlib/VERSION @@ -1 +1 @@ -1.6.1 +1.6.2 diff --git a/src/zimscraperlib/filesystem.py b/src/zimscraperlib/filesystem.py index a4c0ab0b..fb5b804d 100644 --- a/src/zimscraperlib/filesystem.py +++ b/src/zimscraperlib/filesystem.py @@ -31,7 +31,10 @@ def get_file_mimetype(fpath: pathlib.Path) -> str: def get_content_mimetype(content: bytes) -> str: """MIME Type of content retrieved from magic headers""" - detected_mime = magic.detect_from_content(content).mime_type + try: + detected_mime = magic.detect_from_content(content).mime_type + except UnicodeDecodeError: + return "application/octet-stream" return MIME_OVERRIDES.get(detected_mime, detected_mime) diff --git a/tests/conftest.py b/tests/conftest.py index 74a48ad9..49e706f2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -165,3 +165,139 @@ def real_zim_file(tmpdir_factory): dst, ) return dst + + +@pytest.fixture(scope="session") +def undecodable_byte_stream(): + + return ( + b"\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x01\x00\xfb\xff~\x00\x08\x00\xfd\xff\x01\x00\x00\x00" + b"\xff\xff\x03\x00\xf6\xffz\x00\x12\x00\xfa\xff\x02\x00\x00\x00" + b"\xff\xff\x04\x00\xf3\xffv\x00\x1b\x00\xf7\xff\x03\x00\xff\xff" + b"\xff\xff\x04\x00\xf0\xffp\x00%\x00\xf5\xff\x04\x00\xff\xff" + b"\xff\xff\x05\x00\xee\xffi\x000\x00\xf2\xff\x04\x00\xff\xff" + b"\xff\xff\x05\x00\xed\xffa\x00:\x00\xf0\xff\x05\x00\xff\xff" + b"\xff\xff\x06\x00\xed\xffX\x00D\x00\xee\xff\x05\x00\xff\xff" + b"\xff\xff\x06\x00\xed\xffN\x00N\x00\xed\xff\x06\x00\xff\xff" + b"\xff\xff\x05\x00\xee\xffD\x00X\x00\xed\xff\x06\x00\xff\xff" + b"\xff\xff\x05\x00\xf0\xff:\x00a\x00\xed\xff\x05\x00\xff\xff" + b"\xff\xff\x04\x00\xf2\xff0\x00i\x00\xee\xff\x05\x00\xff\xff" + b"\xff\xff\x04\x00\xf5\xff%\x00p\x00\xf0\xff\x04\x00\xff\xff" + b"\xff\xff\x03\x00\xf7\xff\x1b\x00v\x00\xf3\xff\x04\x00\xff\xff" + b"\x00\x00\x02\x00\xfa\xff\x12\x00z\x00\xf6\xff\x03\x00\xff\xff" + b"\x00\x00\x01\x00\xfd\xff\x08\x00~\x00\xfb\xff\x01\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xfd\xff\xff\xff \x00@\x00&\x00\x01\x00\xfd\xff\x00\x00" + b"\xfe\xff\xfe\xff\x1d\x00?\x00)\x00\x02\x00\xfd\xff\x00\x00" + b"\xfe\xff\xfe\xff\x1a\x00?\x00+\x00\x04\x00\xfc\xff\x00\x00" + b"\xfe\xff\xfd\xff\x18\x00>\x00.\x00\x05\x00\xfc\xff\x00\x00" + b"\xfe\xff\xfd\xff\x15\x00<\x001\x00\x07\x00\xfc\xff\x00\x00" + b"\xff\xff\xfc\xff\x12\x00;\x003\x00\t\x00\xfc\xff\x00\x00" + b"\xff\xff\xfc\xff\x10\x009\x005\x00\x0c\x00\xfc\xff\xff\xff" + b"\xff\xff\xfc\xff\x0e\x007\x007\x00\x0e\x00\xfc\xff\xff\xff" + b"\xff\xff\xfc\xff\x0c\x005\x009\x00\x10\x00\xfc\xff\xff\xff" + b"\x00\x00\xfc\xff\t\x003\x00;\x00\x12\x00\xfc\xff\xff\xff" + b"\x00\x00\xfc\xff\x07\x001\x00<\x00\x15\x00\xfd\xff\xfe\xff" + b"\x00\x00\xfc\xff\x05\x00.\x00>\x00\x18\x00\xfd\xff\xfe\xff" + b"\x00\x00\xfc\xff\x04\x00+\x00?\x00\x1a\x00\xfe\xff\xfe\xff" + b"\x00\x00\xfd\xff\x02\x00)\x00?\x00\x1d\x00\xfe\xff\xfe\xff" + b"\x00\x00\xfd\xff\x01\x00&\x00@\x00 \x00\xff\xff\xfd\xff" + b"\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xff\xff\x03\x00\xf9\xff\x7f\x00\x08\x00\xfd\xff\x01\x00\x00\x00" + b"\xfe\xff\x05\x00\xf3\xff}\x00\x11\x00\xfa\xff\x03\x00\xff\xff" + b"\xfd\xff\x07\x00\xef\xffy\x00\x1b\x00\xf6\xff\x05\x00\xfe\xff" + b"\xfc\xff\t\x00\xec\xffs\x00%\x00\xf3\xff\x06\x00\xfe\xff" + b"\xfc\xff\n\x00\xe9\xffl\x000\x00\xf0\xff\x08\x00\xfd\xff" + b"\xfc\xff\n\x00\xe8\xffd\x00;\x00\xed\xff\t\x00\xfd\xff" + b"\xfc\xff\x0b\x00\xe8\xffZ\x00F\x00\xeb\xff\n\x00\xfc\xff" + b"\xfc\xff\x0b\x00\xe9\xffP\x00P\x00\xe9\xff\x0b\x00\xfc\xff" + b"\xfc\xff\n\x00\xeb\xffF\x00Z\x00\xe8\xff\x0b\x00\xfc\xff" + b"\xfd\xff\t\x00\xed\xff;\x00d\x00\xe8\xff\n\x00\xfc\xff" + b"\xfd\xff\x08\x00\xf0\xff0\x00l\x00\xe9\xff\n\x00\xfc\xff" + b"\xfe\xff\x06\x00\xf3\xff%\x00s\x00\xec\xff\t\x00\xfc\xff" + b"\xfe\xff\x05\x00\xf6\xff\x1b\x00y\x00\xef\xff\x07\x00\xfd\xff" + b"\xff\xff\x03\x00\xfa\xff\x11\x00}\x00\xf3\xff\x05\x00\xfe\xff" + b"\x00\x00\x01\x00\xfd\xff\x08\x00\x7f\x00\xf9\xff\x03\x00\xff\xff" + b"\x00\x00\x00\x00\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00x\x00\x08\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00p\x00\x10\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00h\x00\x18\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00`\x00 \x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00X\x00(\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00P\x000\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00H\x008\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00@\x00@\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x008\x00H\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x000\x00P\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00(\x00X\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00 \x00`\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x18\x00h\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x10\x00p\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x08\x00x\x00\x00\x00\x00\x00\x00\x00" + b"\x02\x00\x00\x00\x04\x00\x00\x00\x01\x00\x00\x00\x05\x00\x00\x00" + b"\x03\x00\x00\x00\x06\x00\x00\x00\x08\x01\x00\x00\x07\x00\x00\x00" + b"\x03\x01\x00\x00\x08\x00\x00\x00\x07\x01\x00\x00\t\x00\x00\x00" + b"\t\x01\x00\x00\n\x00\x00\x00\n\x01\x00\x00\x0b\x00\x00\x00" + b"\x0b\x01\x00\x00\x0c\x00\x00\x00\x00\x01\x00\x00\r\x00\x00\x00" + b"\x01\x01\x00\x00\x0e\x00\x00\x00\x80\x00\x00\x00\x0f\x00\x00\x00" + b"\x05\x01\x00\x00\x10\x00\x00\x00\x06\x01\x00\x00\x11\x00\x00\x00" + b"\x04\x01\x00\x00\x12\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00" + b"\x07\x14!.;HUbo|\x89\x96\xa3\xb0\xbd\xca" + b"\xd7\xe4\xf1\xfe\x01\x02\x03\x04\x05\x06\x08\t\n\x0b\x0c\r" + b"\x0e\x0f\x10\x11\x12\x13\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e" + b"\x1f \"#$%&'()*+,-/0" + b"123456789:<=>?@A" + b"BCDEFGIJKLMNOPQR" + b"STVWXYZ[\\]^_`acd" + b"efghijklmnpqrstu" + b"vwxyz{}~\x7f\x80\x81\x82\x83\x84\x85\x86" + b"\x87\x88\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x97\x98" + b"\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa4\xa5\xa6\xa7\xa8\xa9" + b"\xaa\xab\xac\xad\xae\xaf\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba" + b"\xbb\xbc\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xcb\xcc" + b"\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd8\xd9\xda\xdb\xdc\xdd" + b"\xde\xdf\xe0\xe1\xe2\xe3\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee" + b"\xef\xf0\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfd\x00" + b"\x00\x07\x06\x06\x05\x05\x05\x05\x04\x04\x04\x04\x04\x04\x04\x04" + b"\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03\x03" + b"\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02" + b"\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02\x02" + b"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + b"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + b"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + b"\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\x9f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xa5\x91\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xad\x94\x8c\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xb0\x9b\x8c\x87\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xb4\x9d\x8d\x86\x82\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" + b"\xfe\xfe\xfe\xfc\xf9\xf3\xe6\xc4\xb1\x99\x8c\x85\x82\x81\x00\x00" + b"\x00\x01\x01\x02\x02\x02\x03\x03\x03\x03\x04\x04\x04\x04\x04\x04" + b"\x04\x04\x04\x04\x04\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05\x05" + b"" + ) diff --git a/tests/filesystem/test_filesystem.py b/tests/filesystem/test_filesystem.py index ff64ed86..4d7ebd1d 100644 --- a/tests/filesystem/test_filesystem.py +++ b/tests/filesystem/test_filesystem.py @@ -14,13 +14,15 @@ def test_file_mimetype(png_image, jpg_image): assert get_file_mimetype(jpg_image) == "image/jpeg" -def test_content_mimetype(png_image, jpg_image): +def test_content_mimetype(png_image, jpg_image, undecodable_byte_stream): with open(png_image, "rb") as fh: assert get_content_mimetype(fh.read(64)) == "image/png" with open(jpg_image, "rb") as fh: assert get_content_mimetype(fh.read(64)) == "image/jpeg" + assert get_content_mimetype(undecodable_byte_stream) == "application/octet-stream" + def test_mime_overrides(svg_image): mime_map = [(svg_image, "image/svg+xml")]