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 6f2aa85fef [TIKA-4780] Map ID3 TCOP and Vorbis COPYRIGHT to
xmpDM:copyright (#2940)
6f2aa85fef is described below
commit 6f2aa85fef428955224842e7515a6fa7165172d8
Author: Dominik Schmidt <[email protected]>
AuthorDate: Fri Jul 10 15:09:28 2026 +0200
[TIKA-4780] Map ID3 TCOP and Vorbis COPYRIGHT to xmpDM:copyright (#2940)
The MP4 parser already maps the cprt atom to xmpDM:copyright, but the
copyright message was dropped for the other audio formats.
MP3: handle the ID3v2 TCOP frame (TCR in ID3v2.2) following the same
pattern as the composer mapping; ID3v1 has no copyright field. The
ID3v2.3 and ID3v2.4 test fixtures gain a TCOP frame.
Ogg family (Vorbis/Opus/Speex/FLAC): map the copyright comment in the
shared OggAudioParser.extractComments. xmpDM:copyright is single-valued,
so the first comment is mapped; like the vendor comment, the raw values
all stay available under the generic vorbis:copyright name, making this
purely additive.
---
.../tika/parser/mp3/CompositeTagHandler.java | 9 +++
.../java/org/apache/tika/parser/mp3/ID3Tags.java | 5 ++
.../org/apache/tika/parser/mp3/ID3v1Handler.java | 8 +++
.../org/apache/tika/parser/mp3/ID3v22Handler.java | 8 +++
.../org/apache/tika/parser/mp3/ID3v23Handler.java | 8 +++
.../org/apache/tika/parser/mp3/ID3v24Handler.java | 8 +++
.../java/org/apache/tika/parser/mp3/Mp3Parser.java | 1 +
.../org/apache/tika/parser/ogg/OggAudioParser.java | 7 ++
.../org/apache/tika/parser/mp3/Mp3ParserTest.java | 2 +
.../apache/tika/parser/ogg/OggAudioParserTest.java | 80 +++++++++++++++++++++
.../test/resources/test-documents/testMP3id3v2.mp3 | Bin 39577 -> 39602 bytes
.../resources/test-documents/testMP3id3v24.mp3 | Bin 39471 -> 39496 bytes
12 files changed, 136 insertions(+)
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/CompositeTagHandler.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/CompositeTagHandler.java
index b7d2d75427..01ec494ada 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/CompositeTagHandler.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/CompositeTagHandler.java
@@ -76,6 +76,15 @@ public class CompositeTagHandler implements ID3Tags {
return null;
}
+ public String getCopyright() {
+ for (ID3Tags tag : tags) {
+ if (tag.getCopyright() != null) {
+ return tag.getCopyright();
+ }
+ }
+ return null;
+ }
+
public String getYear() {
for (ID3Tags tag : tags) {
if (tag.getYear() != null) {
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3Tags.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3Tags.java
index 9217156f6c..c314734881 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3Tags.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3Tags.java
@@ -184,6 +184,11 @@ public interface ID3Tags {
String getComposer();
+ /**
+ * The copyright message, if any
+ */
+ String getCopyright();
+
String getCompilation();
/**
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v1Handler.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v1Handler.java
index 7029d41d77..56c941cd93 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v1Handler.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v1Handler.java
@@ -154,6 +154,14 @@ public class ID3v1Handler implements ID3Tags {
return null;
}
+ /**
+ * ID3v1 doesn't have copyright messages,
+ * so returns null;
+ */
+ public String getCopyright() {
+ return null;
+ }
+
/**
* ID3v1 doesn't have album-wide artists,
* so returns null;
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v22Handler.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v22Handler.java
index 830f4d4431..5f0102cd03 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v22Handler.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v22Handler.java
@@ -38,6 +38,7 @@ public class ID3v22Handler implements ID3Tags {
private String album;
private String year;
private String composer;
+ private String copyright;
private String genre;
private String trackNumber;
private String albumArtist;
@@ -67,6 +68,9 @@ public class ID3v22Handler implements ID3Tags {
case "TCM":
composer = getTagString(tag.data, 0, tag.data.length);
break;
+ case "TCR":
+ copyright = getTagString(tag.data, 0, tag.data.length);
+ break;
case "COM":
comments.add(getComment(tag.data, 0, tag.data.length));
break;
@@ -133,6 +137,10 @@ public class ID3v22Handler implements ID3Tags {
return composer;
}
+ public String getCopyright() {
+ return copyright;
+ }
+
public List<ID3Comment> getComments() {
return comments;
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v23Handler.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v23Handler.java
index 23284d6773..9d10a5ac29 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v23Handler.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v23Handler.java
@@ -38,6 +38,7 @@ public class ID3v23Handler implements ID3Tags {
private String album;
private String year;
private String composer;
+ private String copyright;
private String genre;
private String trackNumber;
private String albumArtist;
@@ -68,6 +69,9 @@ public class ID3v23Handler implements ID3Tags {
case "TCOM":
composer = getTagString(tag.data, 0, tag.data.length);
break;
+ case "TCOP":
+ copyright = getTagString(tag.data, 0, tag.data.length);
+ break;
case "COMM":
comments.add(getComment(tag.data, 0, tag.data.length));
break;
@@ -119,6 +123,10 @@ public class ID3v23Handler implements ID3Tags {
return composer;
}
+ public String getCopyright() {
+ return copyright;
+ }
+
public List<ID3Comment> getComments() {
return comments;
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v24Handler.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v24Handler.java
index 9e53b77409..f9d7b106a8 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v24Handler.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/ID3v24Handler.java
@@ -39,6 +39,7 @@ public class ID3v24Handler implements ID3Tags {
private String album;
private String year;
private String composer;
+ private String copyright;
private String genre;
private String trackNumber;
private String albumArtist;
@@ -74,6 +75,9 @@ public class ID3v24Handler implements ID3Tags {
case "TCOM":
composer = getTagString(tag.data, 0, tag.data.length);
break;
+ case "TCOP":
+ copyright = getTagString(tag.data, 0, tag.data.length);
+ break;
case "COMM":
comments.add(getComment(tag.data, 0, tag.data.length));
break;
@@ -125,6 +129,10 @@ public class ID3v24Handler implements ID3Tags {
return composer;
}
+ public String getCopyright() {
+ return copyright;
+ }
+
public List<ID3Comment> getComments() {
return comments;
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
index 0fedb73b35..81b3ad7375 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/mp3/Mp3Parser.java
@@ -185,6 +185,7 @@ public class Mp3Parser implements Parser {
metadata.set(XMPDM.ARTIST, tag.getArtist());
metadata.set(XMPDM.ALBUM_ARTIST, tag.getAlbumArtist());
metadata.set(XMPDM.COMPOSER, tag.getComposer());
+ metadata.set(XMPDM.COPYRIGHT, tag.getCopyright());
metadata.set(XMPDM.ALBUM, tag.getAlbum());
metadata.set(XMPDM.COMPILATION, tag.getCompilation());
metadata.set(XMPDM.RELEASE_DATE, tag.getYear());
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
index 52538307f2..defb63361c 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/main/java/org/apache/tika/parser/ogg/OggAudioParser.java
@@ -74,6 +74,13 @@ public abstract class OggAudioParser extends AbstractParser {
metadata.add(XMP.CREATOR_TOOL, comments.getVendor());
metadata.add("vorbis:vendor", comments.getVendor());
+ //xmpDM:copyright is single-valued, so map the first comment; like
+ //vendor, the raw comments also stay available under the vorbis: name
+ List<String> copyrights = comments.getComments("copyright");
+ if (!copyrights.isEmpty()) {
+ metadata.set(XMPDM.COPYRIGHT, copyrights.get(0));
+ }
+
for (String comment : comments.getComments("comment")) {
metadata.add(XMPDM.LOG_COMMENT.getName(), comment);
}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
index c5d098ffc7..935b4be893 100644
---
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/mp3/Mp3ParserTest.java
@@ -104,6 +104,7 @@ public class Mp3ParserTest extends TikaTest {
assertEquals("Test Artist", metadata.get(XMPDM.ARTIST));
assertEquals("Test Album Artist", metadata.get(XMPDM.ALBUM_ARTIST));
assertEquals(null, metadata.get(XMPDM.COMPOSER));
+ assertEquals("Test Copyright", metadata.get(XMPDM.COPYRIGHT));
assertEquals("2008", metadata.get(XMPDM.RELEASE_DATE));
assertEquals("Rock", metadata.get(XMPDM.GENRE));
assertEquals("XXX - ID3v1 Comment\nTest Comment",
@@ -187,6 +188,7 @@ public class Mp3ParserTest extends TikaTest {
assertEquals("Test Artist", metadata.get(XMPDM.ARTIST));
assertEquals("Test Album Artist", metadata.get(XMPDM.ALBUM_ARTIST));
assertEquals(null, metadata.get(XMPDM.COMPOSER));
+ assertEquals("Test Copyright", metadata.get(XMPDM.COPYRIGHT));
assertEquals("2008", metadata.get(XMPDM.RELEASE_DATE));
assertEquals("Rock", metadata.get(XMPDM.GENRE));
assertEquals("1", metadata.get(XMPDM.COMPILATION));
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/ogg/OggAudioParserTest.java
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/ogg/OggAudioParserTest.java
new file mode 100644
index 0000000000..549885a076
--- /dev/null
+++
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/java/org/apache/tika/parser/ogg/OggAudioParserTest.java
@@ -0,0 +1,80 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tika.parser.ogg;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import org.gagravarr.vorbis.VorbisComments;
+import org.junit.jupiter.api.Test;
+import org.xml.sax.helpers.DefaultHandler;
+
+import org.apache.tika.metadata.Metadata;
+import org.apache.tika.metadata.XMPDM;
+import org.apache.tika.sax.XHTMLContentHandler;
+
+/**
+ * Tests the mapping of Vorbis-style comments shared by all Ogg family parsers
+ * (Vorbis, Opus, Speex, FLAC). The comments are fed into
+ * {@link OggAudioParser#extractComments} directly; building a valid Ogg
+ * container around them would exercise the container library rather than the
+ * mapping under test.
+ */
+public class OggAudioParserTest {
+
+ @Test
+ public void testCopyrightCommentIsMapped() throws Exception {
+ Metadata metadata = extractComments("copyright", "Test Copyright");
+
+ assertEquals("Test Copyright", metadata.get(XMPDM.COPYRIGHT));
+ //like vendor, the raw comment stays available under the vorbis: name
+ assertEquals("Test Copyright", metadata.get("vorbis:copyright"));
+ }
+
+ @Test
+ public void testAdditionalCopyrightCommentsAreKept() throws Exception {
+ Metadata metadata = extractComments("copyright", "Test Copyright",
+ "copyright", "Second Copyright");
+
+ //xmpDM:copyright is single-valued: the first comment wins, while the
+ //vorbis: passthrough keeps all values
+ assertEquals("Test Copyright", metadata.get(XMPDM.COPYRIGHT));
+ assertArrayEquals(new String[]{"Test Copyright", "Second Copyright"},
+ metadata.getValues("vorbis:copyright"));
+ }
+
+ /**
+ * Runs the given key/value comment pairs through the shared comment
+ * extraction and returns the resulting metadata.
+ */
+ private static Metadata extractComments(String... keysAndValues) throws
Exception {
+ VorbisComments comments = new VorbisComments();
+ comments.addComment("title", "Test Title");
+ comments.addComment("artist", "Test Artist");
+ comments.addComment("album", "Test Album");
+ for (int i = 0; i < keysAndValues.length; i += 2) {
+ comments.addComment(keysAndValues[i], keysAndValues[i + 1]);
+ }
+
+ Metadata metadata = new Metadata();
+ XHTMLContentHandler xhtml = new XHTMLContentHandler(new
DefaultHandler(), metadata);
+ xhtml.startDocument();
+ OggAudioParser.extractComments(metadata, xhtml, comments);
+ xhtml.endDocument();
+ return metadata;
+ }
+}
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v2.mp3
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v2.mp3
index ac96becdc9..ce40b263df 100644
Binary files
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v2.mp3
and
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v2.mp3
differ
diff --git
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v24.mp3
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v24.mp3
index 704921bd86..368360b6a5 100644
Binary files
a/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v24.mp3
and
b/tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-audiovideo-module/src/test/resources/test-documents/testMP3id3v24.mp3
differ