Skip to content

Commit

Permalink
:octocat: allow for ECI encoded numeric and alphanum segments (???), see #289
Browse files Browse the repository at this point in the history
  • Loading branch information
codemasher committed Nov 16, 2024
1 parent 90eb116 commit 53b52b7
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 11 deletions.
2 changes: 1 addition & 1 deletion examples/reader.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
var_dump($result);
}
catch(Throwable $e){
echo $e->getMessage();
printf("%s(%s): %s\n%s", $e->getFile(), $e->getLine(), $e->getMessage(), $e->getTraceAsString());
}

exit;
25 changes: 17 additions & 8 deletions src/Data/ECI.php
Original file line number Diff line number Diff line change
Expand Up @@ -129,17 +129,12 @@ public static function validateString(string $string):bool{
public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):string{
$eciCharset = self::parseValue($bitBuffer);
$nextMode = $bitBuffer->read(4);

if($nextMode !== Mode::BYTE){
throw new QRCodeDataException(sprintf('ECI designator followed by invalid mode: "%04b"', $nextMode));
}

$data = Byte::decodeSegment($bitBuffer, $versionNumber);
$encoding = $eciCharset->getName();
$data = self::decodeModeSegment($nextMode, $bitBuffer, $versionNumber);
$encoding = $eciCharset->getName();

if($encoding === null){
// The spec isn't clear on this mode; see
// section 6.4.5: t does not say which encoding to assuming
// section 6.4.5: it 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.
Expand All @@ -153,4 +148,18 @@ public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber):s
return mb_convert_encoding($data, mb_internal_encoding(), $encoding);
}

/**
* @throws \chillerlan\QRCode\Data\QRCodeDataException
*/
private static function decodeModeSegment(int $mode, BitBuffer $bitBuffer, int $versionNumber):string{

switch(true){
case $mode === Mode::NUMBER: return Number::decodeSegment($bitBuffer, $versionNumber);
case $mode === Mode::ALPHANUM: return AlphaNum::decodeSegment($bitBuffer, $versionNumber);
case $mode === Mode::BYTE: return Byte::decodeSegment($bitBuffer, $versionNumber);
}

throw new QRCodeDataException(sprintf('ECI designator followed by invalid mode: "%04b"', $mode));
}

}
4 changes: 2 additions & 2 deletions tests/Data/ECITest.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

use chillerlan\QRCode\QROptions;
use chillerlan\QRCode\Common\{BitBuffer, ECICharset, Mode};
use chillerlan\QRCode\Data\{Byte, ECI, Number, QRCodeDataException, QRData, QRDataModeInterface};
use chillerlan\QRCode\Data\{Byte, ECI, Hanzi, QRCodeDataException, QRData, QRDataModeInterface};
use PHPUnit\Framework\TestCase;

/**
Expand Down Expand Up @@ -125,7 +125,7 @@ public function testDecodeECISegmentFollowedByInvalidModeException():void{
/** @var \chillerlan\QRCode\Data\QRDataModeInterface[] $segments */
$segments = $this->getDataSegments();
// follow the ECI segment by a non-8bit-byte segment
$segments[1] = new Number('1');
$segments[1] = new Hanzi(self::testData);
$bitBuffer = (new QRData($options, $segments))->getBitBuffer();
// verify the ECI mode indicator
$this::assertSame(Mode::ECI, $bitBuffer->read(4));
Expand Down

0 comments on commit 53b52b7

Please sign in to comment.