Commit fbf5e22 for mammothjs
commit fbf5e226ec9194ab67081cb9ecdd5f839cd87c3a
Author: Michael Williamson <mike@zwobble.org>
Date: Sun Aug 9 14:33:12 2026 +0100
Check image content type for backslashes
diff --git a/NEWS b/NEWS
index 02dd689..b4251ca 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/lib/images.js b/lib/images.js
index 40aa378..7c49dbe 100644
--- a/lib/images.js
+++ b/lib/images.js
@@ -29,3 +29,9 @@ exports.dataUri = imgElement(function(element) {
};
});
});
+
+function imageFilenameExtension(image) {
+ return image.contentType.split(/\/|\\/)[1];
+}
+
+exports.imageFilenameExtension = imageFilenameExtension;
diff --git a/lib/main.js b/lib/main.js
index f6e149f..54aeebb 100644
--- a/lib/main.js
+++ b/lib/main.js
@@ -13,22 +13,22 @@ function main(argv) {
var outputDir = argv.output_dir;
var outputFormat = argv.output_format;
var styleMapPath = argv.style_map;
-
+
readStyleMap(styleMapPath).then(function(styleMap) {
var options = {
styleMap: styleMap,
outputFormat: outputFormat
};
-
+
if (outputDir) {
var basename = path.basename(docxPath, ".docx");
outputPath = path.join(outputDir, basename + ".html");
var imageIndex = 0;
options.convertImage = images.imgElement(function(element) {
imageIndex++;
- var extension = element.contentType.split("/")[1];
- var filename = imageIndex + "." + extension;
-
+ var extension = images.imageFilenameExtension(element);
+ var filename = imageIndex + (extension === undefined ? "" : "." + extension);
+
return element.read().then(function(imageBuffer) {
var imagePath = path.join(outputDir, filename);
return promises.nfcall(fs.writeFile, imagePath, imageBuffer);
@@ -37,16 +37,16 @@ function main(argv) {
});
});
}
-
+
return mammoth.convert({path: docxPath}, options)
.then(function(result) {
result.messages.forEach(function(message) {
process.stderr.write(message.message);
process.stderr.write("\n");
});
-
+
var outputStream = outputPath ? fs.createWriteStream(outputPath) : process.stdout;
-
+
outputStream.write(result.value);
});
}).done();
diff --git a/test/images.tests.js b/test/images.tests.js
index f308174..5bcf3ba 100644
--- a/test/images.tests.js
+++ b/test/images.tests.js
@@ -110,3 +110,45 @@ test('mammoth.images.imgElement()', {
});
}
});
+
+test("imageFilenameExtension", {
+ "extension is derived from subtype of content type": function() {
+ var image = new documents.Image({
+ contentType: "image/gif"
+ });
+
+ var result = mammoth.images.imageFilenameExtension(image);
+
+ assertThat(result, equalTo("gif"));
+ },
+
+ "data after second slash is ignored": function() {
+ var image = new documents.Image({
+ contentType: "image/gif/jpeg"
+ });
+
+ var result = mammoth.images.imageFilenameExtension(image);
+
+ assertThat(result, equalTo("gif"));
+ },
+
+ "backslashes are treated as forward slashes": function() {
+ var image = new documents.Image({
+ contentType: "image\\gif\\..\\"
+ });
+
+ var result = mammoth.images.imageFilenameExtension(image);
+
+ assertThat(result, equalTo("gif"));
+ },
+
+ "when there is no subtype then null is returned": function() {
+ var image = new documents.Image({
+ contentType: "image"
+ });
+
+ var result = mammoth.images.imageFilenameExtension(image);
+
+ assertThat(result, equalTo(undefined));
+ }
+});