SproutCMS

This is the code documentation for the SproutCMS project

source of /sprout/Helpers/phpqrcode/qrsplit.php

  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 $ret;
  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 ($mode == 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));
  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. }