summaryrefslogtreecommitdiff
path: root/core/src/main/java
diff options
context:
space:
mode:
authorBlake <blakepuhak@gmail.com>2024-01-17 15:49:19 +0300
committerGitHub <noreply@github.com>2024-01-17 15:49:19 +0300
commit1cf9eaaeba610d8e820d64d4196fb480c3eb858c (patch)
tree1d50ac6d400529871d845fc01f833fed12392034 /core/src/main/java
parent956bbcafcbce1b77cb2d557673f6dbe37f114e23 (diff)
downloadzxing-1cf9eaaeba610d8e820d64d4196fb480c3eb858c.tar.xz
Support for platforms where SJIS is unavailable (#1747)
* Add support for embedded JREs where SJIS isn't available (cherry picked from commit 67896f97042f5a9772f0ebcfdbb91f275d86e087) * Add support for embedded JREs where EUC_JP isn't available (cherry picked from commit 979d3b648982b151b7a1e779e58d445086911b31)
Diffstat (limited to 'core/src/main/java')
-rw-r--r--core/src/main/java/com/google/zxing/common/StringUtils.java30
-rw-r--r--core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java4
-rw-r--r--core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java31
3 files changed, 50 insertions, 15 deletions
diff --git a/core/src/main/java/com/google/zxing/common/StringUtils.java b/core/src/main/java/com/google/zxing/common/StringUtils.java
index b749d838b..0a773715f 100644
--- a/core/src/main/java/com/google/zxing/common/StringUtils.java
+++ b/core/src/main/java/com/google/zxing/common/StringUtils.java
@@ -32,7 +32,17 @@ import com.google.zxing.DecodeHintType;
public final class StringUtils {
private static final Charset PLATFORM_DEFAULT_ENCODING = Charset.defaultCharset();
- public static final Charset SHIFT_JIS_CHARSET = Charset.forName("SJIS");
+ public static final Charset SHIFT_JIS_CHARSET;
+ static {
+ Charset sjisCharset;
+ try {
+ sjisCharset = Charset.forName("SJIS");
+ } catch (UnsupportedCharsetException ucee) {
+ // Can happen on JREs without lib/charsets.jar
+ sjisCharset = null;
+ }
+ SHIFT_JIS_CHARSET = sjisCharset;
+ }
public static final Charset GB2312_CHARSET;
static {
Charset gb2312Charset;
@@ -44,10 +54,20 @@ public final class StringUtils {
}
GB2312_CHARSET = gb2312Charset;
}
- private static final Charset EUC_JP = Charset.forName("EUC_JP");
+ private static final Charset EUC_JP;
+ static {
+ Charset eucJpCharset;
+ try {
+ eucJpCharset = Charset.forName("EUC_JP");
+ } catch (UnsupportedCharsetException ucee) {
+ // Can happen on JREs without lib/charsets.jar
+ eucJpCharset = null;
+ }
+ EUC_JP = eucJpCharset;
+ }
private static final boolean ASSUME_SHIFT_JIS =
- SHIFT_JIS_CHARSET.equals(PLATFORM_DEFAULT_ENCODING) ||
- EUC_JP.equals(PLATFORM_DEFAULT_ENCODING);
+ (SHIFT_JIS_CHARSET != null && SHIFT_JIS_CHARSET.equals(PLATFORM_DEFAULT_ENCODING)) ||
+ (EUC_JP != null && EUC_JP.equals(PLATFORM_DEFAULT_ENCODING));
// Retained for ABI compatibility with earlier versions
public static final String SHIFT_JIS = "SJIS";
@@ -101,7 +121,7 @@ public final class StringUtils {
// which should be by far the most common encodings.
int length = bytes.length;
boolean canBeISO88591 = true;
- boolean canBeShiftJIS = true;
+ boolean canBeShiftJIS = SHIFT_JIS_CHARSET != null;
boolean canBeUTF8 = true;
int utf8BytesLeft = 0;
int utf2BytesChars = 0;
diff --git a/core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java b/core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
index 6aa955333..e23ca545b 100644
--- a/core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
+++ b/core/src/main/java/com/google/zxing/qrcode/decoder/DecodedBitStreamParser.java
@@ -211,6 +211,10 @@ final class DecodedBitStreamParser {
private static void decodeKanjiSegment(BitSource bits,
StringBuilder result,
int count) throws FormatException {
+ if (StringUtils.SHIFT_JIS_CHARSET == null) {
+ // Not supported without charset support
+ throw FormatException.getFormatInstance();
+ }
// Don't crash trying to read more bits than we have available.
if (count * 13 > bits.available()) {
throw FormatException.getFormatInstance();
diff --git a/core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java b/core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java
index cc093205e..97f316ddd 100644
--- a/core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java
+++ b/core/src/main/java/com/google/zxing/qrcode/encoder/Encoder.java
@@ -29,6 +29,7 @@ import com.google.zxing.qrcode.decoder.Version;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
+import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;
@@ -91,7 +92,11 @@ public final class Encoder {
Charset encoding = DEFAULT_BYTE_MODE_ENCODING;
boolean hasEncodingHint = hints != null && hints.containsKey(EncodeHintType.CHARACTER_SET);
if (hasEncodingHint) {
- encoding = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
+ try {
+ encoding = Charset.forName(hints.get(EncodeHintType.CHARACTER_SET).toString());
+ } catch (UnsupportedCharsetException ignore) {
+ //ignore the encodingHint and use the DEFAULT_BYTE_MODE_ENCODING
+ }
}
if (hasCompactionHint) {
@@ -105,15 +110,15 @@ public final class Encoder {
version = rn.getVersion();
} else {
-
+
// Pick an encoding mode appropriate for the content. Note that this will not attempt to use
// multiple modes / segments even if that were more efficient.
mode = chooseMode(content, encoding);
-
+
// This will store the header information, like mode and
// length, as well as "header" segments like an ECI segment.
BitArray headerBits = new BitArray();
-
+
// Append ECI segment if applicable
if (mode == Mode.BYTE && hasEncodingHint) {
CharacterSetECI eci = CharacterSetECI.getCharacterSetECI(encoding);
@@ -121,21 +126,21 @@ public final class Encoder {
appendECI(eci, headerBits);
}
}
-
+
// Append the FNC1 mode header for GS1 formatted data if applicable
if (hasGS1FormatHint) {
// GS1 formatted codes are prefixed with a FNC1 in first position mode header
appendModeInfo(Mode.FNC1_FIRST_POSITION, headerBits);
}
-
+
// (With ECI in place,) Write the mode marker
appendModeInfo(mode, headerBits);
-
+
// Collect data within the main segment, separately, to count its size if needed. Don't add it to
// main payload yet.
BitArray dataBits = new BitArray();
appendBytes(content, mode, dataBits, encoding);
-
+
if (hints != null && hints.containsKey(EncodeHintType.QR_VERSION)) {
int versionNumber = Integer.parseInt(hints.get(EncodeHintType.QR_VERSION).toString());
version = Version.getVersionForNumber(versionNumber);
@@ -146,7 +151,7 @@ public final class Encoder {
} else {
version = recommendVersion(ecLevel, mode, headerBits, dataBits);
}
-
+
headerAndDataBits = new BitArray();
headerAndDataBits.appendBitArray(headerBits);
// Find "length" of main segment and write it
@@ -244,7 +249,9 @@ public final class Encoder {
* if it is Shift_JIS, and the input is only double-byte Kanji, then we return {@link Mode#KANJI}.
*/
private static Mode chooseMode(String content, Charset encoding) {
- if (StringUtils.SHIFT_JIS_CHARSET.equals(encoding) && isOnlyDoubleByteKanji(content)) {
+ if (StringUtils.SHIFT_JIS_CHARSET != null &&
+ StringUtils.SHIFT_JIS_CHARSET.equals(encoding) &&
+ isOnlyDoubleByteKanji(content)) {
// Choose Kanji mode if all input are double-byte characters
return Mode.KANJI;
}
@@ -605,6 +612,10 @@ public final class Encoder {
}
static void appendKanjiBytes(String content, BitArray bits) throws WriterException {
+ if (StringUtils.SHIFT_JIS_CHARSET == null) {
+ // Not supported without charset support
+ throw new WriterException("SJIS Charset not supported on this platform");
+ }
byte[] bytes = content.getBytes(StringUtils.SHIFT_JIS_CHARSET);
if (bytes.length % 2 != 0) {
throw new WriterException("Kanji byte size not even");