Issues (4542)

config/qrcode/phpqrcode.php (48 issues)

1
<?php
2
3
/*
4
 * PHP QR Code encoder
5
 *
6
 * This file contains MERGED version of PHP QR Code library.
7
 * It was auto-generated from full version for your convenience.
8
 *
9
 * This merged version was configured to not require any external files,
10
 * with disabled cache, error logging and weaker but faster mask matching.
11
 * If you need tune it up please use non-merged version.
12
 *
13
 * For full version, documentation, examples of use please visit:
14
 *
15
 *    http://phpqrcode.sourceforge.net/
16
 *    https://sourceforge.net/projects/phpqrcode/
17
 *    https://github.com/t0k4rt/phpqrcode
18
 *
19
 * PHP QR Code is distributed under LGPL 3
20
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
21
 *
22
 * This library is free software; you can redistribute it and/or
23
 * modify it under the terms of the GNU Lesser General Public
24
 * License as published by the Free Software Foundation; either
25
 * version 3 of the License, or any later version.
26
 *
27
 * This library is distributed in the hope that it will be useful,
28
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
30
 * Lesser General Public License for more details.
31
 *
32
 * You should have received a copy of the GNU Lesser General Public
33
 * License along with this library; if not, write to the Free Software
34
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35
 */
36
37
/*
38
 * Version: 1.1.4
39
 * Build: 2010100721
40
 */
41
42
//---- qrconst.php -----------------------------
43
44
/*
45
 * PHP QR Code encoder
46
 *
47
 * Common constants
48
 *
49
 * Based on libqrencode C library distributed under LGPL 2.1
50
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
51
 *
52
 * PHP QR Code is distributed under LGPL 3
53
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
54
 *
55
 * This library is free software; you can redistribute it and/or
56
 * modify it under the terms of the GNU Lesser General Public
57
 * License as published by the Free Software Foundation; either
58
 * version 3 of the License, or any later version.
59
 *
60
 * This library is distributed in the hope that it will be useful,
61
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
62
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
63
 * Lesser General Public License for more details.
64
 *
65
 * You should have received a copy of the GNU Lesser General Public
66
 * License along with this library; if not, write to the Free Software
67
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
68
 */
69
70
    // Encoding modes
71
72
    define('QR_MODE_NUL', -1);
73
    define('QR_MODE_NUM', 0);
74
    define('QR_MODE_AN', 1);
75
    define('QR_MODE_8', 2);
76
    define('QR_MODE_KANJI', 3);
77
    define('QR_MODE_STRUCTURE', 4);
78
79
    // Levels of error correction.
80
81
    define('QR_ECLEVEL_L', 0);
82
    define('QR_ECLEVEL_M', 1);
83
    define('QR_ECLEVEL_Q', 2);
84
    define('QR_ECLEVEL_H', 3);
85
86
    // Supported output formats
87
88
    define('QR_FORMAT_TEXT', 0);
89
    define('QR_FORMAT_PNG', 1);
90
91
    class qrstr
92
    {
93
        public static function set(&$srctab, $x, $y, $repl, $replLen = false)
94
        {
95
            $srctab[$y] = substr_replace($srctab[$y], ($replLen !== false) ? substr($repl, 0, $replLen) : $repl, $x, ($replLen !== false) ? $replLen : strlen($repl));
96
        }
97
    }
98
99
//---- merged_config.php -----------------------------
100
101
/*
102
 * PHP QR Code encoder
103
 *
104
 * Config file, tuned-up for merged verion
105
 */
106
107
    define('QR_CACHEABLE', false); // use cache - more disk reads but less CPU power, masks and format templates are stored there
108
    define('QR_CACHE_DIR', false); // used when QR_CACHEABLE === true
109
    define('QR_LOG_DIR', false); // default error logs dir
110
111
    define('QR_FIND_BEST_MASK', true); // if true, estimates best mask (spec. default, but extremally slow; set to false to significant performance boost but (propably) worst quality code
112
    define('QR_FIND_FROM_RANDOM', 2); // if false, checks all masks available, otherwise value tells count of masks need to be checked, mask id are got randomly
113
    define('QR_DEFAULT_MASK', 2); // when QR_FIND_BEST_MASK === false
114
115
    define('QR_PNG_MAXIMUM_SIZE', 1024); // maximum allowed png image width (in pixels), tune to make sure GD and PHP can handle such big images
116
117
//---- qrtools.php -----------------------------
118
119
/*
120
 * PHP QR Code encoder
121
 *
122
 * Toolset, handy and debug utilites.
123
 *
124
 * PHP QR Code is distributed under LGPL 3
125
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
126
 *
127
 * This library is free software; you can redistribute it and/or
128
 * modify it under the terms of the GNU Lesser General Public
129
 * License as published by the Free Software Foundation; either
130
 * version 3 of the License, or any later version.
131
 *
132
 * This library is distributed in the hope that it will be useful,
133
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
134
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
135
 * Lesser General Public License for more details.
136
 *
137
 * You should have received a copy of the GNU Lesser General Public
138
 * License along with this library; if not, write to the Free Software
139
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
140
 */
141
142
    class QRtools
143
    {
144
        //----------------------------------------------------------------------
145
        public static function binarize($frame)
146
        {
147
            $len = count($frame);
148
            foreach ($frame as &$frameLine) {
149
                for ($i = 0; $i < $len; $i++) {
150
                    $frameLine[$i] = (ord($frameLine[$i]) & 1) ? '1' : '0';
151
                }
152
            }
153
154
            return $frame;
155
        }
156
157
        //----------------------------------------------------------------------
158
        public static function tcpdfBarcodeArray($code, $mode = 'QR,L', $tcPdfVersion = '4.5.037')
0 ignored issues
show
The parameter $tcPdfVersion 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 ignore-unused  annotation

158
        public static function tcpdfBarcodeArray($code, $mode = 'QR,L', /** @scrutinizer ignore-unused */ $tcPdfVersion = '4.5.037')

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
159
        {
160
            $barcode_array = [];
161
162
            if (!is_array($mode)) {
163
                $mode = explode(',', $mode);
164
            }
165
166
            $eccLevel = 'L';
167
168
            if (count($mode) > 1) {
169
                $eccLevel = $mode[1];
170
            }
171
172
            $qrTab = QRcode::text($code, false, $eccLevel);
173
            $size = count($qrTab);
174
175
            $barcode_array['num_rows'] = $size;
176
            $barcode_array['num_cols'] = $size;
177
            $barcode_array['bcode'] = [];
178
179
            foreach ($qrTab as $line) {
180
                $arrAdd = [];
181
                foreach (str_split($line) as $char) {
182
                    $arrAdd[] = ($char == '1') ? 1 : 0;
183
                }
184
                $barcode_array['bcode'][] = $arrAdd;
185
            }
186
187
            return $barcode_array;
188
        }
189
190
        //----------------------------------------------------------------------
191
        public static function clearCache()
192
        {
193
            self::$frames = [];
0 ignored issues
show
Bug Best Practice introduced by
The property frames does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
194
        }
195
196
        //----------------------------------------------------------------------
197
        public static function buildCache()
198
        {
199
            self::markTime('before_build_cache');
200
201
            $mask = new QRmask();
202
            for ($a = 1; $a <= QRSPEC_VERSION_MAX; $a++) {
203
                $frame = QRspec::newFrame($a);
204
                if (QR_IMAGE) {
205
                    $fileName = QR_CACHE_DIR.'frame_'.$a.'.png';
206
                    QRimage::png(self::binarize($frame), $fileName, 1, 0);
0 ignored issues
show
The call to qrimage::png() has too few arguments starting with saveandprint. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

206
                    QRimage::/** @scrutinizer ignore-call */ 
207
                             png(self::binarize($frame), $fileName, 1, 0);

This check compares calls to functions or methods with their respective definitions. If the call has less 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.

Loading history...
207
                }
208
209
                $width = count($frame);
210
                $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
211
                for ($maskNo = 0; $maskNo < 8; $maskNo++) {
212
                    $mask->makeMaskNo($maskNo, $width, $frame, $bitMask, true);
213
                }
214
            }
215
216
            self::markTime('after_build_cache');
217
        }
218
219
        //----------------------------------------------------------------------
220
        public static function log($outfile, $err)
221
        {
222
            if (QR_LOG_DIR !== false) {
223
                if ($err != '') {
224
                    if ($outfile !== false) {
225
                        file_put_contents(QR_LOG_DIR.basename($outfile).'-errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
226
                    } else {
227
                        file_put_contents(QR_LOG_DIR.'errors.txt', date('Y-m-d H:i:s').': '.$err, FILE_APPEND);
228
                    }
229
                }
230
            }
231
        }
232
233
        //----------------------------------------------------------------------
234
        public static function dumpMask($frame)
235
        {
236
            $width = count($frame);
237
            for ($y = 0; $y < $width; $y++) {
238
                for ($x = 0; $x < $width; $x++) {
239
                    echo ord($frame[$y][$x]).',';
240
                }
241
            }
242
        }
243
244
        //----------------------------------------------------------------------
245
        public static function markTime($markerId)
246
        {
247
            list($usec, $sec) = explode(' ', microtime());
248
            $time = ((float) $usec + (float) $sec);
249
250
            if (!isset($GLOBALS['qr_time_bench'])) {
251
                $GLOBALS['qr_time_bench'] = [];
252
            }
253
254
            $GLOBALS['qr_time_bench'][$markerId] = $time;
255
        }
256
257
        //----------------------------------------------------------------------
258
        public static function timeBenchmark()
259
        {
260
            self::markTime('finish');
261
262
            $lastTime = 0;
263
            $startTime = 0;
264
            $p = 0;
265
266
            echo '<table cellpadding="3" cellspacing="1">
267
                    <thead><tr style="border-bottom:1px solid silver"><td colspan="2" style="text-align:center">BENCHMARK</td></tr></thead>
268
                    <tbody>';
269
270
            foreach ($GLOBALS['qr_time_bench'] as $markerId=>$thisTime) {
271
                if ($p > 0) {
272
                    echo '<tr><th style="text-align:right">till '.$markerId.': </th><td>'.number_format($thisTime - $lastTime, 6).'s</td></tr>';
273
                } else {
274
                    $startTime = $thisTime;
275
                }
276
277
                $p++;
278
                $lastTime = $thisTime;
279
            }
280
281
            echo '</tbody><tfoot>
282
                <tr style="border-top:2px solid black"><th style="text-align:right">TOTAL: </th><td>'.number_format($lastTime - $startTime, 6).'s</td></tr>
283
            </tfoot>
284
            </table>';
285
        }
286
287
        public static function save($content, $filename_path)
288
        {
289
            try {
290
                $handle = fopen($filename_path, 'w');
291
                fwrite($handle, $content);
0 ignored issues
show
It seems like $handle can also be of type false; however, parameter $handle of fwrite() does only seem to accept resource, 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 ignore-type  annotation

291
                fwrite(/** @scrutinizer ignore-type */ $handle, $content);
Loading history...
292
                fclose($handle);
0 ignored issues
show
It seems like $handle can also be of type false; however, parameter $handle of fclose() does only seem to accept resource, 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 ignore-type  annotation

292
                fclose(/** @scrutinizer ignore-type */ $handle);
Loading history...
293
294
                return true;
295
            } catch (Exception $e) {
296
                echo 'Exception reçue : ', $e->getMessage(), "\n";
297
            }
298
        }
299
    }
300
301
    //##########################################################################
302
303
    QRtools::markTime('start');
304
305
//---- qrspec.php -----------------------------
306
307
/*
308
 * PHP QR Code encoder
309
 *
310
 * QR Code specifications
311
 *
312
 * Based on libqrencode C library distributed under LGPL 2.1
313
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
314
 *
315
 * PHP QR Code is distributed under LGPL 3
316
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
317
 *
318
 * The following data / specifications are taken from
319
 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
320
 *  or
321
 * "Automatic identification and data capture techniques --
322
 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
323
 *
324
 * This library is free software; you can redistribute it and/or
325
 * modify it under the terms of the GNU Lesser General Public
326
 * License as published by the Free Software Foundation; either
327
 * version 3 of the License, or any later version.
328
 *
329
 * This library is distributed in the hope that it will be useful,
330
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
331
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
332
 * Lesser General Public License for more details.
333
 *
334
 * You should have received a copy of the GNU Lesser General Public
335
 * License along with this library; if not, write to the Free Software
336
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
337
 */
338
339
    define('QRSPEC_VERSION_MAX', 40);
340
    define('QRSPEC_WIDTH_MAX', 177);
341
342
    define('QRCAP_WIDTH', 0);
343
    define('QRCAP_WORDS', 1);
344
    define('QRCAP_REMINDER', 2);
345
    define('QRCAP_EC', 3);
346
347
    class QRspec
348
    {
349
        public static $capacity = [
350
            [0, 0, 0, [0, 0, 0, 0]],
351
            [21, 26, 0, [7, 10, 13, 17]], // 1
352
            [25, 44, 7, [10, 16, 22, 28]],
353
            [29, 70, 7, [15, 26, 36, 44]],
354
            [33, 100, 7, [20, 36, 52, 64]],
355
            [37, 134, 7, [26, 48, 72, 88]], // 5
356
            [41, 172, 7, [36, 64, 96, 112]],
357
            [45, 196, 0, [40, 72, 108, 130]],
358
            [49, 242, 0, [48, 88, 132, 156]],
359
            [53, 292, 0, [60, 110, 160, 192]],
360
            [57, 346, 0, [72, 130, 192, 224]], //10
361
            [61, 404, 0, [80, 150, 224, 264]],
362
            [65, 466, 0, [96, 176, 260, 308]],
363
            [69, 532, 0, [104, 198, 288, 352]],
364
            [73, 581, 3, [120, 216, 320, 384]],
365
            [77, 655, 3, [132, 240, 360, 432]], //15
366
            [81, 733, 3, [144, 280, 408, 480]],
367
            [85, 815, 3, [168, 308, 448, 532]],
368
            [89, 901, 3, [180, 338, 504, 588]],
369
            [93, 991, 3, [196, 364, 546, 650]],
370
            [97, 1085, 3, [224, 416, 600, 700]], //20
371
            [101, 1156, 4, [224, 442, 644, 750]],
372
            [105, 1258, 4, [252, 476, 690, 816]],
373
            [109, 1364, 4, [270, 504, 750, 900]],
374
            [113, 1474, 4, [300, 560, 810, 960]],
375
            [117, 1588, 4, [312, 588, 870, 1050]], //25
376
            [121, 1706, 4, [336, 644, 952, 1110]],
377
            [125, 1828, 4, [360, 700, 1020, 1200]],
378
            [129, 1921, 3, [390, 728, 1050, 1260]],
379
            [133, 2051, 3, [420, 784, 1140, 1350]],
380
            [137, 2185, 3, [450, 812, 1200, 1440]], //30
381
            [141, 2323, 3, [480, 868, 1290, 1530]],
382
            [145, 2465, 3, [510, 924, 1350, 1620]],
383
            [149, 2611, 3, [540, 980, 1440, 1710]],
384
            [153, 2761, 3, [570, 1036, 1530, 1800]],
385
            [157, 2876, 0, [570, 1064, 1590, 1890]], //35
386
            [161, 3034, 0, [600, 1120, 1680, 1980]],
387
            [165, 3196, 0, [630, 1204, 1770, 2100]],
388
            [169, 3362, 0, [660, 1260, 1860, 2220]],
389
            [173, 3532, 0, [720, 1316, 1950, 2310]],
390
            [177, 3706, 0, [750, 1372, 2040, 2430]], //40
391
        ];
392
393
        //----------------------------------------------------------------------
394
        public static function getDataLength($version, $level)
395
        {
396
            return self::$capacity[$version][QRCAP_WORDS] - self::$capacity[$version][QRCAP_EC][$level];
397
        }
398
399
        //----------------------------------------------------------------------
400
        public static function getECCLength($version, $level)
401
        {
402
            return self::$capacity[$version][QRCAP_EC][$level];
403
        }
404
405
        //----------------------------------------------------------------------
406
        public static function getWidth($version)
407
        {
408
            return self::$capacity[$version][QRCAP_WIDTH];
409
        }
410
411
        //----------------------------------------------------------------------
412
        public static function getRemainder($version)
413
        {
414
            return self::$capacity[$version][QRCAP_REMINDER];
415
        }
416
417
        //----------------------------------------------------------------------
418
        public static function getMinimumVersion($size, $level)
419
        {
420
            for ($i = 1; $i <= QRSPEC_VERSION_MAX; $i++) {
421
                $words = self::$capacity[$i][QRCAP_WORDS] - self::$capacity[$i][QRCAP_EC][$level];
422
                if ($words >= $size) {
423
                    return $i;
424
                }
425
            }
426
427
            return 0;
428
        }
429
430
        //######################################################################
431
432
        public static $lengthTableBits = [
433
            [10, 12, 14],
434
            [9, 11, 13],
435
            [8, 16, 16],
436
            [8, 10, 12],
437
        ];
438
439
        //----------------------------------------------------------------------
440
        public static function lengthIndicator($mode, $version)
441
        {
442
            if ($mode == QR_MODE_STRUCTURE) {
443
                return 0;
444
            }
445
446
            if ($version <= 9) {
447
                $l = 0;
448
            } elseif ($version <= 26) {
449
                $l = 1;
450
            } else {
451
                $l = 2;
452
            }
453
454
            return self::$lengthTableBits[$mode][$l];
455
        }
456
457
        //----------------------------------------------------------------------
458
        public static function maximumWords($mode, $version)
459
        {
460
            if ($mode == QR_MODE_STRUCTURE) {
461
                return 3;
462
            }
463
464
            if ($version <= 9) {
465
                $l = 0;
466
            } elseif ($version <= 26) {
467
                $l = 1;
468
            } else {
469
                $l = 2;
470
            }
471
472
            $bits = self::$lengthTableBits[$mode][$l];
473
            $words = (1 << $bits) - 1;
474
475
            if ($mode == QR_MODE_KANJI) {
476
                $words *= 2; // the number of bytes is required
477
            }
478
479
            return $words;
480
        }
481
482
        // Error correction code -----------------------------------------------
483
        // Table of the error correction code (Reed-Solomon block)
484
        // See Table 12-16 (pp.30-36), JIS X0510:2004.
485
486
        public static $eccTable = [
487
            [[0, 0], [0, 0], [0, 0], [0, 0]],
488
            [[1, 0], [1, 0], [1, 0], [1, 0]], // 1
489
            [[1, 0], [1, 0], [1, 0], [1, 0]],
490
            [[1, 0], [1, 0], [2, 0], [2, 0]],
491
            [[1, 0], [2, 0], [2, 0], [4, 0]],
492
            [[1, 0], [2, 0], [2, 2], [2, 2]], // 5
493
            [[2, 0], [4, 0], [4, 0], [4, 0]],
494
            [[2, 0], [4, 0], [2, 4], [4, 1]],
495
            [[2, 0], [2, 2], [4, 2], [4, 2]],
496
            [[2, 0], [3, 2], [4, 4], [4, 4]],
497
            [[2, 2], [4, 1], [6, 2], [6, 2]], //10
498
            [[4, 0], [1, 4], [4, 4], [3, 8]],
499
            [[2, 2], [6, 2], [4, 6], [7, 4]],
500
            [[4, 0], [8, 1], [8, 4], [12, 4]],
501
            [[3, 1], [4, 5], [11, 5], [11, 5]],
502
            [[5, 1], [5, 5], [5, 7], [11, 7]], //15
503
            [[5, 1], [7, 3], [15, 2], [3, 13]],
504
            [[1, 5], [10, 1], [1, 15], [2, 17]],
505
            [[5, 1], [9, 4], [17, 1], [2, 19]],
506
            [[3, 4], [3, 11], [17, 4], [9, 16]],
507
            [[3, 5], [3, 13], [15, 5], [15, 10]], //20
508
            [[4, 4], [17, 0], [17, 6], [19, 6]],
509
            [[2, 7], [17, 0], [7, 16], [34, 0]],
510
            [[4, 5], [4, 14], [11, 14], [16, 14]],
511
            [[6, 4], [6, 14], [11, 16], [30, 2]],
512
            [[8, 4], [8, 13], [7, 22], [22, 13]], //25
513
            [[10, 2], [19, 4], [28, 6], [33, 4]],
514
            [[8, 4], [22, 3], [8, 26], [12, 28]],
515
            [[3, 10], [3, 23], [4, 31], [11, 31]],
516
            [[7, 7], [21, 7], [1, 37], [19, 26]],
517
            [[5, 10], [19, 10], [15, 25], [23, 25]], //30
518
            [[13, 3], [2, 29], [42, 1], [23, 28]],
519
            [[17, 0], [10, 23], [10, 35], [19, 35]],
520
            [[17, 1], [14, 21], [29, 19], [11, 46]],
521
            [[13, 6], [14, 23], [44, 7], [59, 1]],
522
            [[12, 7], [12, 26], [39, 14], [22, 41]], //35
523
            [[6, 14], [6, 34], [46, 10], [2, 64]],
524
            [[17, 4], [29, 14], [49, 10], [24, 46]],
525
            [[4, 18], [13, 32], [48, 14], [42, 32]],
526
            [[20, 4], [40, 7], [43, 22], [10, 67]],
527
            [[19, 6], [18, 31], [34, 34], [20, 61]], //40
528
        ];
529
530
        //----------------------------------------------------------------------
531
        // CACHEABLE!!!
532
533
        public static function getEccSpec($version, $level, array &$spec)
534
        {
535
            if (count($spec) < 5) {
536
                $spec = [0, 0, 0, 0, 0];
537
            }
538
539
            $b1 = self::$eccTable[$version][$level][0];
540
            $b2 = self::$eccTable[$version][$level][1];
541
            $data = self::getDataLength($version, $level);
542
            $ecc = self::getECCLength($version, $level);
543
544
            if ($b2 == 0) {
545
                $spec[0] = $b1;
546
                $spec[1] = (int) ($data / $b1);
547
                $spec[2] = (int) ($ecc / $b1);
548
                $spec[3] = 0;
549
                $spec[4] = 0;
550
            } else {
551
                $spec[0] = $b1;
552
                $spec[1] = (int) ($data / ($b1 + $b2));
553
                $spec[2] = (int) ($ecc / ($b1 + $b2));
554
                $spec[3] = $b2;
555
                $spec[4] = $spec[1] + 1;
556
            }
557
        }
558
559
        // Alignment pattern ---------------------------------------------------
560
561
        // Positions of alignment patterns.
562
        // This array includes only the second and the third position of the
563
        // alignment patterns. Rest of them can be calculated from the distance
564
        // between them.
565
566
        // See Table 1 in Appendix E (pp.71) of JIS X0510:2004.
567
568
        public static $alignmentPattern = [
569
            [0, 0],
570
            [0, 0], [18, 0], [22, 0], [26, 0], [30, 0], // 1- 5
571
            [34, 0], [22, 38], [24, 42], [26, 46], [28, 50], // 6-10
572
            [30, 54], [32, 58], [34, 62], [26, 46], [26, 48], //11-15
573
            [26, 50], [30, 54], [30, 56], [30, 58], [34, 62], //16-20
574
            [28, 50], [26, 50], [30, 54], [28, 54], [32, 58], //21-25
575
            [30, 58], [34, 62], [26, 50], [30, 54], [26, 52], //26-30
576
            [30, 56], [34, 60], [30, 58], [34, 62], [30, 54], //31-35
577
            [24, 50], [28, 54], [32, 58], [26, 54], [30, 58], //35-40
578
        ];
579
580
        /** --------------------------------------------------------------------
581
         * Put an alignment marker.
582
         *
583
         * @param frame
584
         * @param width
585
         * @param ox,oy  center coordinate of the pattern
0 ignored issues
show
The type center was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
586
         */
587
        public static function putAlignmentMarker(array &$frame, $ox, $oy)
588
        {
589
            $finder = [
590
                "\xa1\xa1\xa1\xa1\xa1",
591
                "\xa1\xa0\xa0\xa0\xa1",
592
                "\xa1\xa0\xa1\xa0\xa1",
593
                "\xa1\xa0\xa0\xa0\xa1",
594
                "\xa1\xa1\xa1\xa1\xa1",
595
            ];
596
597
            $yStart = $oy - 2;
598
            $xStart = $ox - 2;
599
600
            for ($y = 0; $y < 5; $y++) {
601
                QRstr::set($frame, $xStart, $yStart + $y, $finder[$y]);
602
            }
603
        }
604
605
        //----------------------------------------------------------------------
606
        public static function putAlignmentPattern($version, &$frame, $width)
607
        {
608
            if ($version < 2) {
609
                return;
610
            }
611
612
            $d = self::$alignmentPattern[$version][1] - self::$alignmentPattern[$version][0];
613
            if ($d < 0) {
614
                $w = 2;
615
            } else {
616
                $w = (int) (($width - self::$alignmentPattern[$version][0]) / $d + 2);
617
            }
618
619
            if ($w * $w - 3 == 1) {
620
                $x = self::$alignmentPattern[$version][0];
621
                $y = self::$alignmentPattern[$version][0];
622
                self::putAlignmentMarker($frame, $x, $y);
623
624
                return;
625
            }
626
627
            $cx = self::$alignmentPattern[$version][0];
628
            for ($x = 1; $x < $w - 1; $x++) {
629
                self::putAlignmentMarker($frame, 6, $cx);
630
                self::putAlignmentMarker($frame, $cx, 6);
631
                $cx += $d;
632
            }
633
634
            $cy = self::$alignmentPattern[$version][0];
635
            for ($y = 0; $y < $w - 1; $y++) {
636
                $cx = self::$alignmentPattern[$version][0];
637
                for ($x = 0; $x < $w - 1; $x++) {
638
                    self::putAlignmentMarker($frame, $cx, $cy);
639
                    $cx += $d;
640
                }
641
                $cy += $d;
642
            }
643
        }
644
645
        // Version information pattern -----------------------------------------
646
647
        // Version information pattern (BCH coded).
648
        // See Table 1 in Appendix D (pp.68) of JIS X0510:2004.
649
650
        // size: [QRSPEC_VERSION_MAX - 6]
651
652
        public static $versionPattern = [
653
            0x07c94, 0x085bc, 0x09a99, 0x0a4d3, 0x0bbf6, 0x0c762, 0x0d847, 0x0e60d,
654
            0x0f928, 0x10b78, 0x1145d, 0x12a17, 0x13532, 0x149a6, 0x15683, 0x168c9,
655
            0x177ec, 0x18ec4, 0x191e1, 0x1afab, 0x1b08e, 0x1cc1a, 0x1d33f, 0x1ed75,
656
            0x1f250, 0x209d5, 0x216f0, 0x228ba, 0x2379f, 0x24b0b, 0x2542e, 0x26a64,
657
            0x27541, 0x28c69,
658
        ];
659
660
        //----------------------------------------------------------------------
661
        public static function getVersionPattern($version)
662
        {
663
            if ($version < 7 || $version > QRSPEC_VERSION_MAX) {
664
                return 0;
665
            }
666
667
            return self::$versionPattern[$version - 7];
668
        }
669
670
        // Format information --------------------------------------------------
671
        // See calcFormatInfo in tests/test_qrspec.c (orginal qrencode c lib)
672
673
        public static $formatInfo = [
674
            [0x77c4, 0x72f3, 0x7daa, 0x789d, 0x662f, 0x6318, 0x6c41, 0x6976],
675
            [0x5412, 0x5125, 0x5e7c, 0x5b4b, 0x45f9, 0x40ce, 0x4f97, 0x4aa0],
676
            [0x355f, 0x3068, 0x3f31, 0x3a06, 0x24b4, 0x2183, 0x2eda, 0x2bed],
677
            [0x1689, 0x13be, 0x1ce7, 0x19d0, 0x0762, 0x0255, 0x0d0c, 0x083b],
678
        ];
679
680
        public static function getFormatInfo($mask, $level)
681
        {
682
            if ($mask < 0 || $mask > 7) {
683
                return 0;
684
            }
685
686
            if ($level < 0 || $level > 3) {
687
                return 0;
688
            }
689
690
            return self::$formatInfo[$level][$mask];
691
        }
692
693
        // Frame ---------------------------------------------------------------
694
        // Cache of initial frames.
695
696
        public static $frames = [];
697
698
        /** --------------------------------------------------------------------
699
         * Put a finder pattern.
700
         *
701
         * @param frame
702
         * @param width
703
         * @param ox,oy  upper-left coordinate of the pattern
0 ignored issues
show
Documentation Bug introduced by
The doc comment upper-left at position 0 could not be parsed: Unknown type name 'upper-left' at position 0 in upper-left.
Loading history...
704
         */
705
        public static function putFinderPattern(&$frame, $ox, $oy)
706
        {
707
            $finder = [
708
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
709
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
710
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
711
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
712
                "\xc1\xc0\xc1\xc1\xc1\xc0\xc1",
713
                "\xc1\xc0\xc0\xc0\xc0\xc0\xc1",
714
                "\xc1\xc1\xc1\xc1\xc1\xc1\xc1",
715
            ];
716
717
            for ($y = 0; $y < 7; $y++) {
718
                QRstr::set($frame, $ox, $oy + $y, $finder[$y]);
719
            }
720
        }
721
722
        //----------------------------------------------------------------------
723
        public static function createFrame($version)
724
        {
725
            $width = self::$capacity[$version][QRCAP_WIDTH];
726
            $frameLine = str_repeat("\0", $width);
727
            $frame = array_fill(0, $width, $frameLine);
728
729
            // Finder pattern
730
            self::putFinderPattern($frame, 0, 0);
731
            self::putFinderPattern($frame, $width - 7, 0);
732
            self::putFinderPattern($frame, 0, $width - 7);
733
734
            // Separator
735
            $yOffset = $width - 7;
736
737
            for ($y = 0; $y < 7; $y++) {
738
                $frame[$y][7] = "\xc0";
739
                $frame[$y][$width - 8] = "\xc0";
740
                $frame[$yOffset][7] = "\xc0";
741
                $yOffset++;
742
            }
743
744
            $setPattern = str_repeat("\xc0", 8);
745
746
            QRstr::set($frame, 0, 7, $setPattern);
747
            QRstr::set($frame, $width - 8, 7, $setPattern);
748
            QRstr::set($frame, 0, $width - 8, $setPattern);
749
750
            // Format info
751
            $setPattern = str_repeat("\x84", 9);
752
            QRstr::set($frame, 0, 8, $setPattern);
753
            QRstr::set($frame, $width - 8, 8, $setPattern, 8);
754
755
            $yOffset = $width - 8;
756
757
            for ($y = 0; $y < 8; $y++, $yOffset++) {
758
                $frame[$y][8] = "\x84";
759
                $frame[$yOffset][8] = "\x84";
760
            }
761
762
            // Timing pattern
763
764
            for ($i = 1; $i < $width - 15; $i++) {
765
                $frame[6][7 + $i] = chr(0x90 | ($i & 1));
766
                $frame[7 + $i][6] = chr(0x90 | ($i & 1));
767
            }
768
769
            // Alignment pattern
770
            self::putAlignmentPattern($version, $frame, $width);
771
772
            // Version information
773
            if ($version >= 7) {
774
                $vinf = self::getVersionPattern($version);
775
776
                $v = $vinf;
777
778
                for ($x = 0; $x < 6; $x++) {
779
                    for ($y = 0; $y < 3; $y++) {
780
                        $frame[($width - 11) + $y][$x] = chr(0x88 | ($v & 1));
781
                        $v = $v >> 1;
782
                    }
783
                }
784
785
                $v = $vinf;
786
                for ($y = 0; $y < 6; $y++) {
787
                    for ($x = 0; $x < 3; $x++) {
788
                        $frame[$y][$x + ($width - 11)] = chr(0x88 | ($v & 1));
789
                        $v = $v >> 1;
790
                    }
791
                }
792
            }
793
794
            // and a little bit...
795
            $frame[$width - 8][8] = "\x81";
796
797
            return $frame;
798
        }
799
800
        //----------------------------------------------------------------------
801
        public static function debug($frame, $binary_mode = false)
802
        {
803
            if ($binary_mode) {
804
                foreach ($frame as &$frameLine) {
805
                    $frameLine = implode('<span class="m">&nbsp;&nbsp;</span>', explode('0', $frameLine));
806
                    $frameLine = implode('&#9608;&#9608;', explode('1', $frameLine));
807
                } ?>
808
                <style>
809
                    .m { background-color: white; }
810
                </style>
811
                <?php
812
                    echo '<pre><tt><br/ ><br/ ><br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
813
                echo implode('<br/ >&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;', $frame);
814
                echo '</tt></pre><br/ ><br/ ><br/ ><br/ ><br/ ><br/ >';
815
            } else {
816
                foreach ($frame as &$frameLine) {
817
                    $frameLine = implode('<span class="m">&nbsp;</span>', explode("\xc0", $frameLine));
818
                    $frameLine = implode('<span class="m">&#9618;</span>', explode("\xc1", $frameLine));
819
                    $frameLine = implode('<span class="p">&nbsp;</span>', explode("\xa0", $frameLine));
820
                    $frameLine = implode('<span class="p">&#9618;</span>', explode("\xa1", $frameLine));
821
                    $frameLine = implode('<span class="s">&#9671;</span>', explode("\x84", $frameLine)); //format 0
822
                    $frameLine = implode('<span class="s">&#9670;</span>', explode("\x85", $frameLine)); //format 1
823
                    $frameLine = implode('<span class="x">&#9762;</span>', explode("\x81", $frameLine)); //special bit
824
                    $frameLine = implode('<span class="c">&nbsp;</span>', explode("\x90", $frameLine)); //clock 0
825
                    $frameLine = implode('<span class="c">&#9719;</span>', explode("\x91", $frameLine)); //clock 1
826
                    $frameLine = implode('<span class="f">&nbsp;</span>', explode("\x88", $frameLine)); //version
827
                    $frameLine = implode('<span class="f">&#9618;</span>', explode("\x89", $frameLine)); //version
828
                    $frameLine = implode('&#9830;', explode("\x01", $frameLine));
829
                    $frameLine = implode('&#8901;', explode("\0", $frameLine));
830
                } ?>
831
                <style>
832
                    .p { background-color: yellow; }
833
                    .m { background-color: #00FF00; }
834
                    .s { background-color: #FF0000; }
835
                    .c { background-color: aqua; }
836
                    .x { background-color: pink; }
837
                    .f { background-color: gold; }
838
                </style>
839
                <?php
840
                echo '<pre><tt>';
841
                echo implode('<br/ >', $frame);
842
                echo '</tt></pre>';
843
            }
844
        }
845
846
        //----------------------------------------------------------------------
847
        public static function serial($frame)
848
        {
849
            return gzcompress(implode("\n", $frame), 9);
850
        }
851
852
        //----------------------------------------------------------------------
853
        public static function unserial($code)
854
        {
855
            return explode("\n", gzuncompress($code));
856
        }
857
858
        //----------------------------------------------------------------------
859
        public static function newFrame($version)
860
        {
861
            if ($version < 1 || $version > QRSPEC_VERSION_MAX) {
862
                return;
863
            }
864
865
            if (!isset(self::$frames[$version])) {
866
                $fileName = QR_CACHE_DIR.'frame_'.$version.'.dat';
867
868
                if (QR_CACHEABLE) {
869
                    if (file_exists($fileName)) {
870
                        self::$frames[$version] = self::unserial(file_get_contents($fileName));
871
                    } else {
872
                        self::$frames[$version] = self::createFrame($version);
873
                        file_put_contents($fileName, self::serial(self::$frames[$version]));
874
                    }
875
                } else {
876
                    self::$frames[$version] = self::createFrame($version);
877
                }
878
            }
879
880
            if (is_null(self::$frames[$version])) {
881
                return;
882
            }
883
884
            return self::$frames[$version];
885
        }
886
887
        //----------------------------------------------------------------------
888
        public static function rsBlockNum($spec)
889
        {
890
            return $spec[0] + $spec[3];
891
        }
892
893
        public static function rsBlockNum1($spec)
894
        {
895
            return $spec[0];
896
        }
897
898
        public static function rsDataCodes1($spec)
899
        {
900
            return $spec[1];
901
        }
902
903
        public static function rsEccCodes1($spec)
904
        {
905
            return $spec[2];
906
        }
907
908
        public static function rsBlockNum2($spec)
909
        {
910
            return $spec[3];
911
        }
912
913
        public static function rsDataCodes2($spec)
914
        {
915
            return $spec[4];
916
        }
917
918
        public static function rsEccCodes2($spec)
919
        {
920
            return $spec[2];
921
        }
922
923
        public static function rsDataLength($spec)
924
        {
925
            return ($spec[0] * $spec[1]) + ($spec[3] * $spec[4]);
926
        }
927
928
        public static function rsEccLength($spec)
929
        {
930
            return ($spec[0] + $spec[3]) * $spec[2];
931
        }
932
    }
933
934
//---- qrimage.php -----------------------------
935
936
/*
937
 * PHP QR Code encoder
938
 *
939
 * Image output of code using GD2
940
 *
941
 * PHP QR Code is distributed under LGPL 3
942
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
943
 *
944
 * This library is free software; you can redistribute it and/or
945
 * modify it under the terms of the GNU Lesser General Public
946
 * License as published by the Free Software Foundation; either
947
 * version 3 of the License, or any later version.
948
 *
949
 * This library is distributed in the hope that it will be useful,
950
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
951
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
952
 * Lesser General Public License for more details.
953
 *
954
 * You should have received a copy of the GNU Lesser General Public
955
 * License along with this library; if not, write to the Free Software
956
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
957
 */
958
959
    define('QR_IMAGE', true);
960
961
    class QRimage
962
    {
963
        //----------------------------------------------------------------------
964
        public static function png($frame, $filename, $pixelPerPoint, $outerFrame, $saveandprint, $back_color, $fore_color)
965
        {
966
            $image = self::image($frame, $pixelPerPoint, $outerFrame, $back_color, $fore_color);
967
968
            if ($filename === false) {
969
                header('Content-type: image/png');
970
                imagepng($image);
971
            } else {
972
                if ($saveandprint === true) {
973
                    imagepng($image, $filename);
974
                    header('Content-type: image/png');
975
                    imagepng($image);
976
                } else {
977
                    imagepng($image, $filename);
978
                }
979
            }
980
981
            imagedestroy($image);
982
        }
983
984
        //----------------------------------------------------------------------
985
        public static function jpg($frame, $filename = false, $pixelPerPoint = 8, $outerFrame = 4, $q = 85)
986
        {
987
            $image = self::image($frame, $pixelPerPoint, $outerFrame);
988
989
            if ($filename === false) {
990
                header('Content-type: image/jpeg');
991
                imagejpeg($image, null, $q);
992
            } else {
993
                imagejpeg($image, $filename, $q);
994
            }
995
996
            imagedestroy($image);
997
        }
998
999
        //----------------------------------------------------------------------
1000
        private static function image($frame, $pixelPerPoint = 4, $outerFrame = 4, $back_color = 0xFFFFFF, $fore_color = 0x000000)
1001
        {
1002
            $h = count($frame);
1003
            $w = strlen($frame[0]);
1004
1005
            $imgW = $w + 2 * $outerFrame;
1006
            $imgH = $h + 2 * $outerFrame;
1007
1008
            $base_image = imagecreate($imgW, $imgH);
1009
1010
            // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
1011
            $r1 = round((($fore_color & 0xFF0000) >> 16), 5);
1012
            $b1 = round((($fore_color & 0x00FF00) >> 8), 5);
1013
            $g1 = round(($fore_color & 0x0000FF), 5);
1014
1015
            // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
1016
            $r2 = round((($back_color & 0xFF0000) >> 16), 5);
1017
            $b2 = round((($back_color & 0x00FF00) >> 8), 5);
1018
            $g2 = round(($back_color & 0x0000FF), 5);
1019
1020
            $col[0] = imagecolorallocate($base_image, $r2, $b2, $g2);
0 ignored issues
show
$r2 of type double is incompatible with the type integer expected by parameter $red of imagecolorallocate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1020
            $col[0] = imagecolorallocate($base_image, /** @scrutinizer ignore-type */ $r2, $b2, $g2);
Loading history...
Comprehensibility Best Practice introduced by
$col was never initialized. Although not strictly required by PHP, it is generally a good practice to add $col = array(); before regardless.
Loading history...
$g2 of type double is incompatible with the type integer expected by parameter $blue of imagecolorallocate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1020
            $col[0] = imagecolorallocate($base_image, $r2, $b2, /** @scrutinizer ignore-type */ $g2);
Loading history...
$b2 of type double is incompatible with the type integer expected by parameter $green of imagecolorallocate(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

1020
            $col[0] = imagecolorallocate($base_image, $r2, /** @scrutinizer ignore-type */ $b2, $g2);
Loading history...
1021
            $col[1] = imagecolorallocate($base_image, $r1, $b1, $g1);
1022
1023
            imagefill($base_image, 0, 0, $col[0]);
1024
1025
            for ($y = 0; $y < $h; $y++) {
1026
                for ($x = 0; $x < $w; $x++) {
1027
                    if ($frame[$y][$x] == '1') {
1028
                        imagesetpixel($base_image, $x + $outerFrame, $y + $outerFrame, $col[1]);
1029
                    }
1030
                }
1031
            }
1032
1033
            $target_image = imagecreate($imgW * $pixelPerPoint, $imgH * $pixelPerPoint);
1034
            imagecopyresized($target_image, $base_image, 0, 0, 0, 0, $imgW * $pixelPerPoint, $imgH * $pixelPerPoint, $imgW, $imgH);
1035
            imagedestroy($base_image);
1036
1037
            return $target_image;
1038
        }
1039
    }
1040
1041
//---- qrinput.php -----------------------------
1042
1043
/*
1044
 * PHP QR Code encoder
1045
 *
1046
 * Input encoding class
1047
 *
1048
 * Based on libqrencode C library distributed under LGPL 2.1
1049
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
1050
 *
1051
 * PHP QR Code is distributed under LGPL 3
1052
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1053
 *
1054
 * This library is free software; you can redistribute it and/or
1055
 * modify it under the terms of the GNU Lesser General Public
1056
 * License as published by the Free Software Foundation; either
1057
 * version 3 of the License, or any later version.
1058
 *
1059
 * This library is distributed in the hope that it will be useful,
1060
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1061
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1062
 * Lesser General Public License for more details.
1063
 *
1064
 * You should have received a copy of the GNU Lesser General Public
1065
 * License along with this library; if not, write to the Free Software
1066
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1067
 */
1068
1069
    define('STRUCTURE_HEADER_BITS', 20);
1070
    define('MAX_STRUCTURED_SYMBOLS', 16);
1071
1072
    class QRinputItem
1073
    {
1074
        public $mode;
1075
        public $size;
1076
        public $data;
1077
        public $bstream;
1078
1079
        public function __construct($mode, $size, $data, $bstream = null)
1080
        {
1081
            $setData = array_slice($data, 0, $size);
1082
1083
            if (count($setData) < $size) {
1084
                $setData = array_merge($setData, array_fill(0, $size - count($setData), 0));
1085
            }
1086
1087
            if (!QRinput::check($mode, $size, $setData)) {
1088
                throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.implode(',', $setData));
1089
                return;
0 ignored issues
show
return 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1090
            }
1091
1092
            $this->mode = $mode;
1093
            $this->size = $size;
1094
            $this->data = $setData;
1095
            $this->bstream = $bstream;
1096
        }
1097
1098
        //----------------------------------------------------------------------
1099
        public function encodeModeNum($version)
1100
        {
1101
            try {
1102
                $words = (int) ($this->size / 3);
1103
                $bs = new QRbitstream();
1104
1105
                $val = 0x1;
1106
                $bs->appendNum(4, $val);
1107
                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);
1108
1109
                for ($i = 0; $i < $words; $i++) {
1110
                    $val = (ord($this->data[$i * 3]) - ord('0')) * 100;
1111
                    $val += (ord($this->data[$i * 3 + 1]) - ord('0')) * 10;
1112
                    $val += (ord($this->data[$i * 3 + 2]) - ord('0'));
1113
                    $bs->appendNum(10, $val);
1114
                }
1115
1116
                if ($this->size - $words * 3 == 1) {
1117
                    $val = ord($this->data[$words * 3]) - ord('0');
1118
                    $bs->appendNum(4, $val);
1119
                } elseif ($this->size - $words * 3 == 2) {
1120
                    $val = (ord($this->data[$words * 3]) - ord('0')) * 10;
1121
                    $val += (ord($this->data[$words * 3 + 1]) - ord('0'));
1122
                    $bs->appendNum(7, $val);
1123
                }
1124
1125
                $this->bstream = $bs;
1126
1127
                return 0;
1128
            } catch (Exception $e) {
1129
                return 0;
1130
            }
1131
        }
1132
1133
        //----------------------------------------------------------------------
1134
        public function encodeModeAn($version)
1135
        {
1136
            try {
1137
                $words = (int) ($this->size / 2);
1138
                $bs = new QRbitstream();
1139
1140
                $bs->appendNum(4, 0x02);
1141
                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);
1142
1143
                for ($i = 0; $i < $words; $i++) {
1144
                    $val = (int) QRinput::lookAnTable(ord($this->data[$i * 2])) * 45;
1145
                    $val += (int) QRinput::lookAnTable(ord($this->data[$i * 2 + 1]));
1146
1147
                    $bs->appendNum(11, $val);
1148
                }
1149
1150
                if ($this->size & 1) {
1151
                    $val = QRinput::lookAnTable(ord($this->data[$words * 2]));
1152
                    $bs->appendNum(6, $val);
1153
                }
1154
1155
                $this->bstream = $bs;
1156
1157
                return 0;
1158
            } catch (Exception $e) {
1159
                return 0;
1160
            }
1161
        }
1162
1163
        //----------------------------------------------------------------------
1164
        public function encodeMode8($version)
1165
        {
1166
            try {
1167
                $bs = new QRbitstream();
1168
1169
                $bs->appendNum(4, 0x4);
1170
                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);
1171
1172
                for ($i = 0; $i < $this->size; $i++) {
1173
                    $bs->appendNum(8, ord($this->data[$i]));
1174
                }
1175
1176
                $this->bstream = $bs;
1177
1178
                return 0;
1179
            } catch (Exception $e) {
1180
                return 0;
1181
            }
1182
        }
1183
1184
        //----------------------------------------------------------------------
1185
        public function encodeModeKanji($version)
1186
        {
1187
            try {
1188
                $bs = new QRbitrtream();
0 ignored issues
show
The type QRbitrtream was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
1189
1190
                $bs->appendNum(4, 0x8);
1191
                $bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int) ($this->size / 2));
1192
1193
                for ($i = 0; $i < $this->size; $i += 2) {
1194
                    $val = (ord($this->data[$i]) << 8) | ord($this->data[$i + 1]);
1195
                    if ($val <= 0x9ffc) {
1196
                        $val -= 0x8140;
1197
                    } else {
1198
                        $val -= 0xc140;
1199
                    }
1200
1201
                    $h = ($val >> 8) * 0xc0;
1202
                    $val = ($val & 0xff) + $h;
1203
1204
                    $bs->appendNum(13, $val);
1205
                }
1206
1207
                $this->bstream = $bs;
1208
1209
                return 0;
1210
            } catch (Exception $e) {
1211
                return 0;
1212
            }
1213
        }
1214
1215
        //----------------------------------------------------------------------
1216
        public function encodeModeStructure()
1217
        {
1218
            try {
1219
                $bs = new QRbitstream();
1220
1221
                $bs->appendNum(4, 0x03);
1222
                $bs->appendNum(4, ord($this->data[1]) - 1);
1223
                $bs->appendNum(4, ord($this->data[0]) - 1);
1224
                $bs->appendNum(8, ord($this->data[2]));
1225
1226
                $this->bstream = $bs;
1227
1228
                return 0;
1229
            } catch (Exception $e) {
1230
                return 0;
1231
            }
1232
        }
1233
1234
        //----------------------------------------------------------------------
1235
        public function estimateBitStreamSizeOfEntry($version)
1236
        {
1237
            $bits = 0;
1238
1239
            if ($version == 0) {
1240
                $version = 1;
1241
            }
1242
1243
            switch ($this->mode) {
1244
                case QR_MODE_NUM:        $bits = QRinput::estimateBitsModeNum($this->size); break;
1245
                case QR_MODE_AN:        $bits = QRinput::estimateBitsModeAn($this->size); break;
1246
                case QR_MODE_8:            $bits = QRinput::estimateBitsMode8($this->size); break;
1247
                case QR_MODE_KANJI:        $bits = QRinput::estimateBitsModeKanji($this->size); break;
0 ignored issues
show
Bug Best Practice introduced by
The method QRinput::estimateBitsModeKanji() is not static, but was called statically. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

1247
                case QR_MODE_KANJI:        /** @scrutinizer ignore-call */ $bits = QRinput::estimateBitsModeKanji($this->size); break;
Loading history...
1248
                case QR_MODE_STRUCTURE:    return STRUCTURE_HEADER_BITS;
1249
                default:
1250
                    return 0;
1251
            }
1252
1253
            $l = QRspec::lengthIndicator($this->mode, $version);
1254
            $m = 1 << $l;
1255
            $num = (int) (($this->size + $m - 1) / $m);
1256
1257
            $bits += $num * (4 + $l);
1258
1259
            return $bits;
1260
        }
1261
1262
        //----------------------------------------------------------------------
1263
        public function encodeBitStream($version)
1264
        {
1265
            try {
1266
                unset($this->bstream);
1267
                $words = QRspec::maximumWords($this->mode, $version);
1268
1269
                if ($this->size > $words) {
1270
                    $st1 = new self($this->mode, $words, $this->data);
1271
                    $st2 = new self($this->mode, $this->size - $words, array_slice($this->data, $words));
1272
1273
                    $st1->encodeBitStream($version);
1274
                    $st2->encodeBitStream($version);
1275
1276
                    $this->bstream = new QRbitstream();
1277
                    $this->bstream->append($st1->bstream);
1278
                    $this->bstream->append($st2->bstream);
1279
1280
                    unset($st1);
1281
                    unset($st2);
1282
                } else {
1283
                    $ret = 0;
1284
1285
                    switch ($this->mode) {
1286
                        case QR_MODE_NUM:        $ret = $this->encodeModeNum($version); break;
1287
                        case QR_MODE_AN:        $ret = $this->encodeModeAn($version); break;
1288
                        case QR_MODE_8:            $ret = $this->encodeMode8($version); break;
1289
                        case QR_MODE_KANJI:        $ret = $this->encodeModeKanji($version); break;
1290
                        case QR_MODE_STRUCTURE:    $ret = $this->encodeModeStructure(); break;
1291
1292
                        default:
1293
                            break;
1294
                    }
1295
1296
                    if ($ret < 0) {
1297
                        return 0;
1298
                    }
1299
                }
1300
1301
                return $this->bstream->size();
1302
            } catch (Exception $e) {
1303
                return 0;
1304
            }
1305
        }
1306
    }
1307
1308
    //##########################################################################
1309
1310
    class QRinput
1311
    {
1312
        public $items;
1313
1314
        private $version;
1315
        private $level;
1316
1317
        //----------------------------------------------------------------------
1318
        public function __construct($version = 0, $level = QR_ECLEVEL_L)
1319
        {
1320
            if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
1321
                throw new Exception('Invalid version no');
1322
                return false;
0 ignored issues
show
return false 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1323
            }
1324
1325
            $this->version = $version;
1326
            $this->level = $level;
1327
        }
1328
1329
        //----------------------------------------------------------------------
1330
        public function getVersion()
1331
        {
1332
            return $this->version;
1333
        }
1334
1335
        //----------------------------------------------------------------------
1336
        public function setVersion($version)
1337
        {
1338
            if ($version < 0 || $version > QRSPEC_VERSION_MAX) {
1339
                throw new Exception('Invalid version no');
1340
                return 0;
0 ignored issues
show
return 0 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1341
            }
1342
1343
            $this->version = $version;
1344
1345
            return 0;
1346
        }
1347
1348
        //----------------------------------------------------------------------
1349
        public function getErrorCorrectionLevel()
1350
        {
1351
            return $this->level;
1352
        }
1353
1354
        //----------------------------------------------------------------------
1355
        public function setErrorCorrectionLevel($level)
1356
        {
1357
            if ($level > QR_ECLEVEL_H) {
1358
                throw new Exception('Invalid ECLEVEL');
1359
                return 0;
0 ignored issues
show
return 0 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1360
            }
1361
1362
            $this->level = $level;
1363
1364
            return 0;
1365
        }
1366
1367
        //----------------------------------------------------------------------
1368
        public function appendEntry(QRinputItem $entry)
1369
        {
1370
            $this->items[] = $entry;
1371
        }
1372
1373
        //----------------------------------------------------------------------
1374
        public function append($mode, $size, $data)
1375
        {
1376
            try {
1377
                $entry = new QRinputItem($mode, $size, $data);
1378
                $this->items[] = $entry;
1379
1380
                return 0;
1381
            } catch (Exception $e) {
1382
                return 0;
1383
            }
1384
        }
1385
1386
        //----------------------------------------------------------------------
1387
1388
        public function insertStructuredAppendHeader($size, $index, $parity)
1389
        {
1390
            if ($size > MAX_STRUCTURED_SYMBOLS) {
1391
                throw new Exception('insertStructuredAppendHeader wrong size');
1392
            }
1393
1394
            if ($index <= 0 || $index > MAX_STRUCTURED_SYMBOLS) {
1395
                throw new Exception('insertStructuredAppendHeader wrong index');
1396
            }
1397
1398
            $buf = [$size, $index, $parity];
1399
1400
            try {
1401
                $entry = new QRinputItem(QR_MODE_STRUCTURE, 3, $buf);
1402
                array_unshift($this->items, $entry);
1403
1404
                return 0;
1405
            } catch (Exception $e) {
1406
                return 0;
1407
            }
1408
        }
1409
1410
        //----------------------------------------------------------------------
1411
        public function calcParity()
1412
        {
1413
            $parity = 0;
1414
1415
            foreach ($this->items as $item) {
1416
                if ($item->mode != QR_MODE_STRUCTURE) {
1417
                    for ($i = $item->size - 1; $i >= 0; $i--) {
1418
                        $parity ^= $item->data[$i];
1419
                    }
1420
                }
1421
            }
1422
1423
            return $parity;
1424
        }
1425
1426
        //----------------------------------------------------------------------
1427
        public static function checkModeNum($size, $data)
1428
        {
1429
            for ($i = 0; $i < $size; $i++) {
1430
                if ((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))) {
1431
                    return false;
1432
                }
1433
            }
1434
1435
            return true;
1436
        }
1437
1438
        //----------------------------------------------------------------------
1439
        public static function estimateBitsModeNum($size)
1440
        {
1441
            $w = (int) $size / 3;
1442
            $bits = $w * 10;
1443
1444
            switch ($size - $w * 3) {
1445
                case 1:
1446
                    $bits += 4;
1447
                    break;
1448
                case 2:
1449
                    $bits += 7;
1450
                    break;
1451
                default:
1452
                    break;
1453
            }
1454
1455
            return $bits;
1456
        }
1457
1458
        //----------------------------------------------------------------------
1459
        public static $anTable = [
1460
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1461
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1462
            36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
1463
                0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 44, -1, -1, -1, -1, -1,
1464
            -1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
1465
            25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
1466
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1467
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
1468
        ];
1469
1470
        //----------------------------------------------------------------------
1471
        public static function lookAnTable($c)
1472
        {
1473
            return ($c > 127) ? -1 : self::$anTable[$c];
1474
        }
1475
1476
        //----------------------------------------------------------------------
1477
        public static function checkModeAn($size, $data)
1478
        {
1479
            for ($i = 0; $i < $size; $i++) {
1480
                if (self::lookAnTable(ord($data[$i])) == -1) {
1481
                    return false;
1482
                }
1483
            }
1484
1485
            return true;
1486
        }
1487
1488
        //----------------------------------------------------------------------
1489
        public static function estimateBitsModeAn($size)
1490
        {
1491
            $w = (int) ($size / 2);
1492
            $bits = $w * 11;
1493
1494
            if ($size & 1) {
1495
                $bits += 6;
1496
            }
1497
1498
            return $bits;
1499
        }
1500
1501
        //----------------------------------------------------------------------
1502
        public static function estimateBitsMode8($size)
1503
        {
1504
            return $size * 8;
1505
        }
1506
1507
        //----------------------------------------------------------------------
1508
        public function estimateBitsModeKanji($size)
1509
        {
1510
            return (int) (($size / 2) * 13);
1511
        }
1512
1513
        //----------------------------------------------------------------------
1514
        public static function checkModeKanji($size, $data)
1515
        {
1516
            if ($size & 1) {
1517
                return false;
1518
            }
1519
1520
            for ($i = 0; $i < $size; $i += 2) {
1521
                $val = (ord($data[$i]) << 8) | ord($data[$i + 1]);
1522
                if ($val < 0x8140
1523
                || ($val > 0x9ffc && $val < 0xe040)
1524
                || $val > 0xebbf) {
1525
                    return false;
1526
                }
1527
            }
1528
1529
            return true;
1530
        }
1531
1532
        /***********************************************************************
1533
         * Validation
1534
         **********************************************************************/
1535
1536
        public static function check($mode, $size, $data)
1537
        {
1538
            if ($size <= 0) {
1539
                return false;
1540
            }
1541
1542
            switch ($mode) {
1543
                case QR_MODE_NUM:       return self::checkModeNum($size, $data);
1544
                case QR_MODE_AN:        return self::checkModeAn($size, $data);
1545
                case QR_MODE_KANJI:     return self::checkModeKanji($size, $data);
1546
                case QR_MODE_8:         return true;
1547
                case QR_MODE_STRUCTURE: return true;
1548
1549
                default:
1550
                    break;
1551
            }
1552
1553
            return false;
1554
        }
1555
1556
        //----------------------------------------------------------------------
1557
        public function estimateBitStreamSize($version)
1558
        {
1559
            $bits = 0;
1560
1561
            foreach ($this->items as $item) {
1562
                $bits += $item->estimateBitStreamSizeOfEntry($version);
1563
            }
1564
1565
            return $bits;
1566
        }
1567
1568
        //----------------------------------------------------------------------
1569
        public function estimateVersion()
1570
        {
1571
            $version = 0;
1572
            do {
1573
                $prev = $version;
1574
                $bits = $this->estimateBitStreamSize($prev);
1575
                $version = QRspec::getMinimumVersion((int) (($bits + 7) / 8), $this->level);
1576
                if ($version < 0) {
1577
                    return 0;
1578
                }
1579
            } while ($version > $prev);
1580
1581
            return $version;
1582
        }
1583
1584
        //----------------------------------------------------------------------
1585
        public static function lengthOfCode($mode, $version, $bits)
1586
        {
1587
            $payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
1588
            switch ($mode) {
1589
                case QR_MODE_NUM:
1590
                    $chunks = (int) ($payload / 10);
1591
                    $remain = $payload - $chunks * 10;
1592
                    $size = $chunks * 3;
1593
                    if ($remain >= 7) {
1594
                        $size += 2;
1595
                    } elseif ($remain >= 4) {
1596
                        $size += 1;
1597
                    }
1598
                    break;
1599
                case QR_MODE_AN:
1600
                    $chunks = (int) ($payload / 11);
1601
                    $remain = $payload - $chunks * 11;
1602
                    $size = $chunks * 2;
1603
                    if ($remain >= 6) {
1604
                        $size++;
1605
                    }
1606
                    break;
1607
                case QR_MODE_8:
1608
                    $size = (int) ($payload / 8);
1609
                    break;
1610
                case QR_MODE_KANJI:
1611
                    $size = (int) (($payload / 13) * 2);
1612
                    break;
1613
                case QR_MODE_STRUCTURE:
1614
                    $size = (int) ($payload / 8);
1615
                    break;
1616
                default:
1617
                    $size = 0;
1618
                    break;
1619
            }
1620
1621
            $maxsize = QRspec::maximumWords($mode, $version);
1622
            if ($size < 0) {
1623
                $size = 0;
1624
            }
1625
            if ($size > $maxsize) {
1626
                $size = $maxsize;
1627
            }
1628
1629
            return $size;
1630
        }
1631
1632
        //----------------------------------------------------------------------
1633
        public function createBitStream()
1634
        {
1635
            $total = 0;
1636
1637
            foreach ($this->items as $item) {
1638
                $bits = $item->encodeBitStream($this->version);
1639
1640
                if ($bits < 0) {
1641
                    return 0;
1642
                }
1643
1644
                $total += $bits;
1645
            }
1646
1647
            return $total;
1648
        }
1649
1650
        //----------------------------------------------------------------------
1651
        public function convertData()
1652
        {
1653
            $ver = $this->estimateVersion();
1654
            if ($ver > $this->getVersion()) {
1655
                $this->setVersion($ver);
1656
            }
1657
1658
            for (; ;) {
1659
                $bits = $this->createBitStream();
1660
1661
                if ($bits < 0) {
1662
                    return 0;
1663
                }
1664
1665
                $ver = QRspec::getMinimumVersion((int) (($bits + 7) / 8), $this->level);
1666
                if ($ver < 0) {
1667
                    throw new Exception('WRONG VERSION');
1668
                    return 0;
0 ignored issues
show
return 0 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
1669
                } elseif ($ver > $this->getVersion()) {
1670
                    $this->setVersion($ver);
1671
                } else {
1672
                    break;
1673
                }
1674
            }
1675
1676
            return 0;
1677
        }
1678
1679
        //----------------------------------------------------------------------
1680
        public function appendPaddingBit(&$bstream)
1681
        {
1682
            $bits = $bstream->size();
1683
            $maxwords = QRspec::getDataLength($this->version, $this->level);
1684
            $maxbits = $maxwords * 8;
1685
1686
            if ($maxbits == $bits) {
1687
                return 0;
1688
            }
1689
1690
            if ($maxbits - $bits < 5) {
1691
                return $bstream->appendNum($maxbits - $bits, 0);
1692
            }
1693
1694
            $bits += 4;
1695
            $words = (int) (($bits + 7) / 8);
1696
1697
            $padding = new QRbitstream();
1698
            $ret = $padding->appendNum($words * 8 - $bits + 4, 0);
1699
1700
            if ($ret < 0) {
1701
                return $ret;
1702
            }
1703
1704
            $padlen = $maxwords - $words;
1705
1706
            if ($padlen > 0) {
1707
                $padbuf = [];
1708
                for ($i = 0; $i < $padlen; $i++) {
1709
                    $padbuf[$i] = ($i & 1) ? 0x11 : 0xec;
1710
                }
1711
1712
                $ret = $padding->appendBytes($padlen, $padbuf);
1713
1714
                if ($ret < 0) {
1715
                    return $ret;
1716
                }
1717
            }
1718
1719
            $ret = $bstream->append($padding);
1720
1721
            return $ret;
1722
        }
1723
1724
        //----------------------------------------------------------------------
1725
        public function mergeBitStream()
1726
        {
1727
            if ($this->convertData() < 0) {
1728
                return;
1729
            }
1730
1731
            $bstream = new QRbitstream();
1732
1733
            foreach ($this->items as $item) {
1734
                $ret = $bstream->append($item->bstream);
1735
                if ($ret < 0) {
1736
                    return;
1737
                }
1738
            }
1739
1740
            return $bstream;
1741
        }
1742
1743
        //----------------------------------------------------------------------
1744
        public function getBitStream()
1745
        {
1746
            $bstream = $this->mergeBitStream();
1747
1748
            if ($bstream == null) {
1749
                return;
1750
            }
1751
1752
            $ret = $this->appendPaddingBit($bstream);
1753
            if ($ret < 0) {
1754
                return;
1755
            }
1756
1757
            return $bstream;
1758
        }
1759
1760
        //----------------------------------------------------------------------
1761
        public function getByteStream()
1762
        {
1763
            $bstream = $this->getBitStream();
0 ignored issues
show
Are you sure the assignment to $bstream is correct as $this->getBitStream() targeting QRinput::getBitStream() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

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.

Loading history...
1764
            if ($bstream == null) {
0 ignored issues
show
The condition $bstream == null is always true.
Loading history...
1765
                return;
1766
            }
1767
1768
            return $bstream->toByte();
1769
        }
1770
    }
1771
1772
//---- qrbitstream.php -----------------------------
1773
1774
/*
1775
 * PHP QR Code encoder
1776
 *
1777
 * Bitstream class
1778
 *
1779
 * Based on libqrencode C library distributed under LGPL 2.1
1780
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
1781
 *
1782
 * PHP QR Code is distributed under LGPL 3
1783
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1784
 *
1785
 * This library is free software; you can redistribute it and/or
1786
 * modify it under the terms of the GNU Lesser General Public
1787
 * License as published by the Free Software Foundation; either
1788
 * version 3 of the License, or any later version.
1789
 *
1790
 * This library is distributed in the hope that it will be useful,
1791
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1792
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1793
 * Lesser General Public License for more details.
1794
 *
1795
 * You should have received a copy of the GNU Lesser General Public
1796
 * License along with this library; if not, write to the Free Software
1797
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1798
 */
1799
1800
    class QRbitstream
1801
    {
1802
        public $data = [];
1803
1804
        //----------------------------------------------------------------------
1805
        public function size()
1806
        {
1807
            return count($this->data);
1808
        }
1809
1810
        //----------------------------------------------------------------------
1811
        public function allocate($setLength)
1812
        {
1813
            $this->data = array_fill(0, $setLength, 0);
1814
1815
            return 0;
1816
        }
1817
1818
        //----------------------------------------------------------------------
1819
        public static function newFromNum($bits, $num)
1820
        {
1821
            $bstream = new self();
1822
            $bstream->allocate($bits);
1823
1824
            $mask = 1 << ($bits - 1);
1825
            for ($i = 0; $i < $bits; $i++) {
1826
                if ($num & $mask) {
1827
                    $bstream->data[$i] = 1;
1828
                } else {
1829
                    $bstream->data[$i] = 0;
1830
                }
1831
                $mask = $mask >> 1;
1832
            }
1833
1834
            return $bstream;
1835
        }
1836
1837
        //----------------------------------------------------------------------
1838
        public static function newFromBytes($size, $data)
1839
        {
1840
            $bstream = new self();
1841
            $bstream->allocate($size * 8);
1842
            $p = 0;
1843
1844
            for ($i = 0; $i < $size; $i++) {
1845
                $mask = 0x80;
1846
                for ($j = 0; $j < 8; $j++) {
1847
                    if ($data[$i] & $mask) {
1848
                        $bstream->data[$p] = 1;
1849
                    } else {
1850
                        $bstream->data[$p] = 0;
1851
                    }
1852
                    $p++;
1853
                    $mask = $mask >> 1;
1854
                }
1855
            }
1856
1857
            return $bstream;
1858
        }
1859
1860
        //----------------------------------------------------------------------
1861
        public function append(self $arg)
1862
        {
1863
            if (is_null($arg)) {
1864
                return 0;
1865
            }
1866
1867
            if ($arg->size() == 0) {
1868
                return 0;
1869
            }
1870
1871
            if ($this->size() == 0) {
1872
                $this->data = $arg->data;
1873
1874
                return 0;
1875
            }
1876
1877
            $this->data = array_values(array_merge($this->data, $arg->data));
1878
1879
            return 0;
1880
        }
1881
1882
        //----------------------------------------------------------------------
1883
        public function appendNum($bits, $num)
1884
        {
1885
            if ($bits == 0) {
1886
                return 0;
1887
            }
1888
1889
            $b = self::newFromNum($bits, $num);
1890
1891
            if (is_null($b)) {
1892
                return 0;
1893
            }
1894
1895
            $ret = $this->append($b);
1896
            unset($b);
1897
1898
            return $ret;
1899
        }
1900
1901
        //----------------------------------------------------------------------
1902
        public function appendBytes($size, $data)
1903
        {
1904
            if ($size == 0) {
1905
                return 0;
1906
            }
1907
1908
            $b = self::newFromBytes($size, $data);
1909
1910
            if (is_null($b)) {
1911
                return 0;
1912
            }
1913
1914
            $ret = $this->append($b);
1915
            unset($b);
1916
1917
            return $ret;
1918
        }
1919
1920
        //----------------------------------------------------------------------
1921
        public function toByte()
1922
        {
1923
            $size = $this->size();
1924
1925
            if ($size == 0) {
1926
                return [];
1927
            }
1928
1929
            $data = array_fill(0, (int) (($size + 7) / 8), 0);
1930
            $bytes = (int) ($size / 8);
1931
1932
            $p = 0;
1933
1934
            for ($i = 0; $i < $bytes; $i++) {
1935
                $v = 0;
1936
                for ($j = 0; $j < 8; $j++) {
1937
                    $v = $v << 1;
1938
                    $v |= $this->data[$p];
1939
                    $p++;
1940
                }
1941
                $data[$i] = $v;
1942
            }
1943
1944
            if ($size & 7) {
1945
                $v = 0;
1946
                for ($j = 0; $j < ($size & 7); $j++) {
1947
                    $v = $v << 1;
1948
                    $v |= $this->data[$p];
1949
                    $p++;
1950
                }
1951
                $data[$bytes] = $v;
1952
            }
1953
1954
            return $data;
1955
        }
1956
    }
1957
1958
//---- qrsplit.php -----------------------------
1959
1960
/*
1961
 * PHP QR Code encoder
1962
 *
1963
 * Input splitting classes
1964
 *
1965
 * Based on libqrencode C library distributed under LGPL 2.1
1966
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
1967
 *
1968
 * PHP QR Code is distributed under LGPL 3
1969
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
1970
 *
1971
 * The following data / specifications are taken from
1972
 * "Two dimensional symbol -- QR-code -- Basic Specification" (JIS X0510:2004)
1973
 *  or
1974
 * "Automatic identification and data capture techniques --
1975
 *  QR Code 2005 bar code symbology specification" (ISO/IEC 18004:2006)
1976
 *
1977
 * This library is free software; you can redistribute it and/or
1978
 * modify it under the terms of the GNU Lesser General Public
1979
 * License as published by the Free Software Foundation; either
1980
 * version 3 of the License, or any later version.
1981
 *
1982
 * This library is distributed in the hope that it will be useful,
1983
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1984
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1985
 * Lesser General Public License for more details.
1986
 *
1987
 * You should have received a copy of the GNU Lesser General Public
1988
 * License along with this library; if not, write to the Free Software
1989
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1990
 */
1991
    class QRsplit
1992
    {
1993
        public $dataStr = '';
1994
        public $input;
1995
        public $modeHint;
1996
1997
        //----------------------------------------------------------------------
1998
        public function __construct($dataStr, $input, $modeHint)
1999
        {
2000
            $this->dataStr = $dataStr;
2001
            $this->input = $input;
2002
            $this->modeHint = $modeHint;
2003
        }
2004
2005
        //----------------------------------------------------------------------
2006
        public static function isdigitat($str, $pos)
2007
        {
2008
            if ($pos >= strlen($str)) {
2009
                return false;
2010
            }
2011
2012
            return (ord($str[$pos]) >= ord('0')) && (ord($str[$pos]) <= ord('9'));
2013
        }
2014
2015
        //----------------------------------------------------------------------
2016
        public static function isalnumat($str, $pos)
2017
        {
2018
            if ($pos >= strlen($str)) {
2019
                return false;
2020
            }
2021
2022
            return QRinput::lookAnTable(ord($str[$pos])) >= 0;
2023
        }
2024
2025
        //----------------------------------------------------------------------
2026
        public function identifyMode($pos)
2027
        {
2028
            if ($pos >= strlen($this->dataStr)) {
2029
                return QR_MODE_NUL;
2030
            }
2031
2032
            $c = $this->dataStr[$pos];
2033
2034
            if (self::isdigitat($this->dataStr, $pos)) {
2035
                return QR_MODE_NUM;
2036
            } elseif (self::isalnumat($this->dataStr, $pos)) {
2037
                return QR_MODE_AN;
2038
            } elseif ($this->modeHint == QR_MODE_KANJI) {
2039
                if ($pos + 1 < strlen($this->dataStr)) {
2040
                    $d = $this->dataStr[$pos + 1];
2041
                    $word = (ord($c) << 8) | ord($d);
2042
                    if (($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
2043
                        return QR_MODE_KANJI;
2044
                    }
2045
                }
2046
            }
2047
2048
            return QR_MODE_8;
2049
        }
2050
2051
        //----------------------------------------------------------------------
2052
        public function eatNum()
2053
        {
2054
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2055
2056
            $p = 0;
2057
            while (self::isdigitat($this->dataStr, $p)) {
2058
                $p++;
2059
            }
2060
2061
            $run = $p;
2062
            $mode = $this->identifyMode($p);
2063
2064
            if ($mode == QR_MODE_8) {
2065
                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2066
                     + QRinput::estimateBitsMode8(1)         // + 4 + l8
2067
                     - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
2068
                if ($dif > 0) {
2069
                    return $this->eat8();
2070
                }
2071
            }
2072
            if ($mode == QR_MODE_AN) {
2073
                $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
2074
                     + QRinput::estimateBitsModeAn(1)        // + 4 + la
2075
                     - QRinput::estimateBitsModeAn($run + 1); // - 4 - la
2076
                if ($dif > 0) {
2077
                    return $this->eatAn();
2078
                }
2079
            }
2080
2081
            $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
2082
            if ($ret < 0) {
2083
                return 0;
2084
            }
2085
2086
            return $run;
2087
        }
2088
2089
        //----------------------------------------------------------------------
2090
        public function eatAn()
2091
        {
2092
            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
2093
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2094
2095
            $p = 0;
2096
2097
            while (self::isalnumat($this->dataStr, $p)) {
2098
                if (self::isdigitat($this->dataStr, $p)) {
2099
                    $q = $p;
2100
                    while (self::isdigitat($this->dataStr, $q)) {
2101
                        $q++;
2102
                    }
2103
2104
                    $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
2105
                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2106
                         - QRinput::estimateBitsModeAn($q); // - 4 - la
2107
2108
                    if ($dif < 0) {
2109
                        break;
2110
                    } else {
2111
                        $p = $q;
2112
                    }
2113
                } else {
2114
                    $p++;
2115
                }
2116
            }
2117
2118
            $run = $p;
2119
2120
            if (!self::isalnumat($this->dataStr, $p)) {
2121
                $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
2122
                     + QRinput::estimateBitsMode8(1) // + 4 + l8
2123
                      - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
2124
                if ($dif > 0) {
2125
                    return $this->eat8();
2126
                }
2127
            }
2128
2129
            $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
2130
            if ($ret < 0) {
2131
                return 0;
2132
            }
2133
2134
            return $run;
2135
        }
2136
2137
        //----------------------------------------------------------------------
2138
        public function eatKanji()
2139
        {
2140
            $p = 0;
2141
2142
            while ($this->identifyMode($p) == QR_MODE_KANJI) {
2143
                $p += 2;
2144
            }
2145
2146
            $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
2147
            if ($ret < 0) {
2148
                return 0;
2149
            }
2150
2151
            return $ret;
2152
        }
2153
2154
        //----------------------------------------------------------------------
2155
        public function eat8()
2156
        {
2157
            $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
2158
            $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
2159
2160
            $p = 1;
2161
            $dataStrLen = strlen($this->dataStr);
2162
2163
            while ($p < $dataStrLen) {
2164
                $mode = $this->identifyMode($p);
2165
                if ($mode == QR_MODE_KANJI) {
2166
                    break;
2167
                }
2168
                if ($mode == QR_MODE_NUM) {
2169
                    $q = $p;
2170
                    while (self::isdigitat($this->dataStr, $q)) {
2171
                        $q++;
2172
                    }
2173
                    $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
2174
                         + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
2175
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
2176
                    if ($dif < 0) {
2177
                        break;
2178
                    } else {
2179
                        $p = $q;
2180
                    }
2181
                } elseif ($mode == QR_MODE_AN) {
2182
                    $q = $p;
2183
                    while (self::isalnumat($this->dataStr, $q)) {
2184
                        $q++;
2185
                    }
2186
                    $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
2187
                         + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
2188
                         - QRinput::estimateBitsMode8($q); // - 4 - l8
2189
                    if ($dif < 0) {
2190
                        break;
2191
                    } else {
2192
                        $p = $q;
2193
                    }
2194
                } else {
2195
                    $p++;
2196
                }
2197
            }
2198
2199
            $run = $p;
2200
            $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
2201
2202
            if ($ret < 0) {
2203
                return 0;
2204
            }
2205
2206
            return $run;
2207
        }
2208
2209
        //----------------------------------------------------------------------
2210
        public function splitString()
2211
        {
2212
            while (strlen($this->dataStr) > 0) {
2213
                if ($this->dataStr == '') {
2214
                    return 0;
2215
                }
2216
2217
                $mode = $this->identifyMode(0);
2218
2219
                switch ($mode) {
2220
                    case QR_MODE_NUM: $length = $this->eatNum(); break;
2221
                    case QR_MODE_AN:  $length = $this->eatAn(); break;
2222
                    case QR_MODE_KANJI:
2223
                        if ($mode == QR_MODE_KANJI) {
2224
                            $length = $this->eatKanji();
2225
                        } else {
2226
                            $length = $this->eat8();
2227
                        }
2228
                        break;
2229
                    default: $length = $this->eat8(); break;
2230
2231
                }
2232
2233
                if ($length == 0) {
2234
                    return 0;
2235
                }
2236
                if ($length < 0) {
2237
                    return 0;
2238
                }
2239
2240
                $this->dataStr = substr($this->dataStr, $length);
2241
            }
2242
        }
2243
2244
        //----------------------------------------------------------------------
2245
        public function toUpper()
2246
        {
2247
            $stringLen = strlen($this->dataStr);
2248
            $p = 0;
2249
2250
            while ($p < $stringLen) {
2251
                $mode = $this->identifyMode(substr($this->dataStr, $p));
2252
                if ($mode == QR_MODE_KANJI) {
2253
                    $p += 2;
2254
                } else {
2255
                    if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
2256
                        $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
2257
                    }
2258
                    $p++;
2259
                }
2260
            }
2261
2262
            return $this->dataStr;
2263
        }
2264
2265
        //----------------------------------------------------------------------
2266
        public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
2267
        {
2268
            if (is_null($string) || $string == '\0' || $string == '') {
2269
                throw new Exception('empty string!!!');
2270
            }
2271
2272
            $split = new self($string, $input, $modeHint);
2273
2274
            if (!$casesensitive) {
2275
                $split->toUpper();
2276
            }
2277
2278
            return $split->splitString();
2279
        }
2280
    }
2281
2282
//---- qrrscode.php -----------------------------
2283
2284
/*
2285
 * PHP QR Code encoder
2286
 *
2287
 * Reed-Solomon error correction support
2288
 *
2289
 * Copyright (C) 2002, 2003, 2004, 2006 Phil Karn, KA9Q
2290
 * (libfec is released under the GNU Lesser General Public License.)
2291
 *
2292
 * Based on libqrencode C library distributed under LGPL 2.1
2293
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
2294
 *
2295
 * PHP QR Code is distributed under LGPL 3
2296
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2297
 *
2298
 * This library is free software; you can redistribute it and/or
2299
 * modify it under the terms of the GNU Lesser General Public
2300
 * License as published by the Free Software Foundation; either
2301
 * version 3 of the License, or any later version.
2302
 *
2303
 * This library is distributed in the hope that it will be useful,
2304
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2305
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2306
 * Lesser General Public License for more details.
2307
 *
2308
 * You should have received a copy of the GNU Lesser General Public
2309
 * License along with this library; if not, write to the Free Software
2310
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2311
 */
2312
2313
    class QRrsItem
2314
    {
2315
        public $mm; // Bits per symbol
2316
        public $nn; // Symbols per block (= (1<<mm)-1)
2317
        public $alpha_to = []; // log lookup table
2318
        public $index_of = []; // Antilog lookup table
2319
        public $genpoly = []; // Generator polynomial
2320
        public $nroots; // Number of generator roots = number of parity symbols
2321
        public $fcr; // First consecutive root, index form
2322
        public $prim; // Primitive element, index form
2323
        public $iprim; // prim-th root of 1, index form
2324
        public $pad; // Padding bytes in shortened block
2325
        public $gfpoly;
2326
2327
        //----------------------------------------------------------------------
2328
        public function modnn($x)
2329
        {
2330
            while ($x >= $this->nn) {
2331
                $x -= $this->nn;
2332
                $x = ($x >> $this->mm) + ($x & $this->nn);
2333
            }
2334
2335
            return $x;
2336
        }
2337
2338
        //----------------------------------------------------------------------
2339
        public static function init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2340
        {
2341
            // Common code for intializing a Reed-Solomon control block (char or int symbols)
2342
            // Copyright 2004 Phil Karn, KA9Q
2343
            // May be used under the terms of the GNU Lesser General Public License (LGPL)
2344
2345
            $rs = null;
2346
2347
            // Check parameter ranges
2348
            if ($symsize < 0 || $symsize > 8) {
2349
                return $rs;
2350
            }
2351
            if ($fcr < 0 || $fcr >= (1 << $symsize)) {
2352
                return $rs;
2353
            }
2354
            if ($prim <= 0 || $prim >= (1 << $symsize)) {
2355
                return $rs;
2356
            }
2357
            if ($nroots < 0 || $nroots >= (1 << $symsize)) {
2358
                return $rs;
2359
            } // Can't have more roots than symbol values!
2360
            if ($pad < 0 || $pad >= ((1 << $symsize) - 1 - $nroots)) {
2361
                return $rs;
2362
            } // Too much padding
2363
2364
            $rs = new self();
2365
            $rs->mm = $symsize;
2366
            $rs->nn = (1 << $symsize) - 1;
2367
            $rs->pad = $pad;
2368
2369
            $rs->alpha_to = array_fill(0, $rs->nn + 1, 0);
2370
            $rs->index_of = array_fill(0, $rs->nn + 1, 0);
2371
2372
            // PHP style macro replacement ;)
2373
            $NN = &$rs->nn;
2374
            $A0 = &$NN;
2375
2376
            // Generate Galois field lookup tables
2377
            $rs->index_of[0] = $A0; // log(zero) = -inf
2378
            $rs->alpha_to[$A0] = 0; // alpha**-inf = 0
2379
            $sr = 1;
2380
2381
            for ($i = 0; $i < $rs->nn; $i++) {
2382
                $rs->index_of[$sr] = $i;
2383
                $rs->alpha_to[$i] = $sr;
2384
                $sr <<= 1;
2385
                if ($sr & (1 << $symsize)) {
2386
                    $sr ^= $gfpoly;
2387
                }
2388
                $sr &= $rs->nn;
2389
            }
2390
2391
            if ($sr != 1) {
2392
                // field generator polynomial is not primitive!
2393
                $rs = null;
2394
2395
                return $rs;
2396
            }
2397
2398
            /* Form RS code generator polynomial from its roots */
2399
            $rs->genpoly = array_fill(0, $nroots + 1, 0);
2400
2401
            $rs->fcr = $fcr;
2402
            $rs->prim = $prim;
2403
            $rs->nroots = $nroots;
2404
            $rs->gfpoly = $gfpoly;
2405
2406
            /* Find prim-th root of 1, used in decoding */
2407
            for ($iprim = 1; ($iprim % $prim) != 0; $iprim += $rs->nn); // intentional empty-body loop!
2408
2409
            $rs->iprim = (int) ($iprim / $prim);
2410
            $rs->genpoly[0] = 1;
2411
2412
            for ($i = 0, $root = $fcr * $prim; $i < $nroots; $i++, $root += $prim) {
2413
                $rs->genpoly[$i + 1] = 1;
2414
2415
                // Multiply rs->genpoly[] by  @**(root + x)
2416
                for ($j = $i; $j > 0; $j--) {
2417
                    if ($rs->genpoly[$j] != 0) {
2418
                        $rs->genpoly[$j] = $rs->genpoly[$j - 1] ^ $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[$j]] + $root)];
2419
                    } else {
2420
                        $rs->genpoly[$j] = $rs->genpoly[$j - 1];
2421
                    }
2422
                }
2423
                // rs->genpoly[0] can never be zero
2424
                $rs->genpoly[0] = $rs->alpha_to[$rs->modnn($rs->index_of[$rs->genpoly[0]] + $root)];
2425
            }
2426
2427
            // convert rs->genpoly[] to index form for quicker encoding
2428
            for ($i = 0; $i <= $nroots; $i++) {
2429
                $rs->genpoly[$i] = $rs->index_of[$rs->genpoly[$i]];
2430
            }
2431
2432
            return $rs;
2433
        }
2434
2435
        //----------------------------------------------------------------------
2436
        public function encode_rs_char($data, &$parity)
2437
        {
2438
            $MM = &$this->mm;
0 ignored issues
show
The assignment to $MM is dead and can be removed.
Loading history...
2439
            $NN = &$this->nn;
2440
            $ALPHA_TO = &$this->alpha_to;
2441
            $INDEX_OF = &$this->index_of;
2442
            $GENPOLY = &$this->genpoly;
2443
            $NROOTS = &$this->nroots;
2444
            $FCR = &$this->fcr;
0 ignored issues
show
The assignment to $FCR is dead and can be removed.
Loading history...
2445
            $PRIM = &$this->prim;
0 ignored issues
show
The assignment to $PRIM is dead and can be removed.
Loading history...
2446
            $IPRIM = &$this->iprim;
0 ignored issues
show
The assignment to $IPRIM is dead and can be removed.
Loading history...
2447
            $PAD = &$this->pad;
2448
            $A0 = &$NN;
2449
2450
            $parity = array_fill(0, $NROOTS, 0);
2451
2452
            for ($i = 0; $i < ($NN - $NROOTS - $PAD); $i++) {
2453
                $feedback = $INDEX_OF[$data[$i] ^ $parity[0]];
2454
                if ($feedback != $A0) {
2455
                    // feedback term is non-zero
2456
2457
                    // This line is unnecessary when GENPOLY[NROOTS] is unity, as it must
2458
                    // always be for the polynomials constructed by init_rs()
2459
                    $feedback = $this->modnn($NN - $GENPOLY[$NROOTS] + $feedback);
2460
2461
                    for ($j = 1; $j < $NROOTS; $j++) {
2462
                        $parity[$j] ^= $ALPHA_TO[$this->modnn($feedback + $GENPOLY[$NROOTS - $j])];
2463
                    }
2464
                }
2465
2466
                // Shift
2467
                array_shift($parity);
2468
                if ($feedback != $A0) {
2469
                    array_push($parity, $ALPHA_TO[$this->modnn($feedback + $GENPOLY[0])]);
2470
                } else {
2471
                    array_push($parity, 0);
2472
                }
2473
            }
2474
        }
2475
    }
2476
2477
    //##########################################################################
2478
2479
    class QRrs
2480
    {
2481
        public static $items = [];
2482
2483
        //----------------------------------------------------------------------
2484
        public static function init_rs($symsize, $gfpoly, $fcr, $prim, $nroots, $pad)
2485
        {
2486
            foreach (self::$items as $rs) {
2487
                if ($rs->pad != $pad) {
2488
                    continue;
2489
                }
2490
                if ($rs->nroots != $nroots) {
2491
                    continue;
2492
                }
2493
                if ($rs->mm != $symsize) {
2494
                    continue;
2495
                }
2496
                if ($rs->gfpoly != $gfpoly) {
2497
                    continue;
2498
                }
2499
                if ($rs->fcr != $fcr) {
2500
                    continue;
2501
                }
2502
                if ($rs->prim != $prim) {
2503
                    continue;
2504
                }
2505
2506
                return $rs;
2507
            }
2508
2509
            $rs = QRrsItem::init_rs_char($symsize, $gfpoly, $fcr, $prim, $nroots, $pad);
2510
            array_unshift(self::$items, $rs);
2511
2512
            return $rs;
2513
        }
2514
    }
2515
2516
//---- qrmask.php -----------------------------
2517
2518
/*
2519
 * PHP QR Code encoder
2520
 *
2521
 * Masking
2522
 *
2523
 * Based on libqrencode C library distributed under LGPL 2.1
2524
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
2525
 *
2526
 * PHP QR Code is distributed under LGPL 3
2527
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2528
 *
2529
 * This library is free software; you can redistribute it and/or
2530
 * modify it under the terms of the GNU Lesser General Public
2531
 * License as published by the Free Software Foundation; either
2532
 * version 3 of the License, or any later version.
2533
 *
2534
 * This library is distributed in the hope that it will be useful,
2535
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2536
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2537
 * Lesser General Public License for more details.
2538
 *
2539
 * You should have received a copy of the GNU Lesser General Public
2540
 * License along with this library; if not, write to the Free Software
2541
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2542
 */
2543
2544
    define('N1', 3);
2545
    define('N2', 3);
2546
    define('N3', 40);
2547
    define('N4', 10);
2548
2549
    class QRmask
2550
    {
2551
        public $runLength = [];
2552
2553
        //----------------------------------------------------------------------
2554
        public function __construct()
2555
        {
2556
            $this->runLength = array_fill(0, QRSPEC_WIDTH_MAX + 1, 0);
2557
        }
2558
2559
        //----------------------------------------------------------------------
2560
        public function writeFormatInformation($width, &$frame, $mask, $level)
2561
        {
2562
            $blacks = 0;
2563
            $format = QRspec::getFormatInfo($mask, $level);
2564
2565
            for ($i = 0; $i < 8; $i++) {
2566
                if ($format & 1) {
2567
                    $blacks += 2;
2568
                    $v = 0x85;
2569
                } else {
2570
                    $v = 0x84;
2571
                }
2572
2573
                $frame[8][$width - 1 - $i] = chr($v);
2574
                if ($i < 6) {
2575
                    $frame[$i][8] = chr($v);
2576
                } else {
2577
                    $frame[$i + 1][8] = chr($v);
2578
                }
2579
                $format = $format >> 1;
2580
            }
2581
2582
            for ($i = 0; $i < 7; $i++) {
2583
                if ($format & 1) {
2584
                    $blacks += 2;
2585
                    $v = 0x85;
2586
                } else {
2587
                    $v = 0x84;
2588
                }
2589
2590
                $frame[$width - 7 + $i][8] = chr($v);
2591
                if ($i == 0) {
2592
                    $frame[8][7] = chr($v);
2593
                } else {
2594
                    $frame[8][6 - $i] = chr($v);
2595
                }
2596
2597
                $format = $format >> 1;
2598
            }
2599
2600
            return $blacks;
2601
        }
2602
2603
        //----------------------------------------------------------------------
2604
        public function mask0($x, $y)
2605
        {
2606
            return ($x + $y) & 1;
2607
        }
2608
2609
        public function mask1($x, $y)
2610
        {
2611
            return $y & 1;
2612
        }
2613
2614
        public function mask2($x, $y)
2615
        {
2616
            return $x % 3;
2617
        }
2618
2619
        public function mask3($x, $y)
2620
        {
2621
            return ($x + $y) % 3;
2622
        }
2623
2624
        public function mask4($x, $y)
2625
        {
2626
            return (((int) ($y / 2)) + ((int) ($x / 3))) & 1;
2627
        }
2628
2629
        public function mask5($x, $y)
2630
        {
2631
            return (($x * $y) & 1) + ($x * $y) % 3;
2632
        }
2633
2634
        public function mask6($x, $y)
2635
        {
2636
            return ((($x * $y) & 1) + ($x * $y) % 3) & 1;
2637
        }
2638
2639
        public function mask7($x, $y)
2640
        {
2641
            return ((($x * $y) % 3) + (($x + $y) & 1)) & 1;
2642
        }
2643
2644
        //----------------------------------------------------------------------
2645
        private function generateMaskNo($maskNo, $width, $frame)
2646
        {
2647
            $bitMask = array_fill(0, $width, array_fill(0, $width, 0));
2648
2649
            for ($y = 0; $y < $width; $y++) {
2650
                for ($x = 0; $x < $width; $x++) {
2651
                    if (ord($frame[$y][$x]) & 0x80) {
2652
                        $bitMask[$y][$x] = 0;
2653
                    } else {
2654
                        $maskFunc = call_user_func([$this, 'mask'.$maskNo], $x, $y);
2655
                        $bitMask[$y][$x] = ($maskFunc == 0) ? 1 : 0;
2656
                    }
2657
                }
2658
            }
2659
2660
            return $bitMask;
2661
        }
2662
2663
        //----------------------------------------------------------------------
2664
        public static function serial($bitFrame)
2665
        {
2666
            $codeArr = [];
2667
2668
            foreach ($bitFrame as $line) {
2669
                $codeArr[] = implode('', $line);
2670
            }
2671
2672
            return gzcompress(implode("\n", $codeArr), 9);
2673
        }
2674
2675
        //----------------------------------------------------------------------
2676
        public static function unserial($code)
2677
        {
2678
            $codeArr = [];
2679
2680
            $codeLines = explode("\n", gzuncompress($code));
2681
            foreach ($codeLines as $line) {
2682
                $codeArr[] = str_split($line);
2683
            }
2684
2685
            return $codeArr;
2686
        }
2687
2688
        //----------------------------------------------------------------------
2689
        public function makeMaskNo($maskNo, $width, $s, &$d, $maskGenOnly = false)
2690
        {
2691
            $b = 0;
2692
            $bitMask = [];
2693
2694
            $fileName = QR_CACHE_DIR.'mask_'.$maskNo.DIRECTORY_SEPARATOR.'mask_'.$width.'_'.$maskNo.'.dat';
2695
2696
            if (QR_CACHEABLE) {
2697
                if (file_exists($fileName)) {
2698
                    $bitMask = self::unserial(file_get_contents($fileName));
2699
                } else {
2700
                    $bitMask = $this->generateMaskNo($maskNo, $width, $s);
2701
                    if (!file_exists(QR_CACHE_DIR.'mask_'.$maskNo)) {
2702
                        mkdir(QR_CACHE_DIR.'mask_'.$maskNo);
2703
                    }
2704
                    file_put_contents($fileName, self::serial($bitMask));
2705
                }
2706
            } else {
2707
                $bitMask = $this->generateMaskNo($maskNo, $width, $s);
2708
            }
2709
2710
            if ($maskGenOnly) {
2711
                return;
2712
            }
2713
2714
            $d = $s;
2715
2716
            for ($y = 0; $y < $width; $y++) {
2717
                for ($x = 0; $x < $width; $x++) {
2718
                    if ($bitMask[$y][$x] == 1) {
2719
                        $d[$y][$x] = chr(ord($s[$y][$x]) ^ (int) $bitMask[$y][$x]);
2720
                    }
2721
                    $b += (int) (ord($d[$y][$x]) & 1);
2722
                }
2723
            }
2724
2725
            return $b;
2726
        }
2727
2728
        //----------------------------------------------------------------------
2729
        public function makeMask($width, $frame, $maskNo, $level)
2730
        {
2731
            $masked = array_fill(0, $width, str_repeat("\0", $width));
2732
            $this->makeMaskNo($maskNo, $width, $frame, $masked);
2733
            $this->writeFormatInformation($width, $masked, $maskNo, $level);
2734
2735
            return $masked;
2736
        }
2737
2738
        //----------------------------------------------------------------------
2739
        public function calcN1N3($length)
2740
        {
2741
            $demerit = 0;
2742
2743
            for ($i = 0; $i < $length; $i++) {
2744
                if ($this->runLength[$i] >= 5) {
2745
                    $demerit += (N1 + ($this->runLength[$i] - 5));
2746
                }
2747
                if ($i & 1) {
2748
                    if (($i >= 3) && ($i < ($length - 2)) && ($this->runLength[$i] % 3 == 0)) {
2749
                        $fact = (int) ($this->runLength[$i] / 3);
2750
                        if (($this->runLength[$i - 2] == $fact) &&
2751
                           ($this->runLength[$i - 1] == $fact) &&
2752
                           ($this->runLength[$i + 1] == $fact) &&
2753
                           ($this->runLength[$i + 2] == $fact)) {
2754
                            if (($this->runLength[$i - 3] < 0) || ($this->runLength[$i - 3] >= (4 * $fact))) {
2755
                                $demerit += N3;
2756
                            } elseif ((($i + 3) >= $length) || ($this->runLength[$i + 3] >= (4 * $fact))) {
2757
                                $demerit += N3;
2758
                            }
2759
                        }
2760
                    }
2761
                }
2762
            }
2763
2764
            return $demerit;
2765
        }
2766
2767
        //----------------------------------------------------------------------
2768
        public function evaluateSymbol($width, $frame)
2769
        {
2770
            $head = 0;
2771
            $demerit = 0;
2772
2773
            for ($y = 0; $y < $width; $y++) {
2774
                $head = 0;
2775
                $this->runLength[0] = 1;
2776
2777
                $frameY = $frame[$y];
2778
2779
                if ($y > 0) {
2780
                    $frameYM = $frame[$y - 1];
2781
                }
2782
2783
                for ($x = 0; $x < $width; $x++) {
2784
                    if (($x > 0) && ($y > 0)) {
2785
                        $b22 = ord($frameY[$x]) & ord($frameY[$x - 1]) & ord($frameYM[$x]) & ord($frameYM[$x - 1]);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $frameYM does not seem to be defined for all execution paths leading up to this point.
Loading history...
2786
                        $w22 = ord($frameY[$x]) | ord($frameY[$x - 1]) | ord($frameYM[$x]) | ord($frameYM[$x - 1]);
2787
2788
                        if (($b22 | ($w22 ^ 1)) & 1) {
2789
                            $demerit += N2;
2790
                        }
2791
                    }
2792
                    if (($x == 0) && (ord($frameY[$x]) & 1)) {
2793
                        $this->runLength[0] = -1;
2794
                        $head = 1;
2795
                        $this->runLength[$head] = 1;
2796
                    } elseif ($x > 0) {
2797
                        if ((ord($frameY[$x]) ^ ord($frameY[$x - 1])) & 1) {
2798
                            $head++;
2799
                            $this->runLength[$head] = 1;
2800
                        } else {
2801
                            $this->runLength[$head]++;
2802
                        }
2803
                    }
2804
                }
2805
2806
                $demerit += $this->calcN1N3($head + 1);
2807
            }
2808
2809
            for ($x = 0; $x < $width; $x++) {
2810
                $head = 0;
2811
                $this->runLength[0] = 1;
2812
2813
                for ($y = 0; $y < $width; $y++) {
2814
                    if ($y == 0 && (ord($frame[$y][$x]) & 1)) {
2815
                        $this->runLength[0] = -1;
2816
                        $head = 1;
2817
                        $this->runLength[$head] = 1;
2818
                    } elseif ($y > 0) {
2819
                        if ((ord($frame[$y][$x]) ^ ord($frame[$y - 1][$x])) & 1) {
2820
                            $head++;
2821
                            $this->runLength[$head] = 1;
2822
                        } else {
2823
                            $this->runLength[$head]++;
2824
                        }
2825
                    }
2826
                }
2827
2828
                $demerit += $this->calcN1N3($head + 1);
2829
            }
2830
2831
            return $demerit;
2832
        }
2833
2834
        //----------------------------------------------------------------------
2835
        public function mask($width, $frame, $level)
2836
        {
2837
            $minDemerit = PHP_INT_MAX;
2838
            $bestMaskNum = 0;
0 ignored issues
show
The assignment to $bestMaskNum is dead and can be removed.
Loading history...
2839
            $bestMask = [];
0 ignored issues
show
The assignment to $bestMask is dead and can be removed.
Loading history...
2840
2841
            $checked_masks = [0, 1, 2, 3, 4, 5, 6, 7];
2842
2843
            if (QR_FIND_FROM_RANDOM !== false) {
0 ignored issues
show
The condition QR_FIND_FROM_RANDOM !== false is always false.
Loading history...
2844
                $howManuOut = 8 - (QR_FIND_FROM_RANDOM % 9);
2845
                for ($i = 0; $i < $howManuOut; $i++) {
2846
                    $remPos = rand(0, count($checked_masks) - 1);
2847
                    unset($checked_masks[$remPos]);
2848
                    $checked_masks = array_values($checked_masks);
2849
                }
2850
            }
2851
2852
            $bestMask = $frame;
2853
2854
            foreach ($checked_masks as $i) {
2855
                $mask = array_fill(0, $width, str_repeat("\0", $width));
2856
2857
                $demerit = 0;
0 ignored issues
show
The assignment to $demerit is dead and can be removed.
Loading history...
2858
                $blacks = 0;
0 ignored issues
show
The assignment to $blacks is dead and can be removed.
Loading history...
2859
                $blacks = $this->makeMaskNo($i, $width, $frame, $mask);
2860
                $blacks += $this->writeFormatInformation($width, $mask, $i, $level);
2861
                $blacks = (int) (100 * $blacks / ($width * $width));
2862
                $demerit = (int) ((int) (abs($blacks - 50) / 5) * N4);
2863
                $demerit += $this->evaluateSymbol($width, $mask);
2864
2865
                if ($demerit < $minDemerit) {
2866
                    $minDemerit = $demerit;
2867
                    $bestMask = $mask;
2868
                    $bestMaskNum = $i;
2869
                }
2870
            }
2871
2872
            return $bestMask;
2873
        }
2874
2875
        //----------------------------------------------------------------------
2876
    }
2877
2878
//---- qrencode.php -----------------------------
2879
2880
/*
2881
 * PHP QR Code encoder
2882
 *
2883
 * Main encoder classes.
2884
 *
2885
 * Based on libqrencode C library distributed under LGPL 2.1
2886
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <[email protected]>
2887
 *
2888
 * PHP QR Code is distributed under LGPL 3
2889
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
2890
 *
2891
 * This library is free software; you can redistribute it and/or
2892
 * modify it under the terms of the GNU Lesser General Public
2893
 * License as published by the Free Software Foundation; either
2894
 * version 3 of the License, or any later version.
2895
 *
2896
 * This library is distributed in the hope that it will be useful,
2897
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
2898
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2899
 * Lesser General Public License for more details.
2900
 *
2901
 * You should have received a copy of the GNU Lesser General Public
2902
 * License along with this library; if not, write to the Free Software
2903
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2904
 */
2905
2906
    class QRrsblock
2907
    {
2908
        public $dataLength;
2909
        public $data = [];
2910
        public $eccLength;
2911
        public $ecc = [];
2912
2913
        public function __construct($dl, $data, $el, &$ecc, QRrsItem $rs)
2914
        {
2915
            $rs->encode_rs_char($data, $ecc);
2916
2917
            $this->dataLength = $dl;
2918
            $this->data = $data;
2919
            $this->eccLength = $el;
2920
            $this->ecc = $ecc;
2921
        }
2922
    }
2923
2924
    //##########################################################################
2925
2926
    class QRrawcode
2927
    {
2928
        public $version;
2929
        public $datacode = [];
2930
        public $ecccode = [];
2931
        public $blocks;
2932
        public $rsblocks = []; //of RSblock
2933
        public $count;
2934
        public $dataLength;
2935
        public $eccLength;
2936
        public $b1;
2937
2938
        //----------------------------------------------------------------------
2939
        public function __construct(QRinput $input)
2940
        {
2941
            $spec = [0, 0, 0, 0, 0];
2942
2943
            $this->datacode = $input->getByteStream();
0 ignored issues
show
Are you sure the assignment to $this->datacode is correct as $input->getByteStream() targeting QRinput::getByteStream() seems to always return null.

This check looks for function or method calls that always return null and whose return value is assigned to a variable.

class A
{
    function getObject()
    {
        return null;
    }

}

$a = new A();
$object = $a->getObject();

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.

Loading history...
2944
            if (is_null($this->datacode)) {
0 ignored issues
show
The condition is_null($this->datacode) is always true.
Loading history...
2945
                throw new Exception('null imput string');
2946
            }
2947
2948
            QRspec::getEccSpec($input->getVersion(), $input->getErrorCorrectionLevel(), $spec);
2949
2950
            $this->version = $input->getVersion();
2951
            $this->b1 = QRspec::rsBlockNum1($spec);
2952
            $this->dataLength = QRspec::rsDataLength($spec);
2953
            $this->eccLength = QRspec::rsEccLength($spec);
2954
            $this->ecccode = array_fill(0, $this->eccLength, 0);
2955
            $this->blocks = QRspec::rsBlockNum($spec);
2956
2957
            $ret = $this->init($spec);
2958
            if ($ret < 0) {
2959
                throw new Exception('block alloc error');
2960
                return;
0 ignored issues
show
return 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
2961
            }
2962
2963
            $this->count = 0;
2964
        }
2965
2966
        //----------------------------------------------------------------------
2967
        public function init(array $spec)
2968
        {
2969
            $dl = QRspec::rsDataCodes1($spec);
2970
            $el = QRspec::rsEccCodes1($spec);
2971
            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2972
2973
            $blockNo = 0;
2974
            $dataPos = 0;
2975
            $eccPos = 0;
2976
            for ($i = 0; $i < QRspec::rsBlockNum1($spec); $i++) {
2977
                $ecc = array_slice($this->ecccode, $eccPos);
2978
                $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 ignore-type  annotation

2978
                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, /** @scrutinizer ignore-type */ $rs);
Loading history...
2979
                $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
2980
2981
                $dataPos += $dl;
2982
                $eccPos += $el;
2983
                $blockNo++;
2984
            }
2985
2986
            if (QRspec::rsBlockNum2($spec) == 0) {
2987
                return 0;
2988
            }
2989
2990
            $dl = QRspec::rsDataCodes2($spec);
2991
            $el = QRspec::rsEccCodes2($spec);
2992
            $rs = QRrs::init_rs(8, 0x11d, 0, 1, $el, 255 - $dl - $el);
2993
2994
            if ($rs == null) {
2995
                return 0;
2996
            }
2997
2998
            for ($i = 0; $i < QRspec::rsBlockNum2($spec); $i++) {
2999
                $ecc = array_slice($this->ecccode, $eccPos);
3000
                $this->rsblocks[$blockNo] = new QRrsblock($dl, array_slice($this->datacode, $dataPos), $el, $ecc, $rs);
3001
                $this->ecccode = array_merge(array_slice($this->ecccode, 0, $eccPos), $ecc);
3002
3003
                $dataPos += $dl;
3004
                $eccPos += $el;
3005
                $blockNo++;
3006
            }
3007
3008
            return 0;
3009
        }
3010
3011
        //----------------------------------------------------------------------
3012
        public function getCode()
3013
        {
3014
            $ret;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $ret seems to be never defined.
Loading history...
3015
3016
            if ($this->count < $this->dataLength) {
3017
                $row = $this->count % $this->blocks;
3018
                $col = $this->count / $this->blocks;
3019
                if ($col >= $this->rsblocks[0]->dataLength) {
3020
                    $row += $this->b1;
3021
                }
3022
                $ret = $this->rsblocks[$row]->data[$col];
3023
            } elseif ($this->count < $this->dataLength + $this->eccLength) {
3024
                $row = ($this->count - $this->dataLength) % $this->blocks;
3025
                $col = ($this->count - $this->dataLength) / $this->blocks;
3026
                $ret = $this->rsblocks[$row]->ecc[$col];
3027
            } else {
3028
                return 0;
3029
            }
3030
            $this->count++;
3031
3032
            return $ret;
3033
        }
3034
    }
3035
3036
    //##########################################################################
3037
3038
    class QRcode
3039
    {
3040
        public $version;
3041
        public $width;
3042
        public $data;
3043
3044
        //----------------------------------------------------------------------
3045
        public function encodeMask(QRinput $input, $mask)
3046
        {
3047
            if ($input->getVersion() < 0 || $input->getVersion() > QRSPEC_VERSION_MAX) {
3048
                throw new Exception('wrong version');
3049
            }
3050
            if ($input->getErrorCorrectionLevel() > QR_ECLEVEL_H) {
3051
                throw new Exception('wrong level');
3052
            }
3053
3054
            $raw = new QRrawcode($input);
3055
3056
            QRtools::markTime('after_raw');
3057
3058
            $version = $raw->version;
3059
            $width = QRspec::getWidth($version);
3060
            $frame = QRspec::newFrame($version);
3061
3062
            $filler = new FrameFiller($width, $frame);
3063
            if (is_null($filler)) {
3064
                return;
3065
            }
3066
3067
            // inteleaved data and ecc codes
3068
            for ($i = 0; $i < $raw->dataLength + $raw->eccLength; $i++) {
3069
                $code = $raw->getCode();
3070
                $bit = 0x80;
3071
                for ($j = 0; $j < 8; $j++) {
3072
                    $addr = $filler->next();
3073
                    $filler->setFrameAt($addr, 0x02 | (($bit & $code) != 0));
3074
                    $bit = $bit >> 1;
3075
                }
3076
            }
3077
3078
            QRtools::markTime('after_filler');
3079
3080
            unset($raw);
3081
3082
            // remainder bits
3083
            $j = QRspec::getRemainder($version);
3084
            for ($i = 0; $i < $j; $i++) {
3085
                $addr = $filler->next();
3086
                $filler->setFrameAt($addr, 0x02);
3087
            }
3088
3089
            $frame = $filler->frame;
3090
            unset($filler);
3091
3092
            // masking
3093
            $maskObj = new QRmask();
3094
            if ($mask < 0) {
3095
                if (QR_FIND_BEST_MASK) {
3096
                    $masked = $maskObj->mask($width, $frame, $input->getErrorCorrectionLevel());
3097
                } else {
3098
                    $masked = $maskObj->makeMask($width, $frame, (intval(QR_DEFAULT_MASK) % 8), $input->getErrorCorrectionLevel());
3099
                }
3100
            } else {
3101
                $masked = $maskObj->makeMask($width, $frame, $mask, $input->getErrorCorrectionLevel());
3102
            }
3103
3104
            if ($masked == null) {
3105
                return;
3106
            }
3107
3108
            QRtools::markTime('after_mask');
3109
3110
            $this->version = $version;
3111
            $this->width = $width;
3112
            $this->data = $masked;
3113
3114
            return $this;
3115
        }
3116
3117
        //----------------------------------------------------------------------
3118
        public function encodeInput(QRinput $input)
3119
        {
3120
            return $this->encodeMask($input, -1);
3121
        }
3122
3123
        //----------------------------------------------------------------------
3124
        public function encodeString8bit($string, $version, $level)
3125
        {
3126
            if (string == null) {
0 ignored issues
show
The constant string was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
3127
                throw new Exception('empty string!');
3128
                return;
0 ignored issues
show
return 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
3129
            }
3130
3131
            $input = new QRinput($version, $level);
3132
            if ($input == null) {
3133
                return;
3134
            }
3135
3136
            $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 ignore-call  annotation

3136
            /** @scrutinizer ignore-call */ 
3137
            $ret = $input->append($input, QR_MODE_8, strlen($string), str_split($string));

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.

Loading history...
3137
            if ($ret < 0) {
3138
                unset($input);
3139
3140
                return;
3141
            }
3142
3143
            return $this->encodeInput($input);
3144
        }
3145
3146
        //----------------------------------------------------------------------
3147
        public function encodeString($string, $version, $level, $hint, $casesensitive)
3148
        {
3149
            if ($hint != QR_MODE_8 && $hint != QR_MODE_KANJI) {
3150
                throw new Exception('bad hint');
3151
                return;
0 ignored issues
show
return 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 return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
3152
            }
3153
3154
            $input = new QRinput($version, $level);
3155
            if ($input == null) {
3156
                return;
3157
            }
3158
3159
            $ret = QRsplit::splitStringToQRinput($string, $input, $hint, $casesensitive);
3160
            if ($ret < 0) {
3161
                return;
3162
            }
3163
3164
            return $this->encodeInput($input);
3165
        }
3166
3167
        //----------------------------------------------------------------------
3168
        public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000)
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 ignore-unused  annotation

3168
        public static function png($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, /** @scrutinizer ignore-unused */ $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
3169
        {
3170
            $enc = QRencode::factory($level, $size, $margin, $back_color, $fore_color);
3171
3172
            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 getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
3173
        }
3174
3175
        //----------------------------------------------------------------------
3176
        public static function text($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3177
        {
3178
            $enc = QRencode::factory($level, $size, $margin);
3179
3180
            return $enc->encode($text, $outfile);
3181
        }
3182
3183
        //----------------------------------------------------------------------
3184
        public static function eps($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000, $cmyk = 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 ignore-unused  annotation

3184
        public static function eps($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, /** @scrutinizer ignore-unused */ $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000, $cmyk = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
3185
        {
3186
            $enc = QRencode::factory($level, $size, $margin, $back_color, $fore_color, $cmyk);
3187
3188
            return $enc->encodeEPS($text, $outfile, $saveandprint = false);
0 ignored issues
show
Are you sure the usage of $enc->encodeEPS($text, $... $saveandprint = false) targeting QRencode::encodeEPS() 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 getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
3189
        }
3190
3191
        //----------------------------------------------------------------------
3192
        public static function svg($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000)
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 ignore-unused  annotation

3192
        public static function svg($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4, /** @scrutinizer ignore-unused */ $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
3193
        {
3194
            $enc = QRencode::factory($level, $size, $margin, $back_color, $fore_color);
3195
3196
            return $enc->encodeSVG($text, $outfile, $saveandprint = false);
0 ignored issues
show
Are you sure the usage of $enc->encodeSVG($text, $... $saveandprint = false) targeting QRencode::encodeSVG() 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 getObject() can return nothing but null, so it makes no sense to use the return value.

The reason is most likely that a function or method is imcomplete or has been reduced for debug purposes.

Loading history...
3197
        }
3198
3199
        //----------------------------------------------------------------------
3200
        public static function raw($text, $outfile = false, $level = QR_ECLEVEL_L, $size = 3, $margin = 4)
3201
        {
3202
            $enc = QRencode::factory($level, $size, $margin);
3203
3204
            return $enc->encodeRAW($text, $outfile);
3205
        }
3206
    }
3207
3208
    //##########################################################################
3209
3210
    class FrameFiller
3211
    {
3212
        public $width;
3213
        public $frame;
3214
        public $x;
3215
        public $y;
3216
        public $dir;
3217
        public $bit;
3218
3219
        //----------------------------------------------------------------------
3220
        public function __construct($width, &$frame)
3221
        {
3222
            $this->width = $width;
3223
            $this->frame = $frame;
3224
            $this->x = $width - 1;
3225
            $this->y = $width - 1;
3226
            $this->dir = -1;
3227
            $this->bit = -1;
3228
        }
3229
3230
        //----------------------------------------------------------------------
3231
        public function setFrameAt($at, $val)
3232
        {
3233
            $this->frame[$at['y']][$at['x']] = chr($val);
3234
        }
3235
3236
        //----------------------------------------------------------------------
3237
        public function getFrameAt($at)
3238
        {
3239
            return ord($this->frame[$at['y']][$at['x']]);
3240
        }
3241
3242
        //----------------------------------------------------------------------
3243
        public function next()
3244
        {
3245
            do {
3246
                if ($this->bit == -1) {
3247
                    $this->bit = 0;
3248
3249
                    return ['x'=>$this->x, 'y'=>$this->y];
3250
                }
3251
3252
                $x = $this->x;
3253
                $y = $this->y;
3254
                $w = $this->width;
3255
3256
                if ($this->bit == 0) {
3257
                    $x--;
3258
                    $this->bit++;
3259
                } else {
3260
                    $x++;
3261
                    $y += $this->dir;
3262
                    $this->bit--;
3263
                }
3264
3265
                if ($this->dir < 0) {
3266
                    if ($y < 0) {
3267
                        $y = 0;
3268
                        $x -= 2;
3269
                        $this->dir = 1;
3270
                        if ($x == 6) {
3271
                            $x--;
3272
                            $y = 9;
3273
                        }
3274
                    }
3275
                } else {
3276
                    if ($y == $w) {
3277
                        $y = $w - 1;
3278
                        $x -= 2;
3279
                        $this->dir = -1;
3280
                        if ($x == 6) {
3281
                            $x--;
3282
                            $y -= 8;
3283
                        }
3284
                    }
3285
                }
3286
                if ($x < 0 || $y < 0) {
3287
                    return;
3288
                }
3289
3290
                $this->x = $x;
3291
                $this->y = $y;
3292
            } while (ord($this->frame[$y][$x]) & 0x80);
3293
3294
            return ['x'=>$x, 'y'=>$y];
3295
        }
3296
    }
3297
3298
    //##########################################################################
3299
3300
    class QRencode
3301
    {
3302
        public $casesensitive = true;
3303
        public $eightbit = false;
3304
3305
        public $version = 0;
3306
        public $size = 3;
3307
        public $margin = 4;
3308
        public $back_color = 0xFFFFFF;
3309
        public $fore_color = 0x000000;
3310
3311
        public $structured = 0; // not supported yet
3312
3313
        public $level = QR_ECLEVEL_L;
3314
        public $hint = QR_MODE_8;
3315
3316
        //----------------------------------------------------------------------
3317
        public static function factory($level = QR_ECLEVEL_L, $size = 3, $margin = 4, $back_color = 0xFFFFFF, $fore_color = 0x000000, $cmyk = false)
3318
        {
3319
            $enc = new self();
3320
            $enc->size = $size;
3321
            $enc->margin = $margin;
3322
            $enc->fore_color = $fore_color;
3323
            $enc->back_color = $back_color;
3324
            $enc->cmyk = $cmyk;
0 ignored issues
show
Bug Best Practice introduced by
The property cmyk does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
3325
3326
            switch ($level.'') {
3327
                case '0':
3328
                case '1':
3329
                case '2':
3330
                case '3':
3331
                        $enc->level = $level;
3332
                    break;
3333
                case 'l':
3334
                case 'L':
3335
                        $enc->level = QR_ECLEVEL_L;
3336
                    break;
3337
                case 'm':
3338
                case 'M':
3339
                        $enc->level = QR_ECLEVEL_M;
3340
                    break;
3341
                case 'q':
3342
                case 'Q':
3343
                        $enc->level = QR_ECLEVEL_Q;
3344
                    break;
3345
                case 'h':
3346
                case 'H':
3347
                        $enc->level = QR_ECLEVEL_H;
3348
                    break;
3349
            }
3350
3351
            return $enc;
3352
        }
3353
3354
        //----------------------------------------------------------------------
3355
        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 ignore-unused  annotation

3355
        public function encodeRAW($intext, /** @scrutinizer ignore-unused */ $outfile = false)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
3356
        {
3357
            $code = new QRcode();
3358
3359
            if ($this->eightbit) {
3360
                $code->encodeString8bit($intext, $this->version, $this->level);
3361
            } else {
3362
                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3363
            }
3364
3365
            return $code->data;
3366
        }
3367
3368
        //----------------------------------------------------------------------
3369
        public function encode($intext, $outfile = false)
3370
        {
3371
            $code = new QRcode();
3372
3373
            if ($this->eightbit) {
3374
                $code->encodeString8bit($intext, $this->version, $this->level);
3375
            } else {
3376
                $code->encodeString($intext, $this->version, $this->level, $this->hint, $this->casesensitive);
3377
            }
3378
3379
            QRtools::markTime('after_encode');
3380
3381
            if ($outfile !== false) {
3382
                file_put_contents($outfile, implode("\n", QRtools::binarize($code->data)));
3383
            } else {
3384
                return QRtools::binarize($code->data);
3385
            }
3386
        }
3387
3388
        //----------------------------------------------------------------------
3389
        public function encodePNG($intext, $outfile = false, $saveandprint = false)
3390
        {
3391
            try {
3392
                ob_start();
3393
                $tab = $this->encode($intext);
3394
                $err = ob_get_contents();
3395
                ob_end_clean();
3396
3397
                if ($err != '') {
3398
                    QRtools::log($outfile, $err);
3399
                }
3400
3401
                $maxSize = (int) (QR_PNG_MAXIMUM_SIZE / (count($tab) + 2 * $this->margin));
3402
3403
                QRimage::png($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin, $saveandprint, $this->back_color, $this->fore_color);
3404
            } catch (Exception $e) {
3405
                QRtools::log($outfile, $e->getMessage());
3406
            }
3407
        }
3408
3409
        //----------------------------------------------------------------------
3410
        public function encodeEPS($intext, $outfile = false, $saveandprint = false)
3411
        {
3412
            try {
3413
                ob_start();
3414
                $tab = $this->encode($intext);
3415
                $err = ob_get_contents();
3416
                ob_end_clean();
3417
3418
                if ($err != '') {
3419
                    QRtools::log($outfile, $err);
3420
                }
3421
3422
                $maxSize = (int) (QR_PNG_MAXIMUM_SIZE / (count($tab) + 2 * $this->margin));
3423
3424
                QRvect::eps($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin, $saveandprint, $this->back_color, $this->fore_color, $this->cmyk);
3425
            } catch (Exception $e) {
3426
                QRtools::log($outfile, $e->getMessage());
3427
            }
3428
        }
3429
3430
        //----------------------------------------------------------------------
3431
        public function encodeSVG($intext, $outfile = false, $saveandprint = false)
3432
        {
3433
            try {
3434
                ob_start();
3435
                $tab = $this->encode($intext);
3436
                $err = ob_get_contents();
3437
                ob_end_clean();
3438
3439
                if ($err != '') {
3440
                    QRtools::log($outfile, $err);
3441
                }
3442
3443
                $maxSize = (int) (QR_PNG_MAXIMUM_SIZE / (count($tab) + 2 * $this->margin));
3444
3445
                QRvect::svg($tab, $outfile, min(max(1, $this->size), $maxSize), $this->margin, $saveandprint, $this->back_color, $this->fore_color);
3446
            } catch (Exception $e) {
3447
                QRtools::log($outfile, $e->getMessage());
3448
            }
3449
        }
3450
    }
3451
3452
//---- qrvect.php -----------------------------
3453
3454
/*
3455
 * PHP QR Code encoder
3456
 *
3457
 * Image output of code using GD2
3458
 *
3459
 * PHP QR Code is distributed under LGPL 3
3460
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
3461
 *
3462
 * This library is free software; you can redistribute it and/or
3463
 * modify it under the terms of the GNU Lesser General Public
3464
 * License as published by the Free Software Foundation; either
3465
 * version 3 of the License, or any later version.
3466
 *
3467
 * This library is distributed in the hope that it will be useful,
3468
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3469
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
3470
 * Lesser General Public License for more details.
3471
 *
3472
 * You should have received a copy of the GNU Lesser General Public
3473
 * License along with this library; if not, write to the Free Software
3474
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
3475
 */
3476
3477
    define('QR_VECT', true);
3478
3479
    class QRvect
3480
    {
3481
        //----------------------------------------------------------------------
3482
        public static function eps($frame, $filename = false, $pixelPerPoint = 4, $outerFrame = 4, $saveandprint = false, $back_color = 0xFFFFFF, $fore_color = 0x000000, $cmyk = false)
3483
        {
3484
            $vect = self::vectEPS($frame, $pixelPerPoint, $outerFrame, $back_color, $fore_color, $cmyk);
3485
3486
            if ($filename === false) {
3487
                header('Content-Type: application/postscript');
3488
                header('Content-Disposition: filename="qrcode.eps"');
3489
                echo $vect;
3490
            } else {
3491
                if ($saveandprint === true) {
3492
                    QRtools::save($vect, $filename);
3493
                    header('Content-Type: application/postscript');
3494
                    header('Content-Disposition: filename="qrcode.eps"');
3495
                    echo $vect;
3496
                } else {
3497
                    QRtools::save($vect, $filename);
3498
                }
3499
            }
3500
        }
3501
3502
        //----------------------------------------------------------------------
3503
        private static function vectEPS($frame, $pixelPerPoint = 4, $outerFrame = 4, $back_color = 0xFFFFFF, $fore_color = 0x000000, $cmyk = false)
3504
        {
3505
            $h = count($frame);
3506
            $w = strlen($frame[0]);
3507
3508
            $imgW = $w + 2 * $outerFrame;
3509
            $imgH = $h + 2 * $outerFrame;
3510
3511
            if ($cmyk) {
3512
                // convert color value into decimal eps format
3513
                $c = round((($fore_color & 0xFF000000) >> 16) / 255, 5);
3514
                $m = round((($fore_color & 0x00FF0000) >> 16) / 255, 5);
3515
                $y = round((($fore_color & 0x0000FF00) >> 8) / 255, 5);
3516
                $k = round(($fore_color & 0x000000FF) / 255, 5);
3517
                $fore_color_string = $c.' '.$m.' '.$y.' '.$k.' setcmykcolor'."\n";
3518
3519
                // convert color value into decimal eps format
3520
                $c = round((($back_color & 0xFF000000) >> 16) / 255, 5);
3521
                $m = round((($back_color & 0x00FF0000) >> 16) / 255, 5);
3522
                $y = round((($back_color & 0x0000FF00) >> 8) / 255, 5);
3523
                $k = round(($back_color & 0x000000FF) / 255, 5);
3524
                $back_color_string = $c.' '.$m.' '.$y.' '.$k.' setcmykcolor'."\n";
3525
            } else {
3526
                // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
3527
                $r = round((($fore_color & 0xFF0000) >> 16) / 255, 5);
3528
                $b = round((($fore_color & 0x00FF00) >> 8) / 255, 5);
3529
                $g = round(($fore_color & 0x0000FF) / 255, 5);
3530
                $fore_color_string = $r.' '.$b.' '.$g.' setrgbcolor'."\n";
3531
3532
                // convert a hexadecimal color code into decimal eps format (green = 0 1 0, blue = 0 0 1, ...)
3533
                $r = round((($back_color & 0xFF0000) >> 16) / 255, 5);
3534
                $b = round((($back_color & 0x00FF00) >> 8) / 255, 5);
3535
                $g = round(($back_color & 0x0000FF) / 255, 5);
3536
                $back_color_string = $r.' '.$b.' '.$g.' setrgbcolor'."\n";
3537
            }
3538
3539
            $output =
3540
            '%!PS-Adobe EPSF-3.0'."\n".
3541
            '%%Creator: PHPQrcodeLib'."\n".
3542
            '%%Title: QRcode'."\n".
3543
            '%%CreationDate: '.date('Y-m-d')."\n".
3544
            '%%DocumentData: Clean7Bit'."\n".
3545
            '%%LanguageLevel: 2'."\n".
3546
            '%%Pages: 1'."\n".
3547
            '%%BoundingBox: 0 0 '.$imgW * $pixelPerPoint.' '.$imgH * $pixelPerPoint."\n";
3548
3549
            // set the scale
3550
            $output .= $pixelPerPoint.' '.$pixelPerPoint.' scale'."\n";
3551
            // position the center of the coordinate system
3552
3553
            $output .= $outerFrame.' '.$outerFrame.' translate'."\n";
3554
3555
            // redefine the 'rectfill' operator to shorten the syntax
3556
            $output .= '/F { rectfill } def'."\n";
3557
3558
            // set the symbol color
3559
            $output .= $back_color_string;
3560
            $output .= '-'.$outerFrame.' -'.$outerFrame.' '.($w + 2 * $outerFrame).' '.($h + 2 * $outerFrame).' F'."\n";
3561
3562
            // set the symbol color
3563
            $output .= $fore_color_string;
3564
3565
            // Convert the matrix into pixels
3566
3567
            for ($i = 0; $i < $h; $i++) {
3568
                for ($j = 0; $j < $w; $j++) {
3569
                    if ($frame[$i][$j] == '1') {
3570
                        $y = $h - 1 - $i;
3571
                        $x = $j;
3572
                        $output .= $x.' '.$y.' 1 1 F'."\n";
3573
                    }
3574
                }
3575
            }
3576
3577
            $output .= '%%EOF';
3578
3579
            return $output;
3580
        }
3581
3582
        //----------------------------------------------------------------------
3583
        public static function svg($frame, $filename, $pixelPerPoint, $outerFrame, $saveandprint, $back_color, $fore_color)
3584
        {
3585
            $vect = self::vectSVG($frame, $pixelPerPoint, $outerFrame, $back_color, $fore_color);
3586
3587
            if ($filename === false) {
3588
                header('Content-Type: image/svg+xml');
3589
                //header('Content-Disposition: attachment, filename="qrcode.svg"');
3590
                echo $vect;
3591
            } else {
3592
                if ($saveandprint === true) {
3593
                    QRtools::save($vect, $filename);
3594
                    header('Content-Type: image/svg+xml');
3595
                    //header('Content-Disposition: filename="'.$filename.'"');
3596
                    echo $vect;
3597
                } else {
3598
                    QRtools::save($vect, $filename);
3599
                }
3600
            }
3601
        }
3602
3603
        //----------------------------------------------------------------------
3604
        private static function vectSVG($frame, $pixelPerPoint = 4, $outerFrame = 4, $back_color = 0xFFFFFF, $fore_color = 0x000000)
3605
        {
3606
            $h = count($frame);
3607
            $w = strlen($frame[0]);
3608
3609
            $imgW = $w + 2 * $outerFrame;
3610
            $imgH = $h + 2 * $outerFrame;
3611
3612
            $output =
0 ignored issues
show
The assignment to $output is dead and can be removed.
Loading history...
3613
            '<?xml version="1.0" encoding="utf-8"?>'."\n".
3614
            '<svg version="1.1" baseProfile="full"  width="'.$imgW * $pixelPerPoint.'" height="'.$imgH * $pixelPerPoint.'" viewBox="0 0 '.$imgW * $pixelPerPoint.' '.$imgH * $pixelPerPoint.'"
3615
             xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events">'."\n".
3616
            '<desc></desc>'."\n";
3617
3618
            $output =
3619
            '<?xml version="1.0" encoding="utf-8"?>'."\n".
3620
            '<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">'."\n".
3621
            '<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" xmlns:xlink="http://www.w3.org/1999/xlink" width="'.$imgW * $pixelPerPoint.'" height="'.$imgH * $pixelPerPoint.'" viewBox="0 0 '.$imgW * $pixelPerPoint.' '.$imgH * $pixelPerPoint.'">'."\n".
3622
            '<desc></desc>'."\n";
3623
3624
            if (!empty($back_color)) {
3625
                $backgroundcolor = str_pad(dechex($back_color), 6, '0', STR_PAD_LEFT);
3626
                $output .= '<rect width="'.$imgW * $pixelPerPoint.'" height="'.$imgH * $pixelPerPoint.'" fill="#'.$backgroundcolor.'" cx="0" cy="0" />'."\n";
3627
            }
3628
3629
            $output .=
3630
            '<defs>'."\n".
3631
            '<rect id="p" width="'.$pixelPerPoint.'" height="'.$pixelPerPoint.'" />'."\n".
3632
            '</defs>'."\n".
3633
            '<g fill="#'.str_pad(dechex($fore_color), 6, '0', STR_PAD_LEFT).'">'."\n";
3634
3635
            // Convert the matrix into pixels
3636
3637
            for ($i = 0; $i < $h; $i++) {
3638
                for ($j = 0; $j < $w; $j++) {
3639
                    if ($frame[$i][$j] == '1') {
3640
                        $y = ($i + $outerFrame) * $pixelPerPoint;
3641
                        $x = ($j + $outerFrame) * $pixelPerPoint;
3642
                        $output .= '<use x="'.$x.'" y="'.$y.'" xlink:href="#p" />'."\n";
3643
                    }
3644
                }
3645
            }
3646
            $output .=
3647
            '</g>'."\n".
3648
            '</svg>';
3649
3650
            return $output;
3651
        }
3652
    }
3653