PluginProbe
WCPOS – Point of Sale (POS) plugin for WooCommerce / 1.10.20
WCPOS – Point of Sale (POS) plugin for WooCommerce v1.10.20
1.10.20 1.10.19 1.10.18 1.10.17 1.10.16 1.10.15 1.10.13 1.10.14 1.10.12 1.10.11 1.10.10 1.10.9 1.10.8 untagged-3d9b7ccddc54df87c672 1.10.7 1.10.6 1.10.5 1.10.3 1.10.4 1.10.2 1.10.1 1.10.0 1.9.17 1.9.15 1.9.16 All 164 releases
woocommerce-pos / vendor_prefixed / chillerlan / php-qrcode / src / Data / ECI.php

ECI.php in WCPOS – Point of Sale (POS) plugin for WooCommerce 1.10.20, at vendor_prefixed/chillerlan/php-qrcode/src/Data/ECI.php

148 lines 5.0 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class ECI
5 *
6 * @created 20.11.2020
7 * @author smiley <[email protected]>
8 * @copyright 2020 smiley
9 * @license MIT
10 */
11 namespace WCPOS\Vendor\chillerlan\QRCode\Data;
12
13 use WCPOS\Vendor\chillerlan\QRCode\Common\BitBuffer;
14 use WCPOS\Vendor\chillerlan\QRCode\Common\ECICharset;
15 use WCPOS\Vendor\chillerlan\QRCode\Common\Mode;
16 use function mb_convert_encoding, mb_detect_encoding, mb_internal_encoding, sprintf;
17 /**
18 * Adds an ECI Designator
19 *
20 * ISO/IEC 18004:2000 8.4.1.1
21 *
22 * Please note that you have to take care for the correct data encoding when adding with QRCode::add*Segment()
23 */
24 final class ECI extends QRDataModeAbstract
25 {
26 /**
27 * @inheritDoc
28 */
29 public const DATAMODE = Mode::ECI;
30 /**
31 * The current ECI encoding id
32 */
33 private int $encoding;
34 /**
35 * @inheritDoc
36 * @throws \chillerlan\QRCode\Data\QRCodeDataException
37 * @noinspection PhpMissingParentConstructorInspection
38 */
39 public function __construct(int $encoding)
40 {
41 if ($encoding < 0 || $encoding > 999999) {
42 throw new QRCodeDataException(sprintf('invalid encoding id: "%s"', $encoding));
43 }
44 $this->encoding = $encoding;
45 }
46 /**
47 * @inheritDoc
48 */
49 public function getLengthInBits() : int
50 {
51 if ($this->encoding < 128) {
52 return 8;
53 }
54 if ($this->encoding < 16384) {
55 return 16;
56 }
57 return 24;
58 }
59 /**
60 * Writes an ECI designator to the bitbuffer
61 *
62 * @inheritDoc
63 * @throws \chillerlan\QRCode\Data\QRCodeDataException
64 */
65 public function write(BitBuffer $bitBuffer, int $versionNumber) : QRDataModeInterface
66 {
67 $bitBuffer->put(self::DATAMODE, 4);
68 if ($this->encoding < 128) {
69 $bitBuffer->put($this->encoding, 8);
70 } elseif ($this->encoding < 16384) {
71 $bitBuffer->put($this->encoding | 0x8000, 16);
72 } elseif ($this->encoding < 1000000) {
73 $bitBuffer->put($this->encoding | 0xc00000, 24);
74 } else {
75 throw new QRCodeDataException('invalid ECI ID');
76 }
77 return $this;
78 }
79 /**
80 * Reads and parses the value of an ECI designator
81 *
82 * @throws \chillerlan\QRCode\Data\QRCodeDataException
83 */
84 public static function parseValue(BitBuffer $bitBuffer) : ECICharset
85 {
86 $firstByte = $bitBuffer->read(8);
87 // just one byte
88 if (($firstByte & 0b10000000) === 0) {
89 $id = $firstByte & 0b1111111;
90 } elseif (($firstByte & 0b11000000) === 0b10000000) {
91 $id = ($firstByte & 0b111111) << 8 | $bitBuffer->read(8);
92 } elseif (($firstByte & 0b11100000) === 0b11000000) {
93 $id = ($firstByte & 0b11111) << 16 | $bitBuffer->read(16);
94 } else {
95 throw new QRCodeDataException(sprintf('error decoding ECI value first byte: %08b', $firstByte));
96 // @codeCoverageIgnore
97 }
98 return new ECICharset($id);
99 }
100 /**
101 * @codeCoverageIgnore Unused, but required as per interface
102 */
103 public static function validateString(string $string) : bool
104 {
105 return \true;
106 }
107 /**
108 * Reads and decodes the ECI designator including the following byte sequence
109 *
110 * @throws \chillerlan\QRCode\Data\QRCodeDataException
111 */
112 public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber) : string
113 {
114 $eciCharset = self::parseValue($bitBuffer);
115 $nextMode = $bitBuffer->read(4);
116 $data = self::decodeModeSegment($nextMode, $bitBuffer, $versionNumber);
117 $encoding = $eciCharset->getName();
118 if ($encoding === null) {
119 // The spec isn't clear on this mode; see
120 // section 6.4.5: it does not say which encoding to assuming
121 // upon decoding. I have seen ISO-8859-1 used as well as
122 // Shift_JIS -- without anything like an ECI designator to
123 // give a hint.
124 $encoding = mb_detect_encoding($data, ['ISO-8859-1', 'Windows-1252', 'SJIS', 'UTF-8'], \true);
125 if ($encoding === \false) {
126 throw new QRCodeDataException('could not determine encoding in ECI mode');
127 // @codeCoverageIgnore
128 }
129 }
130 return mb_convert_encoding($data, mb_internal_encoding(), $encoding);
131 }
132 /**
133 * @throws \chillerlan\QRCode\Data\QRCodeDataException
134 */
135 private static function decodeModeSegment(int $mode, BitBuffer $bitBuffer, int $versionNumber) : string
136 {
137 switch (\true) {
138 case $mode === Mode::NUMBER:
139 return Number::decodeSegment($bitBuffer, $versionNumber);
140 case $mode === Mode::ALPHANUM:
141 return AlphaNum::decodeSegment($bitBuffer, $versionNumber);
142 case $mode === Mode::BYTE:
143 return Byte::decodeSegment($bitBuffer, $versionNumber);
144 }
145 throw new QRCodeDataException(sprintf('ECI designator followed by invalid mode: "%04b"', $mode));
146 }
147 }
148