1 | <?php |
||||
2 | /* |
||||
3 | * PHP QR Code encoder |
||||
4 | * |
||||
5 | * Main encoder 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 | * This library is free software; you can redistribute it and/or |
||||
14 | * modify it under the terms of the GNU Lesser General Public |
||||
15 | * License as published by the Free Software Foundation; either |
||||
16 | * version 3 of the License, or any later version. |
||||
17 | * |
||||
18 | * This library is distributed in the hope that it will be useful, |
||||
19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||
21 | * Lesser General Public License for more details. |
||||
22 | * |
||||
23 | * You should have received a copy of the GNU Lesser General Public |
||||
24 | * License along with this library; if not, write to the Free Software |
||||
25 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
||||
26 | */ |
||||
27 | |||||
28 | class QRrsblock { |
||||
29 | public $dataLength; |
||||
30 | public $data = array(); |
||||
31 | public $eccLength; |
||||
32 | public $ecc = array(); |
||||
33 | |||||
34 | public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs) |
||||
35 | { |
||||
36 | $rs->encode_rs_char($data, $ecc); |
||||
37 | |||||
38 | $this->dataLength = $dl; |
||||
39 | $this->data = $data; |
||||
40 | $this->eccLength = $el; |
||||
41 | $this->ecc = $ecc; |
||||
42 | } |
||||
43 | }; |
||||
44 | |||||
45 | //########################################################################## |
||||
46 | |||||
47 | class QRrawcode { |
||||
48 | public $version; |
||||
49 | public $datacode = array(); |
||||
50 | public $ecccode = array(); |
||||
51 | public $blocks; |
||||
52 | public $rsblocks = array(); //of RSblock |
||||
53 | public $count; |
||||
54 | public $dataLength; |
||||
55 | public $eccLength; |
||||
56 | public $b1; |
||||
57 | |||||
58 | //---------------------------------------------------------------------- |
||||
59 | public function __construct(QRinput $input) |
||||
60 | { |
||||
61 | $spec = array(0, 0, 0, 0, 0); |
||||
62 | |||||
63 | $this->datacode = $input->getByteStream(); |
||||
0 ignored issues
–
show
|
|||||
64 | if (is_null($this->datacode)) { |
||||
0 ignored issues
–
show
|
|||||
65 | throw new Exception('null imput string'); |
||||
66 | } |
||||
67 | |||||
68 | QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec); |
||||
69 | |||||
70 | $this->version = $input->getVersion(); |
||||
71 | $this->b1 = QRspec::rsBlockNum1($spec); |
||||
72 | $this->dataLength = QRspec::rsDataLength($spec); |
||||
73 | $this->eccLength = QRspec::rsEccLength($spec); |
||||
74 | $this->ecccode = array_fill(0, $this->eccLength, 0); |
||||
75 | $this->blocks = QRspec::rsBlockNum($spec); |
||||
76 | |||||
77 | $ret = $this->init($spec); |
||||
78 | if ($ret < 0) { |
||||
79 | throw new Exception('block alloc error'); |
||||
80 | return null; |
||||
0 ignored issues
–
show
return null is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||||
81 | } |
||||
82 | |||||
83 | $this->count = 0; |
||||
84 | } |
||||
85 | |||||
86 | //---------------------------------------------------------------------- |
||||
87 | public function init(array $spec) |
||||
88 | { |
||||
89 | $dl = QRspec::rsDataCodes1($spec); |
||||
90 | $el = QRspec::rsEccCodes1($spec); |
||||
91 | $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); |
||||
92 | |||||
93 | |||||
94 | $blockNo = 0; |
||||
95 | $dataPos = 0; |
||||
96 | $eccPos = 0; |
||||
97 | for ($i = 0; $i < QRspec::rsBlockNum1($spec); $i++) { |
||||
98 | $ecc = array_slice($this->ecccode, $eccPos); |
||||
99 | $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); |
||||
0 ignored issues
–
show
It seems like
$rs can also be of type null ; however, parameter $rs of QRrsblock::__construct() does only seem to accept QRrsItem , maybe add an additional type check?
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
![]() |
|||||
100 | $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc); |
||||
101 | |||||
102 | $dataPos += $dl; |
||||
103 | $eccPos += $el; |
||||
104 | $blockNo++; |
||||
105 | } |
||||
106 | |||||
107 | if (QRspec::rsBlockNum2($spec) == 0) { |
||||
108 | return 0; |
||||
109 | } |
||||
110 | |||||
111 | $dl = QRspec::rsDataCodes2($spec); |
||||
112 | $el = QRspec::rsEccCodes2($spec); |
||||
113 | $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el); |
||||
114 | |||||
115 | if ($rs == null) { |
||||
116 | return -1; |
||||
117 | } |
||||
118 | |||||
119 | for ($i = 0; $i < QRspec::rsBlockNum2($spec); $i++) { |
||||
120 | $ecc = array_slice($this->ecccode, $eccPos); |
||||
121 | $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs); |
||||
122 | $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc); |
||||
123 | |||||
124 | $dataPos += $dl; |
||||
125 | $eccPos += $el; |
||||
126 | $blockNo++; |
||||
127 | } |
||||
128 | |||||
129 | return 0; |
||||
130 | } |
||||
131 | |||||
132 | //---------------------------------------------------------------------- |
||||
133 | public function getCode() |
||||
134 | { |
||||
135 | $ret = 0; |
||||
136 | |||||
137 | if ($this->count < $this->dataLength) { |
||||
138 | $row = $this->count % $this->blocks; |
||||
139 | $col = $this->count / $this->blocks; |
||||
140 | if ($col >= $this->rsblocks[0]->dataLength) { |
||||
141 | $row += $this->b1; |
||||
142 | } |
||||
143 | $ret = $this->rsblocks[$row]->data[$col]; |
||||
144 | } else if ($this->count < $this->dataLength + $this->eccLength) { |
||||
145 | $row = ($this->count - $this->dataLength) % $this->blocks; |
||||
146 | $col = ($this->count - $this->dataLength) / $this->blocks; |
||||
147 | $ret = $this->rsblocks[$row]->ecc[$col]; |
||||
148 | } else { |
||||
149 | return 0; |
||||
150 | } |
||||
151 | $this->count++; |
||||
152 | |||||
153 | return $ret; |
||||
154 | } |
||||
155 | } |
||||
156 | |||||
157 | //########################################################################## |
||||
158 | |||||
159 | class QRcode { |
||||
160 | |||||
161 | public $version; |
||||
162 | public $width; |
||||
163 | public $data; |
||||
164 | |||||
165 | //---------------------------------------------------------------------- |
||||
166 | public function encodeMask(QRinput $input, $mask) |
||||
167 | { |
||||
168 | if ($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) { |
||||
169 | throw new Exception('wrong version'); |
||||
170 | } |
||||
171 | if ($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) { |
||||
172 | throw new Exception('wrong level'); |
||||
173 | } |
||||
174 | |||||
175 | $raw = new QRrawcode($input); |
||||
176 | |||||
177 | QRtools::markTime('after_raw'); |
||||
178 | |||||
179 | $version = $raw->version; |
||||
180 | $width = QRspec::getWidth($version); |
||||
181 | $frame = QRspec::newFrame($version); |
||||
182 | |||||
183 | $filler = new FrameFiller($width, $frame); |
||||
184 | if (is_null($filler)) { |
||||
185 | return null; |
||||
186 | } |
||||
187 | |||||
188 | // inteleaved data and ecc codes |
||||
189 | for ($i = 0; $i < $raw->dataLength + $raw->eccLength; $i++) { |
||||
190 | $code = $raw->getCode(); |
||||
191 | $bit = 0x80; |
||||
192 | for ($j = 0; $j < 8; $j++) { |
||||
193 | $addr = $filler->next(); |
||||
194 | $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0)); |
||||
195 | $bit = $bit >> 1; |
||||
196 | } |
||||
197 | } |
||||
198 | |||||
199 | QRtools::markTime('after_filler'); |
||||
200 | |||||
201 | unset($raw); |
||||
202 | |||||
203 | // remainder bits |
||||
204 | $j = QRspec::getRemainder($version); |
||||
205 | for ($i = 0; $i < $j; $i++) { |
||||
206 | $addr = $filler->next(); |
||||
207 | $filler->setFrameAt($addr, 0x02); |
||||
208 | } |
||||
209 | |||||
210 | $frame = $filler->frame; |
||||
211 | unset($filler); |
||||
212 | |||||
213 | |||||
214 | // masking |
||||
215 | $maskObj = new QRmask(); |
||||
216 | if ($mask < 0) { |
||||
217 | |||||
218 | if (QR_FIND_BEST_MASK) { |
||||
219 | $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel()); |
||||
220 | } else { |
||||
221 | $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel()); |
||||
222 | } |
||||
223 | } else { |
||||
224 | $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel()); |
||||
225 | } |
||||
226 | |||||
227 | if ($masked == null) { |
||||
228 | return null; |
||||
229 | } |
||||
230 | |||||
231 | QRtools::markTime('after_mask'); |
||||
232 | |||||
233 | $this->version = $version; |
||||
234 | $this->width = $width; |
||||
235 | $this->data = $masked; |
||||
236 | |||||
237 | return $this; |
||||
238 | } |
||||
239 | |||||
240 | //---------------------------------------------------------------------- |
||||
241 | public function encodeInput(QRinput $input) |
||||
242 | { |
||||
243 | return $this->encodeMask($input, -1); |
||||
244 | } |
||||
245 | |||||
246 | //---------------------------------------------------------------------- |
||||
247 | public function encodeString8bit($string, $version, $level) |
||||
248 | { |
||||
249 | if (string == null) { |
||||
0 ignored issues
–
show
|
|||||
250 | throw new Exception('empty string!'); |
||||
251 | return null; |
||||
0 ignored issues
–
show
return null is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||||
252 | } |
||||
253 | |||||
254 | $input = new QRinput($version, $level); |
||||
255 | if ($input == null) { |
||||
256 | return null; |
||||
257 | } |
||||
258 | |||||
259 | $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string)); |
||||
0 ignored issues
–
show
The call to
QRinput::append() has too many arguments starting with str_split($string) .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above. ![]() |
|||||
260 | if ($ret < 0) { |
||||
261 | unset($input); |
||||
262 | return null; |
||||
263 | } |
||||
264 | return $this->encodeInput($input); |
||||
265 | } |
||||
266 | |||||
267 | //---------------------------------------------------------------------- |
||||
268 | public function encodeString($string, $version, $level, $hint, $casesensitive) |
||||
269 | { |
||||
270 | |||||
271 | if ($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) { |
||||
272 | throw new Exception('bad hint'); |
||||
273 | return null; |
||||
0 ignored issues
–
show
return null is not reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||||
274 | } |
||||
275 | |||||
276 | $input = new QRinput($version, $level); |
||||
277 | if ($input == null) { |
||||
278 | return null; |
||||
279 | } |
||||
280 | |||||
281 | $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive); |
||||
282 | if ($ret < 0) { |
||||
283 | return null; |
||||
284 | } |
||||
285 | |||||
286 | return $this->encodeInput($input); |
||||
287 | } |
||||
288 | |||||
289 | //---------------------------------------------------------------------- |
||||
290 | public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint = false) |
||||
0 ignored issues
–
show
The parameter
$saveandprint is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
291 | { |
||||
292 | $enc = QRencode::factory($level, $size, $margin); |
||||
293 | return $enc->encodePNG($text, $outfile, $saveandprint = false); |
||||
0 ignored issues
–
show
Are you sure the usage of
$enc->encodePNG($text, $... $saveandprint = false) targeting QRencode::encodePNG() seems to always return null.
This check looks for function or method calls that always return null and whose return value is used. class A
{
function getObject()
{
return null;
}
}
$a = new A();
if ($a->getObject()) {
The method The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes. ![]() |
|||||
294 | } |
||||
295 | |||||
296 | //---------------------------------------------------------------------- |
||||
297 | public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) |
||||
298 | { |
||||
299 | $enc = QRencode::factory($level, $size, $margin); |
||||
300 | return $enc->encode($text, $outfile); |
||||
301 | } |
||||
302 | |||||
303 | //---------------------------------------------------------------------- |
||||
304 | public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4) |
||||
305 | { |
||||
306 | $enc = QRencode::factory($level, $size, $margin); |
||||
307 | return $enc->encodeRAW($text, $outfile); |
||||
308 | } |
||||
309 | } |
||||
310 | |||||
311 | //########################################################################## |
||||
312 | |||||
313 | class FrameFiller { |
||||
314 | |||||
315 | public $width; |
||||
316 | public $frame; |
||||
317 | public $x; |
||||
318 | public $y; |
||||
319 | public $dir; |
||||
320 | public $bit; |
||||
321 | |||||
322 | //---------------------------------------------------------------------- |
||||
323 | public function __construct($width, &$frame) |
||||
324 | { |
||||
325 | $this->width = $width; |
||||
326 | $this->frame = $frame; |
||||
327 | $this->x = $width - 1; |
||||
328 | $this->y = $width - 1; |
||||
329 | $this->dir = -1; |
||||
330 | $this->bit = -1; |
||||
331 | } |
||||
332 | |||||
333 | //---------------------------------------------------------------------- |
||||
334 | public function setFrameAt($at, $val) |
||||
335 | { |
||||
336 | $this->frame[$at['y']][$at['x']] = chr($val); |
||||
337 | } |
||||
338 | |||||
339 | //---------------------------------------------------------------------- |
||||
340 | public function getFrameAt($at) |
||||
341 | { |
||||
342 | return ord($this->frame[$at['y']][$at['x']]); |
||||
343 | } |
||||
344 | |||||
345 | //---------------------------------------------------------------------- |
||||
346 | public function next() |
||||
347 | { |
||||
348 | do { |
||||
349 | |||||
350 | if ($this->bit == -1) { |
||||
351 | $this->bit = 0; |
||||
352 | return array('x'=>$this->x, 'y'=>$this->y); |
||||
353 | } |
||||
354 | |||||
355 | $x = $this->x; |
||||
356 | $y = $this->y; |
||||
357 | $w = $this->width; |
||||
358 | |||||
359 | if ($this->bit == 0) { |
||||
360 | $x--; |
||||
361 | $this->bit++; |
||||
362 | } else { |
||||
363 | $x++; |
||||
364 | $y += $this->dir; |
||||
365 | $this->bit--; |
||||
366 | } |
||||
367 | |||||
368 | if ($this->dir < 0) { |
||||
369 | if ($y < 0) { |
||||
370 | $y = 0; |
||||
371 | $x -= 2; |
||||
372 | $this->dir = 1; |
||||
373 | if ($x == 6) { |
||||
374 | $x--; |
||||
375 | $y = 9; |
||||
376 | } |
||||
377 | } |
||||
378 | } else { |
||||
379 | if ($y == $w) { |
||||
380 | $y = $w - 1; |
||||
381 | $x -= 2; |
||||
382 | $this->dir = -1; |
||||
383 | if ($x == 6) { |
||||
384 | $x--; |
||||
385 | $y -= 8; |
||||
386 | } |
||||
387 | } |
||||
388 | } |
||||
389 | if ($x < 0 || $y < 0) { |
||||
390 | return null; |
||||
391 | } |
||||
392 | |||||
393 | $this->x = $x; |
||||
394 | $this->y = $y; |
||||
395 | |||||
396 | } while (ord($this->frame[$y][$x]) & 0x80); |
||||
397 | |||||
398 | return array('x'=>$x, 'y'=>$y); |
||||
399 | } |
||||
400 | |||||
401 | } ; |
||||
402 | |||||
403 | //########################################################################## |
||||
404 | |||||
405 | class QRencode { |
||||
406 | |||||
407 | public $casesensitive = true; |
||||
408 | public $eightbit = false; |
||||
409 | |||||
410 | public $version = 0; |
||||
411 | public $size = 3; |
||||
412 | public $margin = 4; |
||||
413 | |||||
414 | public $structured = 0; // not supported yet |
||||
415 | |||||
416 | public $level = QR_ECLEVEL_L; |
||||
417 | public $hint = QR_MODE_8; |
||||
418 | |||||
419 | //---------------------------------------------------------------------- |
||||
420 | public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4) |
||||
421 | { |
||||
422 | $enc = new QRencode(); |
||||
423 | $enc->size = $size; |
||||
424 | $enc->margin = $margin; |
||||
425 | |||||
426 | switch ($level.'') { |
||||
427 | case '0': |
||||
428 | case '1': |
||||
429 | case '2': |
||||
430 | case '3': |
||||
431 | $enc->level = $level; |
||||
432 | break; |
||||
433 | case 'l': |
||||
434 | case 'L': |
||||
435 | $enc->level = QR_ECLEVEL_L; |
||||
436 | break; |
||||
437 | case 'm': |
||||
438 | case 'M': |
||||
439 | $enc->level = QR_ECLEVEL_M; |
||||
440 | break; |
||||
441 | case 'q': |
||||
442 | case 'Q': |
||||
443 | $enc->level = QR_ECLEVEL_Q; |
||||
444 | break; |
||||
445 | case 'h': |
||||
446 | case 'H': |
||||
447 | $enc->level = QR_ECLEVEL_H; |
||||
448 | break; |
||||
449 | } |
||||
450 | |||||
451 | return $enc; |
||||
452 | } |
||||
453 | |||||
454 | //---------------------------------------------------------------------- |
||||
455 | public function encodeRAW($intext, $outfile = false) |
||||
0 ignored issues
–
show
The parameter
$outfile is not used and could be removed.
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check looks for parameters that have been defined for a function or method, but which are not used in the method body. ![]() |
|||||
456 | { |
||||
457 | $code = new QRcode(); |
||||
458 | |||||
459 | if ($this->eightbit) { |
||||
460 | $code->encodeString8bit($intext, $this->version, $this->level); |
||||
461 | } else { |
||||
462 | $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); |
||||
463 | } |
||||
464 | |||||
465 | return $code->data; |
||||
466 | } |
||||
467 | |||||
468 | //---------------------------------------------------------------------- |
||||
469 | public function encode($intext, $outfile = false) |
||||
470 | { |
||||
471 | $code = new QRcode(); |
||||
472 | |||||
473 | if ($this->eightbit) { |
||||
474 | $code->encodeString8bit($intext, $this->version, $this->level); |
||||
475 | } else { |
||||
476 | $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive); |
||||
477 | } |
||||
478 | |||||
479 | QRtools::markTime('after_encode'); |
||||
480 | |||||
481 | if ($outfile !== false) { |
||||
482 | file_put_contents($outfile, join("\n", QRtools::binarize($code->data))); |
||||
483 | } else { |
||||
484 | return QRtools::binarize($code->data); |
||||
485 | } |
||||
486 | } |
||||
487 | |||||
488 | //---------------------------------------------------------------------- |
||||
489 | public function encodePNG($intext, $outfile = false, $saveandprint = false) |
||||
490 | { |
||||
491 | try { |
||||
492 | |||||
493 | ob_start(); |
||||
494 | $tab = $this->encode($intext); |
||||
495 | $err = ob_get_contents(); |
||||
496 | ob_end_clean(); |
||||
497 | |||||
498 | if ($err != '') { |
||||
499 | QRtools::log($outfile, $err); |
||||
500 | } |
||||
501 | |||||
502 | $maxSize = (int) (QR_PNG_MAXIMUM_SIZE / (count($tab) + 2 * $this->margin)); |
||||
503 | |||||
504 | QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin, $saveandprint); |
||||
505 | |||||
506 | } catch (Exception $e) { |
||||
507 | |||||
508 | QRtools::log($outfile, $e->getMessage()); |
||||
509 | |||||
510 | } |
||||
511 | } |
||||
512 | } |
||||
513 |
This check looks for function or method calls that always return null and whose return value is assigned to a variable.
The method
getObject()
can return nothing but null, so it makes no sense to assign that value to a variable.The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.