Skip to content

Commit 127665a

Browse files
authored
TIKA-4751 - decode as (#2867)
1 parent cf7d87a commit 127665a

7 files changed

Lines changed: 52 additions & 15 deletions

File tree

tika-core/src/main/java/org/apache/tika/detect/AutoDetectReader.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,12 @@ private static Charset detect(TikaInputStream tis, Metadata metadata,
100100
// Ask all given detectors for the character encoding
101101
List<EncodingResult> results = detector.detect(tis, metadata, new ParseContext());
102102
if (!results.isEmpty()) {
103-
Charset detected = results.get(0).getCharset();
104-
Charset superset = CharsetSupersets.supersetOf(detected);
105-
if (superset != null) {
106-
metadata.set(TikaCoreProperties.DECODED_CHARSET, superset.name());
107-
return superset;
103+
EncodingResult result = results.get(0);
104+
Charset decodeAs = result.getDecodeAs();
105+
if (!decodeAs.equals(result.getCharset())) {
106+
metadata.set(TikaCoreProperties.DECODED_CHARSET, decodeAs.name());
108107
}
109-
return detected;
108+
return decodeAs;
110109
}
111110

112111
// Try determining the encoding based on hints in document metadata.

tika-core/src/main/java/org/apache/tika/detect/CharsetSupersets.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,15 @@ public static Charset supersetOf(Charset detected) {
8888
return null;
8989
}
9090
}
91+
92+
/**
93+
* The charset to decode with: {@link #supersetOf(Charset) superset} of
94+
* {@code detected} if one exists, else {@code detected} (null only if
95+
* {@code detected} is null). For bare-{@link Charset} callers; detection
96+
* results can use {@link EncodingResult#getDecodeAs()}.
97+
*/
98+
public static Charset decodeAs(Charset detected) {
99+
Charset superset = supersetOf(detected);
100+
return superset != null ? superset : detected;
101+
}
91102
}

tika-core/src/main/java/org/apache/tika/detect/EncodingResult.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,24 @@ public EncodingResult(Charset charset, float confidence, String label,
126126
this.resultType = resultType;
127127
}
128128

129+
/**
130+
* The detected charset. For <em>decoding</em> bytes prefer {@link #getDecodeAs()};
131+
* this is the charset to <em>report</em> (Content-Type / detected-encoding).
132+
*/
129133
public Charset getCharset() {
130134
return charset;
131135
}
132136

137+
/**
138+
* The charset to decode with: {@link #getCharset()} widened to its superset when
139+
* one exists (e.g. GBK &rarr; GB18030), else the detected charset unchanged.
140+
*
141+
* @see CharsetSupersets
142+
*/
143+
public Charset getDecodeAs() {
144+
return CharsetSupersets.decodeAs(charset);
145+
}
146+
133147
/**
134148
* Detection confidence in {@code [0.0, 1.0]}. Meaningful for ranking
135149
* among {@link ResultType#STATISTICAL} candidates. For

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-html-module/src/main/java/org/apache/tika/parser/html/JSoupParser.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,8 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
163163
List<EncodingResult> encResults = encodingDetector.detect(tis, metadata, context);
164164
Charset charset = encResults.isEmpty() ? DEFAULT_CHARSET
165165
: encResults.get(0).getCharset();
166+
Charset decodeAs = encResults.isEmpty() ? DEFAULT_CHARSET
167+
: encResults.get(0).getDecodeAs();
166168
String previous = metadata.get(Metadata.CONTENT_TYPE);
167169
MediaType contentType = null;
168170
if (previous == null || previous.startsWith("text/html")) {
@@ -195,7 +197,7 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
195197
tis.setCloseShield();
196198
Document document;
197199
try {
198-
document = Jsoup.parse(tis, charset.name(), "",
200+
document = Jsoup.parse(tis, decodeAs.name(), "",
199201
Parser.htmlParser().tagSet(tagSet));
200202
} finally {
201203
tis.removeCloseShield();

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-microsoft-module/src/main/java/org/apache/tika/parser/microsoft/OutlookExtractor.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
import org.slf4j.LoggerFactory;
6969
import org.xml.sax.SAXException;
7070

71+
import org.apache.tika.detect.CharsetSupersets;
7172
import org.apache.tika.detect.EncodingResult;
7273
import org.apache.tika.exception.TikaException;
7374
import org.apache.tika.extractor.EmbeddedDocumentUtil;
@@ -903,7 +904,7 @@ private void guess7BitEncoding(MAPIMessage msg) {
903904
try (TikaInputStream tis = TikaInputStream.get(html.getBytes(UTF_8))) {
904905
List<EncodingResult> encResults =
905906
detector.detect(tis, EMPTY_METADATA, context);
906-
charset = encResults.isEmpty() ? null : encResults.get(0).getCharset();
907+
charset = encResults.isEmpty() ? null : encResults.get(0).getDecodeAs();
907908
} catch (IOException e) {
908909
//swallow
909910
}
@@ -921,9 +922,16 @@ private void guess7BitEncoding(MAPIMessage msg) {
921922
CharsetDetector detector = new CharsetDetector();
922923
detector.setText(text.getRawValue());
923924
CharsetMatch match = detector.detect();
924-
if (match != null && match.getConfidence() > 35 &&
925-
tryToSet7BitEncoding(msg, match.getName())) {
926-
return;
925+
if (match != null && match.getConfidence() > 35) {
926+
String charsetName = match.getName();
927+
try {
928+
charsetName = CharsetSupersets.decodeAs(Charset.forName(charsetName)).name();
929+
} catch (IllegalArgumentException e) {
930+
//ICU name not a resolvable Java charset; use as-is
931+
}
932+
if (tryToSet7BitEncoding(msg, charsetName)) {
933+
return;
934+
}
927935
}
928936
}
929937
}

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-miscoffice-module/src/main/java/org/apache/tika/parser/dbf/DBFParser.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.xml.sax.SAXException;
3131

3232
import org.apache.tika.config.TikaComponent;
33+
import org.apache.tika.detect.CharsetSupersets;
3334
import org.apache.tika.detect.EncodingDetector;
3435
import org.apache.tika.detect.EncodingResult;
3536
import org.apache.tika.exception.TikaException;
@@ -89,14 +90,16 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
8990

9091
Charset charset = getCharset(firstRows, header, context);
9192
metadata.set(Metadata.CONTENT_ENCODING, charset.toString());
93+
//report detected (above); decode with its superset
94+
Charset decodeAs = CharsetSupersets.decodeAs(charset);
9295

9396
XHTMLContentHandler xhtml = new XHTMLContentHandler(handler, metadata, context);
9497
xhtml.startDocument();
9598
xhtml.startElement("table");
9699
xhtml.startElement("thead");
97100
for (DBFColumnHeader col : header.getCols()) {
98101
xhtml.startElement("th");
99-
xhtml.characters(col.getName(charset));
102+
xhtml.characters(col.getName(decodeAs));
100103
xhtml.endElement("th");
101104
}
102105
xhtml.endElement("thead");
@@ -106,12 +109,12 @@ public void parse(TikaInputStream tis, ContentHandler handler, Metadata metadata
106109
//now write cached rows
107110
while (firstRows.size() > 0) {
108111
DBFRow cachedRow = firstRows.remove(0);
109-
writeRow(cachedRow, charset, xhtml);
112+
writeRow(cachedRow, decodeAs, xhtml);
110113
}
111114

112115
//now continue with rest
113116
while (row != null) {
114-
writeRow(row, charset, xhtml);
117+
writeRow(row, decodeAs, xhtml);
115118
row = reader.next();
116119
}
117120
xhtml.endElement("tbody");

tika-parsers/tika-parsers-standard/tika-parsers-standard-modules/tika-parser-pkg-module/src/main/java/org/apache/tika/parser/pkg/ZipParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -565,7 +565,7 @@ private String detectEntryName(ZipArchiveEntry entry, Metadata parentMetadata,
565565
try (TikaInputStream detectStream = TikaInputStream.get(entryName)) {
566566
List<EncodingResult> encResults =
567567
getEncodingDetector().detect(detectStream, parentMetadata, context);
568-
Charset candidate = encResults.isEmpty() ? null : encResults.get(0).getCharset();
568+
Charset candidate = encResults.isEmpty() ? null : encResults.get(0).getDecodeAs();
569569
if (candidate != null) {
570570
return new String(entry.getRawName(), candidate);
571571
}

0 commit comments

Comments
 (0)