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 / Kanji.php

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

156 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 /**
4 * Class Kanji
5 *
6 * @created 25.11.2015
7 * @author Smiley <[email protected]>
8 * @copyright 2015 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\Mode;
15 use Throwable;
16 use function chr, implode, intdiv, is_string, mb_convert_encoding, mb_detect_encoding, mb_internal_encoding, mb_strlen, ord, sprintf, strlen;
17 /**
18 * Kanji mode: 13-bit double-byte characters from the Shift-JIS character set
19 *
20 * ISO/IEC 18004:2000 Section 8.3.5
21 * ISO/IEC 18004:2000 Section 8.4.5
22 *
23 * @see https://en.wikipedia.org/wiki/Shift_JIS#As_defined_in_JIS_X_0208:1997
24 * @see http://www.rikai.com/library/kanjitables/kanji_codes.sjis.shtml
25 * @see https://gist.github.com/codemasher/d07d3e6e9346c08e7a41b8b978784952
26 */
27 final class Kanji extends QRDataModeAbstract
28 {
29 /**
30 * possible values: SJIS, SJIS-2004
31 *
32 * SJIS-2004 may produce errors in PHP < 8
33 *
34 * @var string
35 */
36 public const ENCODING = 'SJIS';
37 /**
38 * @inheritDoc
39 */
40 public const DATAMODE = Mode::KANJI;
41 /**
42 * @inheritDoc
43 */
44 protected function getCharCount() : int
45 {
46 return mb_strlen($this->data, self::ENCODING);
47 }
48 /**
49 * @inheritDoc
50 */
51 public function getLengthInBits() : int
52 {
53 return $this->getCharCount() * 13;
54 }
55 /**
56 * @inheritDoc
57 * @throws \chillerlan\QRCode\Data\QRCodeDataException
58 */
59 public static function convertEncoding(string $string) : string
60 {
61 $detected = mb_detect_encoding($string, [mb_internal_encoding(), 'UTF-8', 'SJIS', 'SJIS-2004'], \true);
62 if ($detected === \false) {
63 throw new QRCodeDataException('mb_detect_encoding error');
64 }
65 if ($detected === self::ENCODING) {
66 return $string;
67 }
68 $string = mb_convert_encoding($string, self::ENCODING, $detected);
69 if (!is_string($string)) {
70 throw new QRCodeDataException(sprintf('invalid encoding: %s', $detected));
71 }
72 return $string;
73 }
74 /**
75 * checks if a string qualifies as SJIS Kanji
76 */
77 public static function validateString(string $string) : bool
78 {
79 try {
80 $string = self::convertEncoding($string);
81 } catch (Throwable $e) {
82 return \false;
83 }
84 $len = strlen($string);
85 if ($len < 2 || $len % 2 !== 0) {
86 return \false;
87 }
88 for ($i = 0; $i < $len; $i += 2) {
89 $byte1 = ord($string[$i]);
90 $byte2 = ord($string[$i + 1]);
91 // byte 1 unused and vendor ranges
92 if ($byte1 < 0x81 || $byte1 > 0x84 && $byte1 < 0x88 || $byte1 > 0x9f && $byte1 < 0xe0 || $byte1 > 0xea) {
93 return \false;
94 }
95 // byte 2 unused ranges
96 if ($byte2 < 0x40 || $byte2 === 0x7f || $byte2 > 0xfc) {
97 return \false;
98 }
99 }
100 return \true;
101 }
102 /**
103 * @inheritDoc
104 *
105 * @throws \chillerlan\QRCode\Data\QRCodeDataException on an illegal character occurence
106 */
107 public function write(BitBuffer $bitBuffer, int $versionNumber) : QRDataModeInterface
108 {
109 $bitBuffer->put(self::DATAMODE, 4)->put($this->getCharCount(), $this::getLengthBits($versionNumber));
110 $len = strlen($this->data);
111 for ($i = 0; $i + 1 < $len; $i += 2) {
112 $c = (0xff & ord($this->data[$i])) << 8 | 0xff & ord($this->data[$i + 1]);
113 if ($c >= 0x8140 && $c <= 0x9ffc) {
114 $c -= 0x8140;
115 } elseif ($c >= 0xe040 && $c <= 0xebbf) {
116 $c -= 0xc140;
117 } else {
118 throw new QRCodeDataException(sprintf('illegal char at %d [%d]', $i + 1, $c));
119 }
120 $bitBuffer->put(($c >> 8 & 0xff) * 0xc0 + ($c & 0xff), 13);
121 }
122 if ($i < $len) {
123 throw new QRCodeDataException(sprintf('illegal char at %d', $i + 1));
124 }
125 return $this;
126 }
127 /**
128 * @inheritDoc
129 *
130 * @throws \chillerlan\QRCode\Data\QRCodeDataException
131 */
132 public static function decodeSegment(BitBuffer $bitBuffer, int $versionNumber) : string
133 {
134 $length = $bitBuffer->read(self::getLengthBits($versionNumber));
135 if ($bitBuffer->available() < $length * 13) {
136 throw new QRCodeDataException('not enough bits available');
137 // @codeCoverageIgnore
138 }
139 // Each character will require 2 bytes. Read the characters as 2-byte pairs and decode as SJIS afterwards
140 $buffer = [];
141 $offset = 0;
142 while ($length > 0) {
143 // Each 13 bits encodes a 2-byte character
144 $twoBytes = $bitBuffer->read(13);
145 $assembledTwoBytes = intdiv($twoBytes, 0xc0) << 8 | $twoBytes % 0xc0;
146 $assembledTwoBytes += $assembledTwoBytes < 0x1f00 ? 0x8140 : 0xc140;
147 // In the 0xE040 to 0xEBBF range
148 $buffer[$offset] = chr(0xff & $assembledTwoBytes >> 8);
149 $buffer[$offset + 1] = chr(0xff & $assembledTwoBytes);
150 $offset += 2;
151 $length--;
152 }
153 return mb_convert_encoding(implode('', $buffer), mb_internal_encoding(), self::ENCODING);
154 }
155 }
156