diff --git a/.travis.yml b/.travis.yml index 8dae417..db82257 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,8 @@ language: cpp -script: mkdir build && cd build && cmake -G "Unix Makefiles" .. && make +script: + - mkdir build + - cd build + - cmake -G "Unix Makefiles" .. + - make + - export PATH=$(pwd):$PATH + - ../tests/test.sh diff --git a/core/src/zxing/common/StringUtils.cpp b/core/src/zxing/common/StringUtils.cpp index 30f9325..e5cea76 100644 --- a/core/src/zxing/common/StringUtils.cpp +++ b/core/src/zxing/common/StringUtils.cpp @@ -25,7 +25,9 @@ using namespace zxing::common; // N.B.: these are the iconv strings for at least some versions of iconv -char const* const StringUtils::PLATFORM_DEFAULT_ENCODING = "UTF-8"; +char const* const StringUtils::PLATFORM_DEFAULT_ENCODING = "ISO8859-1"; + // This default is an 8-bit fixed-width encoding and it's identical with + // unicode in its range, which reduces accidental mangling during decode. char const* const StringUtils::ASCII = "ASCII"; char const* const StringUtils::SHIFT_JIS = "SHIFT_JIS"; char const* const StringUtils::GB2312 = "GBK"; @@ -76,6 +78,11 @@ StringUtils::guessEncoding(char* bytes, int length, int value = bytes[i] & 0xFF; + // embedded nuls are a sure sign of binary data + if(value == '\x00') { + canBeISO88591 = canBeShiftJIS = canBeUTF8 = false; + } + // UTF-8 stuff if (canBeUTF8) { if (utf8BytesLeft > 0) { diff --git a/core/src/zxing/qrcode/decoder/DecodedBitStreamParser.cpp b/core/src/zxing/qrcode/decoder/DecodedBitStreamParser.cpp index 1d36bba..40f5c32 100644 --- a/core/src/zxing/qrcode/decoder/DecodedBitStreamParser.cpp +++ b/core/src/zxing/qrcode/decoder/DecodedBitStreamParser.cpp @@ -67,6 +67,12 @@ void DecodedBitStreamParser::append(std::string &result, return; } + if(src == NULL) { + // don't try to recode un-encoded data. + result.append((const char *)bufIn, nIn); + return; + } + iconv_t cd = iconv_open(StringUtils::UTF8, src); if (cd == (iconv_t)-1) { result.append((const char *)bufIn, nIn); @@ -193,19 +199,24 @@ void DecodedBitStreamParser::decodeByteSegment(Ref bits_, for (int i = 0; i < count; i++) { readBytes[i] = (char) bits.readBits(8); } - string encoding; - if (currentCharacterSetECI == 0) { - // The spec isn't clear on this mode; see - // section 6.4.5: t does not say which encoding to assuming - // upon decoding. I have seen ISO-8859-1 used as well as - // Shift_JIS -- without anything like an ECI designator to - // give a hint. - encoding = StringUtils::guessEncoding(readBytes, count, hints); + const char* encoding = NULL; + if (currentCharacterSetECI == NULL) { + // The spec says + // 8.3.1: The default interpretation for QR Code is ECI 000020 representing the JIS8 and Shift JIS character sets. + // 8.4.4: In [8-bit Byte Mode], one 8 bit codeword directly represents the JIS8 character [...]. + // In ECIs other than the default ECI, it represents an 8-bit byte value directly. + // If I'm reading that right, *if* the character set is unspecified *or* explicitly set to Shift-JIS, + // *then* use JIS8 but *otherwise* don't try to decode the value. + // + // That's a stupid spec. + // Instead we follow qrencode: + // unspecified ECI <=> unmolested binary + encoding = NULL; } else { encoding = currentCharacterSetECI->name(); } try { - append(result, readBytes, nBytes, encoding.c_str()); + append(result, readBytes, nBytes, encoding); } catch (ReaderException const& ignored) { (void)ignored; throw FormatException(); diff --git a/tests/amen-01.bin b/tests/amen-01.bin new file mode 100644 index 0000000..74d21bf Binary files /dev/null and b/tests/amen-01.bin differ diff --git a/tests/amen-01.png b/tests/amen-01.png new file mode 100644 index 0000000..599f494 Binary files /dev/null and b/tests/amen-01.png differ diff --git a/tests/test.sh b/tests/test.sh new file mode 100755 index 0000000..3c7e825 --- /dev/null +++ b/tests/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + + +cd "$(dirname "$0")"; + +find . -name "*.png" | while read file; do + #zxing has a --test-mode but it's not working for binary files + # perl is here because in textmode, zxing appends a newline, but a lot of test files don't have that + zxing "$file" | perl -pe 'chomp if eof' | diff -u "$(ls "${file%.*}".{txt,bin} 2>/dev/null)" - +done