|
| 1 | +/* |
| 2 | + * Licensed to the Apache Software Foundation (ASF) under one or more |
| 3 | + * contributor license agreements. See the NOTICE file distributed with |
| 4 | + * this work for additional information regarding copyright ownership. |
| 5 | + * The ASF licenses this file to You under the Apache License, Version 2.0 |
| 6 | + * (the "License"); you may not use this file except in compliance with |
| 7 | + * the License. You may obtain a copy of the License at |
| 8 | + * |
| 9 | + * http://www.apache.org/licenses/LICENSE-2.0 |
| 10 | + * |
| 11 | + * Unless required by applicable law or agreed to in writing, software |
| 12 | + * distributed under the License is distributed on an "AS IS" BASIS, |
| 13 | + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 14 | + * See the License for the specific language governing permissions and |
| 15 | + * limitations under the License. |
| 16 | + */ |
| 17 | +package org.apache.tika.parser.microsoft.rtf.jflex; |
| 18 | + |
| 19 | +import java.nio.charset.Charset; |
| 20 | +import java.nio.charset.StandardCharsets; |
| 21 | +import java.util.Collections; |
| 22 | +import java.util.HashMap; |
| 23 | +import java.util.Map; |
| 24 | + |
| 25 | +import org.apache.tika.utils.CharsetUtils; |
| 26 | + |
| 27 | +/** |
| 28 | + * Shared charset maps for RTF parsing. Maps RTF {@code \fcharsetN} and |
| 29 | + * {@code \ansicpgN} values to Java {@link Charset} instances. |
| 30 | + * |
| 31 | + * <p>Extracted from the original {@code TextExtractor} so both the JFlex-based |
| 32 | + * parser and decapsulator can reuse them.</p> |
| 33 | + */ |
| 34 | +public final class RTFCharsetMaps { |
| 35 | + |
| 36 | + public static final Charset WINDOWS_1252 = Charset.forName("windows-1252"); |
| 37 | + |
| 38 | + /** |
| 39 | + * Maps {@code \fcharsetN} values to Java charsets. |
| 40 | + * The RTF font table uses these to declare per-font character encodings. |
| 41 | + */ |
| 42 | + public static final Map<Integer, Charset> FCHARSET_MAP; |
| 43 | + |
| 44 | + /** |
| 45 | + * Maps {@code \ansicpgN} values to Java charsets. |
| 46 | + * This is the global ANSI code page declared in the RTF header. |
| 47 | + */ |
| 48 | + public static final Map<Integer, Charset> ANSICPG_MAP; |
| 49 | + |
| 50 | + static { |
| 51 | + Map<Integer, Charset> fcharset = new HashMap<>(); |
| 52 | + |
| 53 | + fcharset.put(0, WINDOWS_1252); // ANSI |
| 54 | + // charset 1 = Default, charset 2 = Symbol |
| 55 | + |
| 56 | + fcharset.put(77, getCharset("MacRoman")); // Mac Roman |
| 57 | + fcharset.put(78, getCharset("Shift_JIS")); // Mac Shift Jis |
| 58 | + fcharset.put(79, getCharset("ms949")); // Mac Hangul |
| 59 | + fcharset.put(80, getCharset("GB2312")); // Mac GB2312 |
| 60 | + fcharset.put(81, getCharset("Big5")); // Mac Big5 |
| 61 | + fcharset.put(82, getCharset("johab")); // Mac Johab (old) |
| 62 | + fcharset.put(83, getCharset("MacHebrew")); // Mac Hebrew |
| 63 | + fcharset.put(84, getCharset("MacArabic")); // Mac Arabic |
| 64 | + fcharset.put(85, getCharset("MacGreek")); // Mac Greek |
| 65 | + fcharset.put(86, getCharset("MacTurkish")); // Mac Turkish |
| 66 | + fcharset.put(87, getCharset("MacThai")); // Mac Thai |
| 67 | + fcharset.put(88, getCharset("cp1250")); // Mac East Europe |
| 68 | + fcharset.put(89, getCharset("cp1251")); // Mac Russian |
| 69 | + |
| 70 | + fcharset.put(128, getCharset("MS932")); // Shift JIS |
| 71 | + fcharset.put(129, getCharset("ms949")); // Hangul |
| 72 | + fcharset.put(130, getCharset("ms1361")); // Johab |
| 73 | + fcharset.put(134, getCharset("ms936")); // GB2312 |
| 74 | + fcharset.put(136, getCharset("ms950")); // Big5 |
| 75 | + fcharset.put(161, getCharset("cp1253")); // Greek |
| 76 | + fcharset.put(162, getCharset("cp1254")); // Turkish |
| 77 | + fcharset.put(163, getCharset("cp1258")); // Vietnamese |
| 78 | + fcharset.put(177, getCharset("cp1255")); // Hebrew |
| 79 | + fcharset.put(178, getCharset("cp1256")); // Arabic |
| 80 | + fcharset.put(186, getCharset("cp1257")); // Baltic |
| 81 | + |
| 82 | + fcharset.put(204, getCharset("cp1251")); // Russian |
| 83 | + fcharset.put(222, getCharset("ms874")); // Thai |
| 84 | + fcharset.put(238, getCharset("cp1250")); // Eastern European |
| 85 | + fcharset.put(254, getCharset("cp437")); // PC 437 |
| 86 | + fcharset.put(255, getCharset("cp850")); // OEM |
| 87 | + |
| 88 | + FCHARSET_MAP = Collections.unmodifiableMap(fcharset); |
| 89 | + } |
| 90 | + |
| 91 | + static { |
| 92 | + Map<Integer, Charset> ansicpg = new HashMap<>(); |
| 93 | + |
| 94 | + ansicpg.put(437, getCharset("CP437")); // US IBM |
| 95 | + ansicpg.put(708, getCharset("ISO-8859-6")); // Arabic (ASMO 708) |
| 96 | + ansicpg.put(709, getCharset("windows-709")); // Arabic (ASMO 449+) |
| 97 | + ansicpg.put(710, getCharset("windows-710")); // Arabic (transparent) |
| 98 | + ansicpg.put(711, getCharset("windows-711")); // Arabic (Nafitha) |
| 99 | + ansicpg.put(720, getCharset("windows-720")); // Arabic (transparent ASMO) |
| 100 | + ansicpg.put(819, getCharset("CP819")); // Windows 3.1 (US/Western) |
| 101 | + ansicpg.put(850, getCharset("CP850")); // IBM Multilingual |
| 102 | + ansicpg.put(852, getCharset("CP852")); // Eastern European |
| 103 | + ansicpg.put(860, getCharset("CP860")); // Portuguese |
| 104 | + ansicpg.put(862, getCharset("CP862")); // Hebrew |
| 105 | + ansicpg.put(863, getCharset("CP863")); // French Canadian |
| 106 | + ansicpg.put(864, getCharset("CP864")); // Arabic |
| 107 | + ansicpg.put(865, getCharset("CP865")); // Norwegian |
| 108 | + ansicpg.put(866, getCharset("CP866")); // Soviet Union |
| 109 | + ansicpg.put(874, getCharset("MS874")); // Thai |
| 110 | + ansicpg.put(932, getCharset("MS932")); // Japanese |
| 111 | + ansicpg.put(936, getCharset("MS936")); // Simplified Chinese |
| 112 | + ansicpg.put(949, getCharset("CP949")); // Korean |
| 113 | + ansicpg.put(950, getCharset("CP950")); // Traditional Chinese |
| 114 | + ansicpg.put(1250, getCharset("CP1250")); // Eastern European |
| 115 | + ansicpg.put(1251, getCharset("CP1251")); // Cyrillic |
| 116 | + ansicpg.put(1252, getCharset("CP1252")); // Western European |
| 117 | + ansicpg.put(1253, getCharset("CP1253")); // Greek |
| 118 | + ansicpg.put(1254, getCharset("CP1254")); // Turkish |
| 119 | + ansicpg.put(1255, getCharset("CP1255")); // Hebrew |
| 120 | + ansicpg.put(1256, getCharset("CP1256")); // Arabic |
| 121 | + ansicpg.put(1257, getCharset("CP1257")); // Baltic |
| 122 | + ansicpg.put(1258, getCharset("CP1258")); // Vietnamese |
| 123 | + ansicpg.put(1361, getCharset("x-Johab")); // Johab |
| 124 | + ansicpg.put(10000, getCharset("MacRoman")); // Mac Roman |
| 125 | + ansicpg.put(10001, getCharset("Shift_JIS")); // Mac Japan |
| 126 | + ansicpg.put(10004, getCharset("MacArabic")); // Mac Arabic |
| 127 | + ansicpg.put(10005, getCharset("MacHebrew")); // Mac Hebrew |
| 128 | + ansicpg.put(10006, getCharset("MacGreek")); // Mac Greek |
| 129 | + ansicpg.put(10007, getCharset("MacCyrillic")); // Mac Cyrillic |
| 130 | + ansicpg.put(10029, getCharset("x-MacCentralEurope")); // Mac Latin2 |
| 131 | + ansicpg.put(10081, getCharset("MacTurkish")); // Mac Turkish |
| 132 | + ansicpg.put(57002, getCharset("x-ISCII91")); // Devanagari |
| 133 | + ansicpg.put(57003, getCharset("windows-57003")); // Bengali |
| 134 | + ansicpg.put(57004, getCharset("windows-57004")); // Tamil |
| 135 | + ansicpg.put(57005, getCharset("windows-57005")); // Telugu |
| 136 | + ansicpg.put(57006, getCharset("windows-57006")); // Assamese |
| 137 | + ansicpg.put(57007, getCharset("windows-57007")); // Oriya |
| 138 | + ansicpg.put(57008, getCharset("windows-57008")); // Kannada |
| 139 | + ansicpg.put(57009, getCharset("windows-57009")); // Malayalam |
| 140 | + ansicpg.put(57010, getCharset("windows-57010")); // Gujarati |
| 141 | + ansicpg.put(57011, getCharset("windows-57011")); // Punjabi |
| 142 | + |
| 143 | + ANSICPG_MAP = Collections.unmodifiableMap(ansicpg); |
| 144 | + } |
| 145 | + |
| 146 | + private RTFCharsetMaps() { |
| 147 | + } |
| 148 | + |
| 149 | + /** |
| 150 | + * Resolve a charset by name, falling back to US-ASCII if unavailable. |
| 151 | + */ |
| 152 | + static Charset getCharset(String name) { |
| 153 | + try { |
| 154 | + return CharsetUtils.forName(name); |
| 155 | + } catch (IllegalArgumentException e) { |
| 156 | + return StandardCharsets.US_ASCII; |
| 157 | + } |
| 158 | + } |
| 159 | + |
| 160 | + /** |
| 161 | + * Resolve an ANSI code page number to a Java Charset. |
| 162 | + * Tries the ANSICPG_MAP first, then falls back to {@code windows-N} and {@code cpN}. |
| 163 | + * Returns {@code WINDOWS_1252} if nothing matches. |
| 164 | + */ |
| 165 | + public static Charset resolveCodePage(int cpNumber) { |
| 166 | + Charset cs = ANSICPG_MAP.get(cpNumber); |
| 167 | + if (cs != null) { |
| 168 | + return cs; |
| 169 | + } |
| 170 | + try { |
| 171 | + return Charset.forName("windows-" + cpNumber); |
| 172 | + } catch (Exception e) { |
| 173 | + try { |
| 174 | + return Charset.forName("cp" + cpNumber); |
| 175 | + } catch (Exception e2) { |
| 176 | + return WINDOWS_1252; |
| 177 | + } |
| 178 | + } |
| 179 | + } |
| 180 | +} |
0 commit comments