Skip to content

Commit

Permalink
port SHA-1: 3b189fc700c9c7c210f4b78fc66b01f4c13ae5d2
Browse files Browse the repository at this point in the history
* 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
  • Loading branch information
micjahn committed Dec 30, 2024
1 parent cedd130 commit 6f4634e
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 16 deletions.
2 changes: 1 addition & 1 deletion Source/lib/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@
#if NETFX_CORE && !WINDOWS_UWP
[assembly: AssemblyTitle("zxing.net for windows rt")]
#endif
[assembly: AssemblyDescription("port of the java based barcode scanning library for .net (java zxing 19.10.2024 03:38:56)")]
[assembly: AssemblyDescription("port of the java based barcode scanning library for .net (java zxing 22.10.2024 15:24:36)")]
[assembly: AssemblyCompany("ZXing.Net Development")]
[assembly: AssemblyProduct("ZXing.Net")]
[assembly: AssemblyCopyright("Copyright © 2012")]
Expand Down
36 changes: 27 additions & 9 deletions Source/lib/pdf417/encoder/PDF417HighLevelEncoder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using System;
#if (NET40 || NET45 || NET46 || NET47 || NET48 || NETFX_CORE || NETSTANDARD) && !NETSTANDARD1_0
using System.Numerics;

#else
using BigIntegerLibrary;
#endif
Expand Down Expand Up @@ -184,18 +185,16 @@ internal static String encodeHighLevel(String msg, Compaction compaction, Encodi
throw new ArgumentException("Empty message not allowed");
}

if (Compaction.TEXT == compaction)
{
checkCharset(msg, 127, "Consider specifying Compaction.AUTO instead of Compaction.TEXT");
}

if (encoding == null && !autoECI)
{
for (int i = 0; i < msg.Length; i++)
{
if (msg[i] > 255)
{
throw new WriterException("Non-encodable character detected: " + msg[i] + " (Unicode: " +
(int)msg[i] +
"). Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET.");
}
}
checkCharset(msg, 255, "Consider specifying EncodeHintType.PDF417_AUTO_ECI and/or EncodeTypeHint.CHARACTER_SET");
}

encoding = ECIEncoderSet.Clone(encoding); // needed because of ECIEncoderSet.canEncode

//the codewords 0..928 are encoded as Unicode characters
Expand Down Expand Up @@ -367,6 +366,25 @@ private static byte[] toBytes(char msg, Encoding encoding)
return getEncoder(encoding).GetBytes(new[] { msg });
}

/// <summary>
/// Check if input is only made of characters between 0 and the upper limit
/// </summary>
/// <param name="input">the input</param>
/// <param name="max">the upper limit for charset</param>
/// <param name="errorMessage">the message to explain the error</param>
/// <exception cref="WriterException">exception highlighting the offending character and a suggestion to avoid the error</exception>
internal static void checkCharset(String input, int max, String errorMessage)
{
for (int i = 0; i < input.Length; i++)
{
if (input[i] > max)
{
throw new WriterException("Non-encodable character detected: " + input[i] + " (Unicode: " +
(int)input[i] + ") at position #" + i + " - " + errorMessage);
}
}
}

/// <summary>
/// Encode parts of the message using Text Compaction as described in ISO/IEC 15438:2001(E),
/// chapter 4.4.2.
Expand Down
107 changes: 101 additions & 6 deletions Source/test/src/pdf417/encoder/PDF417EncoderTestCase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,25 +18,120 @@
using System.Text;

using NUnit.Framework;
using ZXing.Common;

namespace ZXing.PDF417.Internal.Test
{
public sealed class PDF417EncoderTestCase
{
private static String PDF417PFX = "\u039f\u001A\u0385";

[Test]
public void testEncodeAuto()
{
var encoded = PDF417HighLevelEncoder.encodeHighLevel(
"ABCD", Compaction.AUTO, Encoding.UTF8, false, false);
Assert.AreEqual("\u039f\u001A\u0385ABCD", encoded);
var input = "ABCD";
Assert.That(checkEncodeAutoWithSpecialChars(input, Compaction.AUTO), Is.EqualTo(PDF417PFX + input));
}

[Test]
public void testEncodeAutoWithSpecialChars()
{
//Just check if this does not throw an exception
PDF417HighLevelEncoder.encodeHighLevel(
"1%§s ?aG$", Compaction.AUTO, Encoding.UTF8, false, false);
// Just check if this does not throw an exception
checkEncodeAutoWithSpecialChars("1%§s ?aG$", Compaction.AUTO);
checkEncodeAutoWithSpecialChars("日本語", Compaction.AUTO);
checkEncodeAutoWithSpecialChars("₸ 5555", Compaction.AUTO);
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.AUTO);
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.BYTE);
checkEncodeAutoWithSpecialChars("123,45", Compaction.TEXT);

// Greek alphabet
var cp437 = CharacterSetECI.getEncoding("IBM437");
Assert.That(cp437, Is.Not.Null);
byte[] cp437Array = { (byte)224, (byte)225, (byte)226, (byte)227, (byte)228 }; //αßΓπΣ
var greek = cp437.GetString(cp437Array);
Assert.That("αßΓπΣ", Is.EqualTo(greek));
checkEncodeAutoWithSpecialChars(greek, Compaction.AUTO);
checkEncodeAutoWithSpecialChars(greek, Compaction.BYTE);
PDF417HighLevelEncoder.encodeHighLevel(greek, Compaction.AUTO, cp437, false, true);
PDF417HighLevelEncoder.encodeHighLevel(greek, Compaction.AUTO, cp437, false, false);

try
{
// detect when a TEXT Compaction is applied to a non text input
checkEncodeAutoWithSpecialChars("€ 123,45", Compaction.TEXT);
}
catch (WriterException e)
{
Assert.That(e.Message, Is.Not.Null);
Assert.That(e.Message.Contains("8364"), Is.True);
Assert.That(e.Message.Contains("Compaction.TEXT"), Is.True);
Assert.That(e.Message.Contains("Compaction.AUTO"), Is.True);
}

try
{
// detect when a TEXT Compaction is applied to a non text input
var input = "Hello! " + (char)128;
checkEncodeAutoWithSpecialChars(input, Compaction.TEXT);
}
catch (WriterException e)
{
Assert.That(e.Message, Is.Not.Null);
Assert.That(e.Message.Contains("128"), Is.True);
Assert.That(e.Message.Contains("Compaction.TEXT"), Is.True);
Assert.That(e.Message.Contains("Compaction.AUTO"), Is.True);
}

try
{
// detect when a TEXT Compaction is applied to a non text input
// https://github.com/zxing/zxing/issues/1761
var content = "€ 123,45";
var hints = new System.Collections.Generic.Dictionary<EncodeHintType, object>();
hints[EncodeHintType.ERROR_CORRECTION] = 4;
hints[EncodeHintType.PDF417_DIMENSIONS] = new Dimensions(7, 7, 1, 300);
hints[EncodeHintType.MARGIN] = 0;
hints[EncodeHintType.CHARACTER_SET] = "ISO-8859-15";
hints[EncodeHintType.PDF417_COMPACTION] = Compaction.TEXT;

(new MultiFormatWriter()).encode(content, BarcodeFormat.PDF_417, 200, 100, hints);
}
catch (WriterException e)
{
Assert.That(e.Message, Is.Not.Null);
Assert.That(e.Message.Contains("8364"), Is.True);
Assert.That(e.Message.Contains("Compaction.TEXT"), Is.True);
Assert.That(e.Message.Contains("Compaction.AUTO"), Is.True);
}
}

public String checkEncodeAutoWithSpecialChars(String input, Compaction compaction)
{
return PDF417HighLevelEncoder.encodeHighLevel(input, compaction, Encoding.UTF8, false, false);
}

[Test]
public void testCheckCharset()
{
var input = "Hello!";
var errorMessage = Guid.NewGuid().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)
{
Assert.That(e.Message, Is.Not.Null);
Assert.That(e.Message.Contains("111"), Is.True);
Assert.That(e.Message.Contains(errorMessage), Is.True);
}
}

[Test]
Expand Down

0 comments on commit 6f4634e

Please sign in to comment.