aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--mammoth/cli.py20
-rw-r--r--mammoth/images.py9
-rw-r--r--tests/images_tests.py35
4 files changed, 58 insertions, 11 deletions
diff --git a/NEWS b/NEWS
index 8de02f5..66e134e 100644
--- a/NEWS
+++ b/NEWS
@@ -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)