mirror of
https://github.com/zxing/zxing.git
synced 2025-01-12 11:47:26 -08:00
PDF417: Check that input is made of 0...127 chars when using Compaction.TEXT, throw an explicit exception if not the case (#1878)
* throw a more explicit exception when trying to PDF417/TEXT encode something outside of 0...255 * refactor PDF417HighLevelEncoder to avoid code duplication extend UT to new method PDF417HighLevelEncoder#checkCharset * fix javadoc typo make UT more stringent on PDF417HighLevelEncoder#checkCharset * restrict TEXT to 0...127 test with CP437 and Greek chars * reinstate testEncodeAuto UT * refactor testEncodeAuto UT * address codacy findings * formatting
This commit is contained in:
parent
e750aca9e5
commit
3b189fc700
|
@ -175,15 +175,14 @@ final class PDF417HighLevelEncoder {
|
||||||
throw new WriterException("Empty message not allowed");
|
throw new WriterException("Empty message not allowed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Compaction.TEXT == compaction) {
|
||||||
|
checkCharset(msg, 127, "Consider specifying Compaction.AUTO instead of Compaction.TEXT");
|
||||||
|
}
|
||||||
|
|
||||||
if (encoding == null && !autoECI) {
|
if (encoding == null && !autoECI) {
|
||||||
for (int i = 0; i < msg.length(); i++) {
|
checkCharset(msg, 255, "Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET");
|
||||||
if (msg.charAt(i) > 255) {
|
|
||||||
throw new WriterException("Non-encodable character detected: " + msg.charAt(i) + " (Unicode: " +
|
|
||||||
(int) msg.charAt(i) +
|
|
||||||
"). Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//the codewords 0..928 are encoded as Unicode characters
|
//the codewords 0..928 are encoded as Unicode characters
|
||||||
StringBuilder sb = new StringBuilder(msg.length());
|
StringBuilder sb = new StringBuilder(msg.length());
|
||||||
|
|
||||||
|
@ -284,6 +283,22 @@ final class PDF417HighLevelEncoder {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if input is only made of characters between 0 and the upper limit
|
||||||
|
* @param input the input
|
||||||
|
* @param max the upper limit for charset
|
||||||
|
* @param errorMessage the message to explain the error
|
||||||
|
* @throws WriterException exception highlighting the offending character and a suggestion to avoid the error
|
||||||
|
*/
|
||||||
|
protected static void checkCharset(String input, int max, String errorMessage) throws WriterException {
|
||||||
|
for (int i = 0; i < input.length(); i++) {
|
||||||
|
if (input.charAt(i) > max) {
|
||||||
|
throw new WriterException("Non-encodable character detected: " + input.charAt(i) + " (Unicode: " +
|
||||||
|
(int) input.charAt(i) + ") at position #" + i + " - " + errorMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E),
|
* Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E),
|
||||||
* chapter 4.4.2.
|
* chapter 4.4.2.
|
||||||
|
|
|
@ -16,8 +16,16 @@
|
||||||
|
|
||||||
package com.google.zxing.pdf417.encoder;
|
package com.google.zxing.pdf417.encoder;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import com.google.zxing.BarcodeFormat;
|
||||||
|
import com.google.zxing.EncodeHintType;
|
||||||
|
import com.google.zxing.MultiFormatWriter;
|
||||||
import com.google.zxing.WriterException;
|
import com.google.zxing.WriterException;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
|
@ -28,18 +36,98 @@ import org.junit.Test;
|
||||||
*/
|
*/
|
||||||
public final class PDF417EncoderTestCase extends Assert {
|
public final class PDF417EncoderTestCase extends Assert {
|
||||||
|
|
||||||
|
private static final String PDF417PFX = "\u039f\u001A\u0385";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAuto() throws Exception {
|
public void testEncodeAuto() throws Exception {
|
||||||
String encoded = PDF417HighLevelEncoder.encodeHighLevel(
|
String input = "ABCD";
|
||||||
"ABCD", Compaction.AUTO, StandardCharsets.UTF_8, false);
|
assertEquals(PDF417PFX + input, checkEncodeAutoWithSpecialChars(input, Compaction.AUTO));
|
||||||
assertEquals("\u039f\u001A\u0385ABCD", encoded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeAutoWithSpecialChars() throws Exception {
|
public void testEncodeAutoWithSpecialChars() throws Exception {
|
||||||
// Just check if this does not throw an exception
|
// Just check if this does not throw an exception
|
||||||
PDF417HighLevelEncoder.encodeHighLevel(
|
checkEncodeAutoWithSpecialChars("1%§s ?aG$", Compaction.AUTO);
|
||||||
"1%§s ?aG$", Compaction.AUTO, StandardCharsets.UTF_8, false);
|
checkEncodeAutoWithSpecialChars("日本語", Compaction.AUTO);
|
||||||
|
checkEncodeAutoWithSpecialChars("₸ 5555", Compaction.AUTO);
|
||||||
|
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.AUTO);
|
||||||
|
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.BYTE);
|
||||||
|
checkEncodeAutoWithSpecialChars("123,45", Compaction.TEXT);
|
||||||
|
|
||||||
|
// Greek alphabet
|
||||||
|
Charset cp437 = Charset.forName("IBM437");
|
||||||
|
assertNotNull(cp437);
|
||||||
|
byte[] cp437Array = {(byte) 224,(byte) 225,(byte) 226,(byte) 227,(byte) 228}; //αßΓπΣ
|
||||||
|
String greek = new String(cp437Array, cp437);
|
||||||
|
assertEquals("αßΓπΣ", greek);
|
||||||
|
checkEncodeAutoWithSpecialChars(greek, Compaction.AUTO);
|
||||||
|
checkEncodeAutoWithSpecialChars(greek, Compaction.BYTE);
|
||||||
|
PDF417HighLevelEncoder.encodeHighLevel(greek, Compaction.AUTO, cp437, true);
|
||||||
|
PDF417HighLevelEncoder.encodeHighLevel(greek, Compaction.AUTO, cp437, false);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// detect when a TEXT Compaction is applied to a non text input
|
||||||
|
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.TEXT);
|
||||||
|
} catch (WriterException e) {
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().contains("8364"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.TEXT"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.AUTO"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// detect when a TEXT Compaction is applied to a non text input
|
||||||
|
String input = "Hello! " + (char) 128;
|
||||||
|
checkEncodeAutoWithSpecialChars(input, Compaction.TEXT);
|
||||||
|
} catch (WriterException e) {
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().contains("128"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.TEXT"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.AUTO"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// detect when a TEXT Compaction is applied to a non text input
|
||||||
|
// https://github.com/zxing/zxing/issues/1761
|
||||||
|
String content = "€ 123,45";
|
||||||
|
Map<EncodeHintType, Object> hints = new HashMap<>();
|
||||||
|
hints.put(EncodeHintType.ERROR_CORRECTION, 4);
|
||||||
|
hints.put(EncodeHintType.PDF417_DIMENSIONS, new Dimensions(7, 7, 1, 300));
|
||||||
|
hints.put(EncodeHintType.MARGIN, 0);
|
||||||
|
hints.put(EncodeHintType.CHARACTER_SET, "ISO-8859-15");
|
||||||
|
hints.put(EncodeHintType.PDF417_COMPACTION, Compaction.TEXT);
|
||||||
|
|
||||||
|
(new MultiFormatWriter()).encode(content, BarcodeFormat.PDF_417, 200, 100, hints);
|
||||||
|
} catch (WriterException e) {
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().contains("8364"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.TEXT"));
|
||||||
|
assertTrue(e.getMessage().contains("Compaction.AUTO"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String checkEncodeAutoWithSpecialChars(String input, Compaction compaction) throws Exception {
|
||||||
|
return PDF417HighLevelEncoder.encodeHighLevel(input, compaction, StandardCharsets.UTF_8, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCheckCharset() throws Exception {
|
||||||
|
String input = "Hello!";
|
||||||
|
String errorMessage = UUID.randomUUID().toString();
|
||||||
|
|
||||||
|
// no exception
|
||||||
|
PDF417HighLevelEncoder.checkCharset(input,255,errorMessage);
|
||||||
|
PDF417HighLevelEncoder.checkCharset(input,1255,errorMessage);
|
||||||
|
PDF417HighLevelEncoder.checkCharset(input,111,errorMessage);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// should throw an exception for character 'o' because it exceeds upper limit 110
|
||||||
|
PDF417HighLevelEncoder.checkCharset(input,110,errorMessage);
|
||||||
|
} catch (WriterException e) {
|
||||||
|
assertNotNull(e.getMessage());
|
||||||
|
assertTrue(e.getMessage().contains("111"));
|
||||||
|
assertTrue(e.getMessage().contains(errorMessage));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in a new issue