Issues (1270)

lib/phpqrcode/qrsplit.php (1 issue)

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

297
                /** @scrutinizer ignore-call */ 
298
                $mode = self::identifyMode(substr($this->dataStr, $p));
Loading history...
298
                if ($mode == QR_MODE_KANJI) {
299
                    $p += 2;
300
                } else {
301
                    if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
302
                        $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
303
                    }
304
                    $p++;
305
                }
306
            }
307
308
            return $this->dataStr;
309
        }
310
311
        //----------------------------------------------------------------------
312
        public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
313
        {
314
            if (is_null($string) || $string == '\0' || $string == '') {
315
                throw new Exception('empty string!!!');
316
            }
317
318
            $split = new QRsplit($string, $input, $modeHint);
319
            
320
            if (!$casesensitive) {
321
                            $split->toUpper();
322
            }
323
                
324
            return $split->splitString();
325
        }
326
    }
327