This is an automated email from the ASF dual-hosted git repository.
tballison pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git
The following commit(s) were added to refs/heads/main by this push:
new 749d2f1c62 TIKA-5031: parse 3MF packages as zip, not XML (#3529)
749d2f1c62 is described below
commit 749d2f1c6210490d917f21b18d4e33e10182b51a
Author: Dominik Schmidt <[email protected]>
AuthorDate: Wed Nov 4 22:49:51 2026 +0100
TIKA-5031: parse 3MF packages as zip, not XML (#3529)
---
CHANGES.txt | 3 +++
.../resources/org/apache/tika/mime/tika-mimetypes.xml | 2 ++
.../java/org/apache/tika/parser/pkg/ZipParserTest.java | 15 +++++++++++++++
.../tika/detect/microsoft/ooxml/OPCPackageDetector.java | 1 +
.../main/java/org/apache/tika/parser/pkg/ZipParser.java | 1 +
5 files changed, 22 insertions(+)
diff --git a/CHANGES.txt b/CHANGES.txt
index a851f5c04a..41c1c3714b 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -56,6 +56,9 @@ Release 4.3.0 - ???
EXTRACTION AND FORMATS
+ * 3MF packages are parsed as zip packages instead of failing as XML: the
type is a
+ sub-type of application/zip, and the streaming zip detector recognizes it
(TIKA-5031).
+
* New SubtitleParser for WebVTT (.vtt) and SubRip (.srt). Each cue becomes
<div class="cue"> with data-start/data-end (HH:MM:SS.mmm) and data-id,
its text
cleaned of markup; WebVTT NOTE blocks become <div class="note"> and a
Language
diff --git
a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
index 36fbecbea0..984eaf40e5 100644
--- a/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
+++ b/tika-core/src/main/resources/org/apache/tika/mime/tika-mimetypes.xml
@@ -2226,6 +2226,8 @@
<mime-type type="application/vnd.ms-package.3dmanufacturing-3dmodel+xml">
<tika:link>https://en.wikipedia.org/wiki/3D_Manufacturing_Format</tika:link>
<_comment>3D manufacturing format</_comment>
+ <!-- a zip package; without this, the +xml suffix would make it an XML
document -->
+ <sub-class-of type="application/zip"/>
<glob pattern="*.3mf"/>
</mime-type>
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/pkg/ZipParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/pkg/ZipParserTest.java
index 232522bdf2..9752ae8d2b 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/pkg/ZipParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-integration-tests/src/test/java/org/apache/tika/parser/pkg/ZipParserTest.java
@@ -18,6 +18,7 @@ package org.apache.tika.parser.pkg;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.util.HashSet;
@@ -91,6 +92,20 @@ public class ZipParserTest extends AbstractPkgTest {
assertTrue(extractor.allInternalPaths.contains("test2.txt"));
}
+ @Test
+ public void test3MFIsParsedAsZip() throws Exception {
+ List<Metadata> metadataList = getRecursiveMetadata("test3mf.3mf");
+ Metadata container = metadataList.get(0);
+ assertEquals("application/vnd.ms-package.3dmanufacturing-3dmodel+xml",
+ container.get(HttpHeaders.CONTENT_TYPE));
+ assertNull(container.get(TikaCoreProperties.CONTAINER_EXCEPTION));
+ Set<String> names = new HashSet<>();
+ for (Metadata m : metadataList.subList(1, metadataList.size())) {
+ names.add(m.get(TikaCoreProperties.RESOURCE_NAME_KEY));
+ }
+ assertTrue(names.contains("3D/3dmodel.model"), names.toString());
+ }
+
@Test
public void testZipEncrypted() throws Exception {
List<Metadata> metadataList =
getRecursiveMetadata("testZipEncrypted.zip");
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/ooxml/OPCPackageDetector.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/ooxml/OPCPackageDetector.java
index 8378d9b19c..1e60fed208 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/ooxml/OPCPackageDetector.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/detect/microsoft/ooxml/OPCPackageDetector.java
@@ -145,6 +145,7 @@ public class OPCPackageDetector implements
ZipContainerDetector {
MediaType.application("vnd.ms-visio.template"));
OOXML_CONTENT_TYPES.put("application/vnd.ms-package.xps-fixeddocumentsequence+xml",
XPS);
+ OOXML_CONTENT_TYPES.put(THREE_MF.toString(), THREE_MF);
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java
index 28e3830c15..c0a97b8fd3 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java
@@ -146,6 +146,7 @@ public class ZipParser extends AbstractArchiveParser {
"application/vnd.ms-excel.sheet.binary.macroenabled.12",
"application/vnd.ms-excel.sheet.macroenabled.12",
"application/vnd.ms-excel.template.macroenabled.12",
+ "application/vnd.ms-package.3dmanufacturing-3dmodel+xml",
"application/vnd.ms-powerpoint.addin.macroenabled.12",
"application/vnd.ms-powerpoint.presentation.macroenabled.12",
"application/vnd.ms-powerpoint.slide.macroenabled.12",