From dd6b187ecc8418fdf5cd1c2681db02813af8b070 Mon Sep 17 00:00:00 2001 From: Shane32 Date: Wed, 1 May 2024 23:15:54 -0400 Subject: [PATCH] Fix character encoding --- QRCoder/QRCodeGenerator.cs | 42 +++++++++----------------------- QRCoderTests/QRGeneratorTests.cs | 31 +++++++++++++++++++++++ 2 files changed, 42 insertions(+), 31 deletions(-) diff --git a/QRCoder/QRCodeGenerator.cs b/QRCoder/QRCodeGenerator.cs index 85c24b17..721dabc3 100644 --- a/QRCoder/QRCodeGenerator.cs +++ b/QRCoder/QRCodeGenerator.cs @@ -1015,19 +1015,7 @@ private static int GetCountIndicatorLength(int version, EncodingMode encMode) private static int GetDataLength(EncodingMode encoding, string plainText, string codedText, bool forceUtf8) { - return forceUtf8 || IsUtf8(encoding, plainText, forceUtf8) ? (codedText.Length / 8) : plainText.Length; - } - - private static bool IsUtf8(EncodingMode encoding, string plainText, bool forceUtf8) - { - return (encoding == EncodingMode.Byte && (!IsValidISO(plainText) || forceUtf8)); - } - - private static bool IsValidISO(string input) - { - var bytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(input); - var result = Encoding.GetEncoding("ISO-8859-1").GetString(bytes); - return String.Equals(input, result); + return encoding == EncodingMode.Byte ? (codedText.Length / 8) : plainText.Length; } private static string PlainTextToBinary(string plainText, EncodingMode encMode, EciMode eciMode, bool utf8BOM, bool forceUtf8) @@ -1100,37 +1088,30 @@ private string PlainTextToBinaryECI(string plainText) return codeText; } - private static string ConvertToIso8859(string value, string Iso = "ISO-8859-2") - { - Encoding iso = Encoding.GetEncoding(Iso); - Encoding utf8 = Encoding.UTF8; - byte[] utfBytes = utf8.GetBytes(value); - byte[] isoBytes = Encoding.Convert(utf8, iso, utfBytes); - return iso.GetString(isoBytes); - } - private static string PlainTextToBinaryByte(string plainText, EciMode eciMode, bool utf8BOM, bool forceUtf8) { byte[] codeBytes; var codeText = string.Empty; - if (IsValidISO(plainText) && !forceUtf8) - codeBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(plainText); + if (eciMode == EciMode.Utf8 || (eciMode == EciMode.Default && forceUtf8)) + codeBytes = utf8BOM ? Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(plainText)).ToArray() : Encoding.UTF8.GetBytes(plainText); else { switch(eciMode) { + case EciMode.Default: // per spec, ISO-8859-1 is default case EciMode.Iso8859_1: - codeBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(ConvertToIso8859(plainText, "ISO-8859-1")); +#if NET5_0_OR_GREATER + codeBytes = Encoding.Latin1.GetBytes(plainText); +#else + codeBytes = Encoding.GetEncoding("ISO-8859-1").GetBytes(plainText); +#endif break; case EciMode.Iso8859_2: - codeBytes = Encoding.GetEncoding("ISO-8859-2").GetBytes(ConvertToIso8859(plainText, "ISO-8859-2")); + codeBytes = Encoding.GetEncoding("ISO-8859-2").GetBytes(plainText); break; - case EciMode.Default: - case EciMode.Utf8: default: - codeBytes = utf8BOM ? Encoding.UTF8.GetPreamble().Concat(Encoding.UTF8.GetBytes(plainText)).ToArray() : Encoding.UTF8.GetBytes(plainText); - break; + throw new ArgumentOutOfRangeException(nameof(eciMode)); } } @@ -1140,7 +1121,6 @@ private static string PlainTextToBinaryByte(string plainText, EciMode eciMode, b return codeText; } - private static Polynom XORPolynoms(Polynom messagePolynom, Polynom resPolynom) { var resultPolynom = new Polynom(); diff --git a/QRCoderTests/QRGeneratorTests.cs b/QRCoderTests/QRGeneratorTests.cs index 29373ea7..c9890f28 100644 --- a/QRCoderTests/QRGeneratorTests.cs +++ b/QRCoderTests/QRGeneratorTests.cs @@ -7,6 +7,7 @@ using System.Linq; using System.Collections; using System.Text; +using System.IO; namespace QRCoderTests { @@ -143,6 +144,36 @@ public void can_generate_from_bytes() var result = string.Join("", qrData.ModuleMatrix.Select(x => x.ToBitString()).ToArray()); result.ShouldBe("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001111111011001011111110000000010000010010010100000100000000101110101010101011101000000001011101010010010111010000000010111010111000101110100000000100000100000001000001000000001111111010101011111110000000000000000011000000000000000000111100101010010011101000000001011100001001001001110000000010101011111011111110100000000000101000000110000000000000001011001001010100110000000000000000000110001000101000000000111111100110011011110000000001000001001111110111010000000010111010011100100101100000000101110101110010010010000000001011101011010100011000000000010000010110110101000100000000111111101011100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); } + + [Fact] + [Category("QRGenerator/TextEncoding")] + public void can_encode_latin1() + { + var gen = new QRCodeGenerator(); + var qrData = gen.CreateQrCode("https://en.wikipedia.org/wiki/È", QRCodeGenerator.ECCLevel.L); + var result = string.Join("", qrData.ModuleMatrix.Select(x => x.ToBitString()).ToArray()); + result.ShouldBe("000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110011110110011111110000000010000010001111111010000010000000010111010110010100010111010000000010111010011000110010111010000000010111010011101110010111010000000010000010010111010010000010000000011111110101010101011111110000000000000000110001110000000000000000011101111101111000110001000000000010110000000011001110000010000000010110110010000100101101110000000010111101000101110110000100000000001101010000111111010010110000000000110000100010001110010010000000010100011000001000101001110000000001001000011011000110100100000000010101011010001011111110000000000000000000100010011000110110000000011111110100001011010110110000000010000010100011101000110010000000010111010101111001111110100000000010111010010001100001111000000000010111010100001100100100010000000010000010100011011000110100000000011111110101011011101000110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } + + [Fact] + [Category("QRGenerator/TextEncoding")] + public void can_encode_utf_notForced() + { + var gen = new QRCodeGenerator(); + var qrData = gen.CreateQrCode("https://en.wikipedia.org/wiki/È", QRCodeGenerator.ECCLevel.L, eciMode: QRCodeGenerator.EciMode.Utf8); + var result = string.Join("", qrData.ModuleMatrix.Select(x => x.ToBitString()).ToArray()); + result.ShouldBe("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110010011001011001111111000000001000001000111011101000100000100000000101110101110111011111010111010000000010111010011101110011101011101000000001011101000100010000010101110100000000100000100100010000110010000010000000011111110101010101010101111111000000000000000011101110111010000000000000000111011111011001111100110001000000000011001101101100110101011010010000000000101011011000100110111100101100000000000010010001000101001011000010000000010110011000010001100111000111000000000010010111011101011110101001000000000011100111101101111101110010000000000010010101011011110000111001011000000001101101000110011010000011011100000000011110001001001001111000000100000000010110111010001001100111001001000000000100110101110001111011100101100000000100110110110100101001111110010000000000000000101111001111100011010000000001111111011111011110010101101100000000100000101010111000011000111110000000010111010101100100010111110000000000001011101001110011011011101100000000000101110101100010111011101000010000000010000010101100001000000110101000000001111111010001000011000001101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } + + [Fact] + [Category("QRGenerator/TextEncoding")] + public void can_encode_utf_forced() + { + var gen = new QRCodeGenerator(); + var qrData = gen.CreateQrCode("https://en.wikipedia.org/wiki/È", QRCodeGenerator.ECCLevel.L, forceUtf8: true, eciMode: QRCodeGenerator.EciMode.Utf8); + var result = string.Join("", qrData.ModuleMatrix.Select(x => x.ToBitString()).ToArray()); + result.ShouldBe("0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011111110010011001011001111111000000001000001000111011101000100000100000000101110101110111011111010111010000000010111010011101110011101011101000000001011101000100010000010101110100000000100000100100010000110010000010000000011111110101010101010101111111000000000000000011101110111010000000000000000111011111011001111100110001000000000011001101101100110101011010010000000000101011011000100110111100101100000000000010010001000101001011000010000000010110011000010001100111000111000000000010010111011101011110101001000000000011100111101101111101110010000000000010010101011011110000111001011000000001101101000110011010000011011100000000011110001001001001111000000100000000010110111010001001100111001001000000000100110101110001111011100101100000000100110110110100101001111110010000000000000000101111001111100011010000000001111111011111011110010101101100000000100000101010111000011000111110000000010111010101100100010111110000000000001011101001110011011011101100000000000101110101100010111011101000010000000010000010101100001000000110101000000001111111010001000011000001101100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"); + } } public static class ExtensionMethods