diff options
| -rw-r--r-- | NEWS | 5 | ||||
| -rw-r--r-- | mammoth/cli.py | 20 | ||||
| -rw-r--r-- | mammoth/images.py | 9 | ||||
| -rw-r--r-- | tests/images_tests.py | 35 |
4 files changed, 58 insertions, 11 deletions
@@ -1,3 +1,8 @@ +# 1.12.1 + +* Fix: on Windows, when an image's content type includes a backslash in the + subpart, files may be written outside of the directory set by --output-dir. + # 1.12.0 * Handle hyperlinked wp:anchor and wp:inline elements. diff --git a/mammoth/cli.py b/mammoth/cli.py index b759412..08b67c6 100644 --- a/mammoth/cli.py +++ b/mammoth/cli.py @@ -10,13 +10,13 @@ from . import writers def main(): args = _parse_args() - + if args.style_map is None: style_map = None else: with open(args.style_map) as style_map_fileobj: style_map = style_map_fileobj.read() - + with open(args.path, "rb") as docx_fileobj: if args.output_dir is None: convert_image = None @@ -25,7 +25,7 @@ def main(): convert_image = mammoth.images.img_element(ImageWriter(args.output_dir)) output_filename = "{0}.html".format(os.path.basename(args.path).rpartition(".")[0]) output_path = os.path.join(args.output_dir, output_filename) - + result = mammoth.convert( docx_fileobj, style_map=style_map, @@ -35,7 +35,7 @@ def main(): for message in result.messages: sys.stderr.write(message.message) sys.stderr.write("\n") - + _write_output(output_path, result.value) @@ -43,16 +43,16 @@ class ImageWriter(object): def __init__(self, output_dir): self._output_dir = output_dir self._image_number = 1 - + def __call__(self, element): - extension = element.content_type.partition("/")[2] + extension = mammoth.images.image_filename_extension(element) image_filename = "{0}.{1}".format(self._image_number, extension) with open(os.path.join(self._output_dir, image_filename), "wb") as image_dest: with element.open() as image_source: shutil.copyfileobj(image_source, image_dest) - + self._image_number += 1 - + return {"src": image_filename} @@ -76,7 +76,7 @@ def _parse_args(): "path", metavar="docx-path", help="Path to the .docx file to convert.") - + output_group = parser.add_mutually_exclusive_group() output_group.add_argument( "output", @@ -86,7 +86,7 @@ def _parse_args(): output_group.add_argument( "--output-dir", help="Output directory for generated HTML and images. Images will be stored in separate files. Mutually exclusive with output-path.") - + parser.add_argument( "--output-format", required=False, diff --git a/mammoth/images.py b/mammoth/images.py index 21b9288..1623a73 100644 --- a/mammoth/images.py +++ b/mammoth/images.py @@ -1,4 +1,5 @@ import base64 +import re from . import html @@ -26,3 +27,11 @@ def data_uri(image): return { "src": "data:{0};base64,{1}".format(image.content_type, encoded_src) } + + +def image_filename_extension(image): + result = re.split(r"/|\\", image.content_type) + if len(result) < 2: + return None + else: + return result[1] diff --git a/tests/images_tests.py b/tests/images_tests.py index 6e2487d..024aeb0 100644 --- a/tests/images_tests.py +++ b/tests/images_tests.py @@ -1,6 +1,6 @@ import io -from precisely import assert_that, has_attrs, is_sequence +from precisely import assert_that, equal_to, has_attrs, is_sequence import mammoth @@ -78,3 +78,36 @@ class ImgElementTests: assert_that(result, is_sequence( has_attrs(attributes={"alt": "<alt override>", "src": "<src>"}), )) + + +class ImageFilenameExtensionTests: + def test_extension_is_derived_from_subtype_of_content_type(self): + image = self._image_with_content_type("image/gif") + + result = mammoth.images.image_filename_extension(image) + + assert_that(result, equal_to("gif")) + + def test_data_after_second_slash_is_ignored(self): + image = self._image_with_content_type("image/gif/jpeg") + + result = mammoth.images.image_filename_extension(image) + + assert_that(result, equal_to("gif")) + + def test_backslashes_are_treated_as_forward_slashes(self): + image = self._image_with_content_type("image\\gif\\..\\") + + result = mammoth.images.image_filename_extension(image) + + assert_that(result, equal_to("gif")) + + def test_when_there_is_no_subtype_then_none_is_returned(self): + image = self._image_with_content_type("image") + + result = mammoth.images.image_filename_extension(image) + + assert_that(result, equal_to(None)) + + def _image_with_content_type(self, content_type): + return mammoth.documents.Image(alt_text="", content_type=content_type, open=None) |
