survey_seahorse

Software Engineering Project - Fall 2018
Log | Files | Refs | README

qrsplit.php (11381B)


      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 <fukuchi@megaui.net>
      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             return ((ord($str[$pos]) >= ord('0'))&&(ord($str[$pos]) <= ord('9')));
     54         }
     55         
     56         //----------------------------------------------------------------------
     57         public static function isalnumat($str, $pos)
     58         {
     59             if ($pos >= strlen($str))
     60                 return false;
     61                 
     62             return (QRinput::lookAnTable(ord($str[$pos])) >= 0);
     63         }
     64 
     65         //----------------------------------------------------------------------
     66         public function identifyMode($pos)
     67         {
     68             if ($pos >= strlen($this->dataStr)) 
     69                 return QR_MODE_NUL;
     70                 
     71             $c = $this->dataStr[$pos];
     72             
     73             if(self::isdigitat($this->dataStr, $pos)) {
     74                 return QR_MODE_NUM;
     75             } else if(self::isalnumat($this->dataStr, $pos)) {
     76                 return QR_MODE_AN;
     77             } else if($this->modeHint == QR_MODE_KANJI) {
     78             
     79                 if ($pos+1 < strlen($this->dataStr)) 
     80                 {
     81                     $d = $this->dataStr[$pos+1];
     82                     $word = (ord($c) << 8) | ord($d);
     83                     if(($word >= 0x8140 && $word <= 0x9ffc) || ($word >= 0xe040 && $word <= 0xebbf)) {
     84                         return QR_MODE_KANJI;
     85                     }
     86                 }
     87             }
     88 
     89             return QR_MODE_8;
     90         } 
     91         
     92         //----------------------------------------------------------------------
     93         public function eatNum()
     94         {
     95             $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
     96 
     97             $p = 0;
     98             while(self::isdigitat($this->dataStr, $p)) {
     99                 $p++;
    100             }
    101             
    102             $run = $p;
    103             $mode = $this->identifyMode($p);
    104             
    105             if($mode == QR_MODE_8) {
    106                 $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
    107                      + QRinput::estimateBitsMode8(1)         // + 4 + l8
    108                      - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
    109                 if($dif > 0) {
    110                     return $this->eat8();
    111                 }
    112             }
    113             if($mode == QR_MODE_AN) {
    114                 $dif = QRinput::estimateBitsModeNum($run) + 4 + $ln
    115                      + QRinput::estimateBitsModeAn(1)        // + 4 + la
    116                      - QRinput::estimateBitsModeAn($run + 1);// - 4 - la
    117                 if($dif > 0) {
    118                     return $this->eatAn();
    119                 }
    120             }
    121             
    122             $ret = $this->input->append(QR_MODE_NUM, $run, str_split($this->dataStr));
    123             if($ret < 0)
    124                 return -1;
    125 
    126             return $run;
    127         }
    128         
    129         //----------------------------------------------------------------------
    130         public function eatAn()
    131         {
    132             $la = QRspec::lengthIndicator(QR_MODE_AN,  $this->input->getVersion());
    133             $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
    134 
    135             $p = 0;
    136             
    137             while(self::isalnumat($this->dataStr, $p)) {
    138                 if(self::isdigitat($this->dataStr, $p)) {
    139                     $q = $p;
    140                     while(self::isdigitat($this->dataStr, $q)) {
    141                         $q++;
    142                     }
    143                     
    144                     $dif = QRinput::estimateBitsModeAn($p) // + 4 + la
    145                          + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
    146                          - QRinput::estimateBitsModeAn($q); // - 4 - la
    147                          
    148                     if($dif < 0) {
    149                         break;
    150                     } else {
    151                         $p = $q;
    152                     }
    153                 } else {
    154                     $p++;
    155                 }
    156             }
    157 
    158             $run = $p;
    159 
    160             if(!self::isalnumat($this->dataStr, $p)) {
    161                 $dif = QRinput::estimateBitsModeAn($run) + 4 + $la
    162                      + QRinput::estimateBitsMode8(1) // + 4 + l8
    163                       - QRinput::estimateBitsMode8($run + 1); // - 4 - l8
    164                 if($dif > 0) {
    165                     return $this->eat8();
    166                 }
    167             }
    168 
    169             $ret = $this->input->append(QR_MODE_AN, $run, str_split($this->dataStr));
    170             if($ret < 0)
    171                 return -1;
    172 
    173             return $run;
    174         }
    175         
    176         //----------------------------------------------------------------------
    177         public function eatKanji()
    178         {
    179             $p = 0;
    180             
    181             while($this->identifyMode($p) == QR_MODE_KANJI) {
    182                 $p += 2;
    183             }
    184             
    185             $ret = $this->input->append(QR_MODE_KANJI, $p, str_split($this->dataStr));
    186             if($ret < 0)
    187                 return -1;
    188 
    189             return $run;
    190         }
    191 
    192         //----------------------------------------------------------------------
    193         public function eat8()
    194         {
    195             $la = QRspec::lengthIndicator(QR_MODE_AN, $this->input->getVersion());
    196             $ln = QRspec::lengthIndicator(QR_MODE_NUM, $this->input->getVersion());
    197 
    198             $p = 1;
    199             $dataStrLen = strlen($this->dataStr);
    200             
    201             while($p < $dataStrLen) {
    202                 
    203                 $mode = $this->identifyMode($p);
    204                 if($mode == QR_MODE_KANJI) {
    205                     break;
    206                 }
    207                 if($mode == QR_MODE_NUM) {
    208                     $q = $p;
    209                     while(self::isdigitat($this->dataStr, $q)) {
    210                         $q++;
    211                     }
    212                     $dif = QRinput::estimateBitsMode8($p) // + 4 + l8
    213                          + QRinput::estimateBitsModeNum($q - $p) + 4 + $ln
    214                          - QRinput::estimateBitsMode8($q); // - 4 - l8
    215                     if($dif < 0) {
    216                         break;
    217                     } else {
    218                         $p = $q;
    219                     }
    220                 } else if($mode == QR_MODE_AN) {
    221                     $q = $p;
    222                     while(self::isalnumat($this->dataStr, $q)) {
    223                         $q++;
    224                     }
    225                     $dif = QRinput::estimateBitsMode8($p)  // + 4 + l8
    226                          + QRinput::estimateBitsModeAn($q - $p) + 4 + $la
    227                          - QRinput::estimateBitsMode8($q); // - 4 - l8
    228                     if($dif < 0) {
    229                         break;
    230                     } else {
    231                         $p = $q;
    232                     }
    233                 } else {
    234                     $p++;
    235                 }
    236             }
    237 
    238             $run = $p;
    239             $ret = $this->input->append(QR_MODE_8, $run, str_split($this->dataStr));
    240             
    241             if($ret < 0)
    242                 return -1;
    243 
    244             return $run;
    245         }
    246 
    247         //----------------------------------------------------------------------
    248         public function splitString()
    249         {
    250             while (strlen($this->dataStr) > 0)
    251             {
    252                 if($this->dataStr == '')
    253                     return 0;
    254 
    255                 $mode = $this->identifyMode(0);
    256                 
    257                 switch ($mode) {
    258                     case QR_MODE_NUM: $length = $this->eatNum(); break;
    259                     case QR_MODE_AN:  $length = $this->eatAn(); break;
    260                     case QR_MODE_KANJI:
    261                         if ($hint == QR_MODE_KANJI)
    262                                 $length = $this->eatKanji();
    263                         else    $length = $this->eat8();
    264                         break;
    265                     default: $length = $this->eat8(); break;
    266                 
    267                 }
    268 
    269                 if($length == 0) return 0;
    270                 if($length < 0)  return -1;
    271                 
    272                 $this->dataStr = substr($this->dataStr, $length);
    273             }
    274         }
    275 
    276         //----------------------------------------------------------------------
    277         public function toUpper()
    278         {
    279             $stringLen = strlen($this->dataStr);
    280             $p = 0;
    281             
    282             while ($p<$stringLen) {
    283                 $mode = self::identifyMode(substr($this->dataStr, $p), $this->modeHint);
    284                 if($mode == QR_MODE_KANJI) {
    285                     $p += 2;
    286                 } else {
    287                     if (ord($this->dataStr[$p]) >= ord('a') && ord($this->dataStr[$p]) <= ord('z')) {
    288                         $this->dataStr[$p] = chr(ord($this->dataStr[$p]) - 32);
    289                     }
    290                     $p++;
    291                 }
    292             }
    293 
    294             return $this->dataStr;
    295         }
    296 
    297         //----------------------------------------------------------------------
    298         public static function splitStringToQRinput($string, QRinput $input, $modeHint, $casesensitive = true)
    299         {
    300             if(is_null($string) || $string == '\0' || $string == '') {
    301                 throw new Exception('empty string!!!');
    302             }
    303 
    304             $split = new QRsplit($string, $input, $modeHint);
    305             
    306             if(!$casesensitive)
    307                 $split->toUpper();
    308                 
    309             return $split->splitString();
    310         }
    311     }