1 | <?php |
||
2 | /* |
||
3 | * PHP QR Code encoder |
||
4 | * |
||
5 | * Input splitting classes |
||
6 | * |
||
7 | * Based on libqrencode C library distributed under LGPL 2.1 |
||
8 | * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]> |
||
9 | * |
||
10 | * PHP QR Code is distributed under LGPL 3 |
||
11 | * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm> |
||
12 | * |
||
13 | * The following data / specifications are taken from |
||
14 | * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004) |
||
15 | * or |
||
16 | * "Automatic identification and data capture techniques -- |
||
17 | * QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006) |
||
18 | * |
||
19 | * This library is free software; you can redistribute it and/or |
||
20 | * modify it under the terms of the GNU Lesser General Public |
||
21 | * License as published by the Free Software Foundation; either |
||
22 | * version 3 of the License, or any later version. |
||
23 | * |
||
24 | * This library is distributed in the hope that it will be useful, |
||
25 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
26 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||
27 | * Lesser General Public License for more details. |
||
28 | * |
||
29 | * You should have received a copy of the GNU Lesser General Public |
||
30 | * License along with this library; if not, write to the Free Software |
||
31 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||
32 | */ |
||
33 | class QRsplit { |
||
34 | |||
35 | public $dataStr = ''; |
||
36 | public $input; |
||
37 | public $modeHint; |
||
38 | |||
39 | //---------------------------------------------------------------------- |
||
40 | public function __construct($dataStr, $input, $modeHint) |
||
41 | { |
||
42 | $this->dataStr = $dataStr; |
||
43 | $this->input = $input; |
||
44 | $this->modeHint = $modeHint; |
||
45 | } |
||
46 | |||
47 | //---------------------------------------------------------------------- |
||
48 | public static function isdigitat($str, $pos) |
||
49 | { |
||
50 | if ($pos >= strlen($str)) { |
||
51 | return false; |
||
52 | } |
||
53 | |||
54 | return ((ord($str[$pos]) >= ord('0')) && (ord($str[$pos]) <= ord('9'))); |
||
55 | } |
||
56 | |||
57 | //---------------------------------------------------------------------- |
||
58 | public static function isalnumat($str, $pos) |
||
59 | { |
||
60 | if ($pos >= strlen($str)) { |
||
61 | return false; |
||
62 | } |
||
63 | |||
64 | return (QRinput::lookAnTable(ord($str[$pos])) >= 0); |
||
65 | } |
||
66 | |||
67 | //---------------------------------------------------------------------- |
||
68 | public function identifyMode($pos) |
||
69 | { |
||
70 | if ($pos >= strlen($this->dataStr)) { |
||
71 | return QR_MODE_NUL; |
||
72 | } |
||
73 | |||
74 | $c = $this->dataStr[$pos]; |
||
75 | |||
76 | if (self::isdigitat($this->dataStr, $pos)) { |
||
77 | return QR_MODE_NUM; |
||
78 | } else if (self::isalnumat($this->dataStr, $pos)) { |
||
79 | return QR_MODE_AN; |
||
80 | } else if ($this->modeHint == QR_MODE_KANJI) { |
||
81 | |||
82 | if ($pos + 1 < strlen($this->dataStr)) |
||
83 | { |
||
84 | $d = $this->dataStr[$pos + 1]; |
||
85 | $word = (ord($c) << 8) | ord($d); |
||
86 | if (($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) { |
||
87 | return QR_MODE_KANJI; |
||
88 | } |
||
89 | } |
||
90 | } |
||
91 | |||
92 | return QR_MODE_8; |
||
93 | } |
||
94 | |||
95 | //---------------------------------------------------------------------- |
||
96 | public function eatNum() |
||
97 | { |
||
98 | $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); |
||
99 | |||
100 | $p = 0; |
||
101 | while (self::isdigitat($this->dataStr, $p)) { |
||
102 | $p++; |
||
103 | } |
||
104 | |||
105 | $run = $p; |
||
106 | $mode = $this->identifyMode($p); |
||
107 | |||
108 | if ($mode == QR_MODE_8) { |
||
109 | $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln |
||
110 | + QRinput::estimateBitsMode8(1) // + 4 + l8 |
||
111 | - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 |
||
112 | if ($dif > 0) { |
||
113 | return $this->eat8(); |
||
114 | } |
||
115 | } |
||
116 | if ($mode == QR_MODE_AN) { |
||
117 | $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln |
||
118 | + QRinput::estimateBitsModeAn(1) // + 4 + la |
||
119 | - QRinput::estimateBitsModeAn($run + 1); // - 4 - la |
||
120 | if ($dif > 0) { |
||
121 | return $this->eatAn(); |
||
122 | } |
||
123 | } |
||
124 | |||
125 | $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr)); |
||
126 | if ($ret < 0) { |
||
127 | return -1; |
||
128 | } |
||
129 | |||
130 | return $run; |
||
131 | } |
||
132 | |||
133 | //---------------------------------------------------------------------- |
||
134 | public function eatAn() |
||
135 | { |
||
136 | $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); |
||
137 | $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); |
||
138 | |||
139 | $p = 0; |
||
140 | |||
141 | while (self::isalnumat($this->dataStr, $p)) { |
||
142 | if (self::isdigitat($this->dataStr, $p)) { |
||
143 | $q = $p; |
||
144 | while (self::isdigitat($this->dataStr, $q)) { |
||
145 | $q++; |
||
146 | } |
||
147 | |||
148 | $dif = QRinput::estimateBitsModeAn($p) // + 4 + la |
||
149 | + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln |
||
150 | - QRinput::estimateBitsModeAn($q); // - 4 - la |
||
151 | |||
152 | if ($dif < 0) { |
||
153 | break; |
||
154 | } else { |
||
155 | $p = $q; |
||
156 | } |
||
157 | } else { |
||
158 | $p++; |
||
159 | } |
||
160 | } |
||
161 | |||
162 | $run = $p; |
||
163 | |||
164 | if (!self::isalnumat($this->dataStr, $p)) { |
||
165 | $dif = QRinput::estimateBitsModeAn($run) + 4 + $la |
||
166 | + QRinput::estimateBitsMode8(1) // + 4 + l8 |
||
167 | - QRinput::estimateBitsMode8($run + 1); // - 4 - l8 |
||
168 | if ($dif > 0) { |
||
169 | return $this->eat8(); |
||
170 | } |
||
171 | } |
||
172 | |||
173 | $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr)); |
||
174 | if ($ret < 0) { |
||
175 | return -1; |
||
176 | } |
||
177 | |||
178 | return $run; |
||
179 | } |
||
180 | |||
181 | //---------------------------------------------------------------------- |
||
182 | public function eatKanji() |
||
183 | { |
||
184 | $p = 0; |
||
185 | |||
186 | while ($this->identifyMode($p) == QR_MODE_KANJI) { |
||
187 | $p += 2; |
||
188 | } |
||
189 | |||
190 | $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr)); |
||
191 | if ($ret < 0) { |
||
192 | return -1; |
||
193 | } |
||
194 | |||
195 | return $ret; |
||
196 | } |
||
197 | |||
198 | //---------------------------------------------------------------------- |
||
199 | public function eat8() |
||
200 | { |
||
201 | $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion()); |
||
202 | $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion()); |
||
203 | |||
204 | $p = 1; |
||
205 | $dataStrLen = strlen($this->dataStr); |
||
206 | |||
207 | while ($p < $dataStrLen) { |
||
208 | |||
209 | $mode = $this->identifyMode($p); |
||
210 | if ($mode == QR_MODE_KANJI) { |
||
211 | break; |
||
212 | } |
||
213 | if ($mode == QR_MODE_NUM) { |
||
214 | $q = $p; |
||
215 | while (self::isdigitat($this->dataStr, $q)) { |
||
216 | $q++; |
||
217 | } |
||
218 | $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 |
||
219 | + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln |
||
220 | - QRinput::estimateBitsMode8($q); // - 4 - l8 |
||
221 | if ($dif < 0) { |
||
222 | break; |
||
223 | } else { |
||
224 | $p = $q; |
||
225 | } |
||
226 | } else if ($mode == QR_MODE_AN) { |
||
227 | $q = $p; |
||
228 | while (self::isalnumat($this->dataStr, $q)) { |
||
229 | $q++; |
||
230 | } |
||
231 | $dif = QRinput::estimateBitsMode8($p) // + 4 + l8 |
||
232 | + QRinput::estimateBitsModeAn($q - $p) + 4 + $la |
||
233 | - QRinput::estimateBitsMode8($q); // - 4 - l8 |
||
234 | if ($dif < 0) { |
||
235 | break; |
||
236 | } else { |
||
237 | $p = $q; |
||
238 | } |
||
239 | } else { |
||
240 | $p++; |
||
241 | } |
||
242 | } |
||
243 | |||
244 | $run = $p; |
||
245 | $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr)); |
||
246 | |||
247 | if ($ret < 0) { |
||
248 | return -1; |
||
249 | } |
||
250 | |||
251 | return $run; |
||
252 | } |
||
253 | |||
254 | //---------------------------------------------------------------------- |
||
255 | public function splitString() |
||
256 | { |
||
257 | while (strlen($this->dataStr) > 0) |
||
258 | { |
||
259 | if ($this->dataStr == '') { |
||
260 | return 0; |
||
261 | } |
||
262 | |||
263 | $mode = $this->identifyMode(0); |
||
264 | |||
265 | switch ($mode) { |
||
266 | case QR_MODE_NUM: $length = $this->eatNum(); break; |
||
267 | case QR_MODE_AN: $length = $this->eatAn(); break; |
||
268 | case QR_MODE_KANJI: |
||
269 | if ($this->modeHint == QR_MODE_KANJI) { |
||
270 | $length = $this->eatKanji(); |
||
271 | } else { |
||
272 | $length = $this->eat8(); |
||
273 | } |
||
274 | break; |
||
275 | default: $length = $this->eat8(); break; |
||
276 | |||
277 | } |
||
278 | |||
279 | if ($length == 0) { |
||
280 | return 0; |
||
281 | } |
||
282 | if ($length < 0) { |
||
283 | return -1; |
||
284 | } |
||
285 | |||
286 | $this->dataStr = substr($this->dataStr, $length); |
||
287 | } |
||
288 | } |
||
289 | |||
290 | //---------------------------------------------------------------------- |
||
291 | public function toUpper() |
||
292 | { |
||
293 | $stringLen = strlen($this->dataStr); |
||
294 | $p = 0; |
||
295 | |||
296 | while ($p < $stringLen) { |
||
297 | $mode = self::identifyMode(substr($this->dataStr, $p)); |
||
0 ignored issues
–
show
Bug
Best Practice
introduced
by
![]() |
|||
298 | if ($mode == QR_MODE_KANJI) { |
||
299 | $p += 2; |
||
300 | } else { |
||
301 | if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) { |
||
302 | $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32); |
||
303 | } |
||
304 | $p++; |
||
305 | } |
||
306 | } |
||
307 | |||
308 | return $this->dataStr; |
||
309 | } |
||
310 | |||
311 | //---------------------------------------------------------------------- |
||
312 | public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true) |
||
313 | { |
||
314 | if (is_null($string) || $string == '\0' || $string == '') { |
||
315 | throw new Exception('empty string!!!'); |
||
316 | } |
||
317 | |||
318 | $split = new QRsplit($string, $input, $modeHint); |
||
319 | |||
320 | if (!$casesensitive) { |
||
321 | $split->toUpper(); |
||
322 | } |
||
323 | |||
324 | return $split->splitString(); |
||
325 | } |
||
326 | } |
||
327 |