Your IP : 10.10.0.253


Current Path : /var/www/libraries/foundry/libraries/qrcode/
Upload File :
Current File : /var/www/libraries/foundry/libraries/qrcode/qrinput.php

<?php
/**
* @package      Foundry
* @copyright    Copyright (C) Stack Ideas Sdn Bhd. All rights reserved.
* @license      GNU/GPL, see LICENSE.php
* Foundry is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* See COPYRIGHT.php for copyright notices and details.
*/
defined('_JEXEC') or die('Unauthorized Access');

/*
 * PHP QR Code encoder
 *
 * Input encoding class
 *
 * Based on libqrencode C library distributed under LGPL 2.1
 * Copyright (C) 2006, 2007, 2008, 2009 Kentaro Fukuchi <fukuchi@megaui.net>
 *
 * PHP QR Code is distributed under LGPL 3
 * Copyright (C) 2010 Dominik Dzienia <deltalab at poczta dot fm>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 */
 
	define('STRUCTURE_HEADER_BITS',  20);
	define('MAX_STRUCTURED_SYMBOLS', 16);

	class QRinputItem {
	
		public $mode;
		public $size;
		public $data;
		public $bstream;

		public function __construct($mode, $size, $data, $bstream = null) 
		{
			$setData = array_slice($data, 0, $size);
			
			if (count($setData) < $size) {
				$setData = array_merge($setData, array_fill(0,$size-count($setData),0));
			}
		
			if(!QRinput::check($mode, $size, $setData)) {
				throw new Exception('Error m:'.$mode.',s:'.$size.',d:'.join(',',$setData));
				return null;
			}
			
			$this->mode = $mode;
			$this->size = $size;
			$this->data = $setData;
			$this->bstream = $bstream;
		}
		
		//----------------------------------------------------------------------
		public function encodeModeNum($version)
		{
			try {
			
				$words = (int)($this->size / 3);
				$bs = new QRbitstream();
				
				$val = 0x1;
				$bs->appendNum(4, $val);
				$bs->appendNum(QRspec::lengthIndicator(QR_MODE_NUM, $version), $this->size);

				for($i=0; $i<$words; $i++) {
					$val  = (ord($this->data[$i*3  ]) - ord('0')) * 100;
					$val += (ord($this->data[$i*3+1]) - ord('0')) * 10;
					$val += (ord($this->data[$i*3+2]) - ord('0'));
					$bs->appendNum(10, $val);
				}

				if($this->size - $words * 3 == 1) {
					$val = ord($this->data[$words*3]) - ord('0');
					$bs->appendNum(4, $val);
				} else if($this->size - $words * 3 == 2) {
					$val  = (ord($this->data[$words*3  ]) - ord('0')) * 10;
					$val += (ord($this->data[$words*3+1]) - ord('0'));
					$bs->appendNum(7, $val);
				}

				$this->bstream = $bs;
				return 0;
				
			} catch (Exception $e) {
				return -1;
			}
		}
		
		//----------------------------------------------------------------------
		public function encodeModeAn($version)
		{
			try {
				$words = (int)($this->size / 2);
				$bs = new QRbitstream();
				
				$bs->appendNum(4, 0x02);
				$bs->appendNum(QRspec::lengthIndicator(QR_MODE_AN, $version), $this->size);

				for($i=0; $i<$words; $i++) {
					$val  = (int)QRinput::lookAnTable(ord($this->data[$i*2  ])) * 45;
					$val += (int)QRinput::lookAnTable(ord($this->data[$i*2+1]));

					$bs->appendNum(11, $val);
				}

				if($this->size & 1) {
					$val = QRinput::lookAnTable(ord($this->data[$words * 2]));
					$bs->appendNum(6, $val);
				}
		
				$this->bstream = $bs;
				return 0;
			
			} catch (Exception $e) {
				return -1;
			}
		}
		
		//----------------------------------------------------------------------
		public function encodeMode8($version)
		{
			try {
				$bs = new QRbitstream();

				$bs->appendNum(4, 0x4);
				$bs->appendNum(QRspec::lengthIndicator(QR_MODE_8, $version), $this->size);

				for($i=0; $i<$this->size; $i++) {
					$bs->appendNum(8, ord($this->data[$i]));
				}

				$this->bstream = $bs;
				return 0;
			
			} catch (Exception $e) {
				return -1;
			}
		}
		
		//----------------------------------------------------------------------
		public function encodeModeKanji($version)
		{
			try {

				$bs = new QRbitrtream();
				
				$bs->appendNum(4, 0x8);
				$bs->appendNum(QRspec::lengthIndicator(QR_MODE_KANJI, $version), (int)($this->size / 2));

				for($i=0; $i<$this->size; $i+=2) {
					$val = (ord($this->data[$i]) << 8) | ord($this->data[$i+1]);
					if($val <= 0x9ffc) {
						$val -= 0x8140;
					} else {
						$val -= 0xc140;
					}
					
					$h = ($val >> 8) * 0xc0;
					$val = ($val & 0xff) + $h;

					$bs->appendNum(13, $val);
				}

				$this->bstream = $bs;
				return 0;
			
			} catch (Exception $e) {
				return -1;
			}
		}

		//----------------------------------------------------------------------
		public function encodeModeStructure()
		{
			try {
				$bs =  new QRbitstream();
				
				$bs->appendNum(4, 0x03);
				$bs->appendNum(4, ord($this->data[1]) - 1);
				$bs->appendNum(4, ord($this->data[0]) - 1);
				$bs->appendNum(8, ord($this->data[2]));

				$this->bstream = $bs;
				return 0;
			
			} catch (Exception $e) {
				return -1;
			}
		}
		
		//----------------------------------------------------------------------
		public function estimateBitStreamSizeOfEntry($version)
		{
			$bits = 0;

			if($version == 0) 
				$version = 1;

			switch($this->mode) {
				case QR_MODE_NUM:        $bits = QRinput::estimateBitsModeNum($this->size);    break;
				case QR_MODE_AN:        $bits = QRinput::estimateBitsModeAn($this->size);    break;
				case QR_MODE_8:            $bits = QRinput::estimateBitsMode8($this->size);    break;
				case QR_MODE_KANJI:        $bits = QRinput::estimateBitsModeKanji($this->size);break;
				case QR_MODE_STRUCTURE:    return STRUCTURE_HEADER_BITS;            
				default:
					return 0;
			}

			$l = QRspec::lengthIndicator($this->mode, $version);
			$m = 1 << $l;
			$num = (int)(($this->size + $m - 1) / $m);

			$bits += $num * (4 + $l);

			return $bits;
		}
		
		//----------------------------------------------------------------------
		public function encodeBitStream($version)
		{
			try {
			
				unset($this->bstream);
				$words = QRspec::maximumWords($this->mode, $version);
				
				if($this->size > $words) {
				
					$st1 = new QRinputItem($this->mode, $words, $this->data);
					$st2 = new QRinputItem($this->mode, $this->size - $words, array_slice($this->data, $words));

					$st1->encodeBitStream($version);
					$st2->encodeBitStream($version);
					
					$this->bstream = new QRbitstream();
					$this->bstream->append($st1->bstream);
					$this->bstream->append($st2->bstream);
					
					unset($st1);
					unset($st2);
					
				} else {
					
					$ret = 0;
					
					switch($this->mode) {
						case QR_MODE_NUM:        $ret = $this->encodeModeNum($version);    break;
						case QR_MODE_AN:        $ret = $this->encodeModeAn($version);    break;
						case QR_MODE_8:            $ret = $this->encodeMode8($version);    break;
						case QR_MODE_KANJI:        $ret = $this->encodeModeKanji($version);break;
						case QR_MODE_STRUCTURE:    $ret = $this->encodeModeStructure();    break;
						
						default:
							break;
					}
					
					if($ret < 0)
						return -1;
				}

				return $this->bstream->size();
			
			} catch (Exception $e) {
				return -1;
			}
		}
	};
	
	//##########################################################################

	class QRinput {

		public $items;
		
		private $version;
		private $level;
		
		//----------------------------------------------------------------------
		public function __construct($version = 0, $level = QR_ECLEVEL_L)
		{
			if ($version < 0 || $version > QRSPEC_VERSION_MAX || $level > QR_ECLEVEL_H) {
				throw new Exception('Invalid version no');
				return NULL;
			}
			
			$this->version = $version;
			$this->level = $level;
		}
		
		//----------------------------------------------------------------------
		public function getVersion()
		{
			return $this->version;
		}
		
		//----------------------------------------------------------------------
		public function setVersion($version)
		{
			if($version < 0 || $version > QRSPEC_VERSION_MAX) {
				throw new Exception('Invalid version no');
				return -1;
			}

			$this->version = $version;

			return 0;
		}
		
		//----------------------------------------------------------------------
		public function getErrorCorrectionLevel()
		{
			return $this->level;
		}

		//----------------------------------------------------------------------
		public function setErrorCorrectionLevel($level)
		{
			if($level > QR_ECLEVEL_H) {
				throw new Exception('Invalid ECLEVEL');
				return -1;
			}

			$this->level = $level;

			return 0;
		}
		
		//----------------------------------------------------------------------
		public function appendEntry(QRinputItem $entry)
		{
			$this->items[] = $entry;
		}
		
		//----------------------------------------------------------------------
		public function append($mode, $size, $data)
		{
			try {
				$entry = new QRinputItem($mode, $size, $data);
				$this->items[] = $entry;
				return 0;
			} catch (Exception $e) {
				return -1;
			}
		}
		
		//----------------------------------------------------------------------
		
		public function insertStructuredAppendHeader($size, $index, $parity)
		{
			if( $size > MAX_STRUCTURED_SYMBOLS ) {
				throw new Exception('insertStructuredAppendHeader wrong size');
			}
			
			if( $index <= 0 || $index > MAX_STRUCTURED_SYMBOLS ) {
				throw new Exception('insertStructuredAppendHeader wrong index');
			}

			$buf = array($size, $index, $parity);
			
			try {
				$entry = new QRinputItem(QR_MODE_STRUCTURE, 3, buf);
				array_unshift($this->items, $entry);
				return 0;
			} catch (Exception $e) {
				return -1;
			}
		}

		//----------------------------------------------------------------------
		public function calcParity()
		{
			$parity = 0;
			
			foreach($this->items as $item) {
				if($item->mode != QR_MODE_STRUCTURE) {
					for($i=$item->size-1; $i>=0; $i--) {
						$parity ^= $item->data[$i];
					}
				}
			}

			return $parity;
		}
		
		//----------------------------------------------------------------------
		public static function checkModeNum($size, $data)
		{
			for($i=0; $i<$size; $i++) {
				if((ord($data[$i]) < ord('0')) || (ord($data[$i]) > ord('9'))){
					return false;
				}
			}

			return true;
		}

		//----------------------------------------------------------------------
		public static function estimateBitsModeNum($size)
		{
			$w = (int)$size / 3;
			$bits = $w * 10;
			
			switch($size - $w * 3) {
				case 1:
					$bits += 4;
					break;
				case 2:
					$bits += 7;
					break;
				default:
					break;
			}

			return $bits;
		}
		
		//----------------------------------------------------------------------
		public static $anTable = array(
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			36, -1, -1, -1, 37, 38, -1, -1, -1, -1, 39, 40, -1, 41, 42, 43,
			 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 44, -1, -1, -1, -1, -1,
			-1, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
			25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
			-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
		);
		
		//----------------------------------------------------------------------
		public static function lookAnTable($c)
		{
			return (($c > 127)?-1:self::$anTable[$c]);
		}
		
		//----------------------------------------------------------------------
		public static function checkModeAn($size, $data)
		{
			for($i=0; $i<$size; $i++) {
				if (self::lookAnTable(ord($data[$i])) == -1) {
					return false;
				}
			}

			return true;
		}
		
		//----------------------------------------------------------------------
		public static function estimateBitsModeAn($size)
		{
			$w = (int)($size / 2);
			$bits = $w * 11;
			
			if($size & 1) {
				$bits += 6;
			}

			return $bits;
		}
	
		//----------------------------------------------------------------------
		public static function estimateBitsMode8($size)
		{
			return $size * 8;
		}
		
		//----------------------------------------------------------------------
		public function estimateBitsModeKanji($size)
		{
			return (int)(($size / 2) * 13);
		}
		
		//----------------------------------------------------------------------
		public static function checkModeKanji($size, $data)
		{
			if($size & 1)
				return false;

			for($i=0; $i<$size; $i+=2) {
				$val = (ord($data[$i]) << 8) | ord($data[$i+1]);
				if( $val < 0x8140 
				|| ($val > 0x9ffc && $val < 0xe040) 
				|| $val > 0xebbf) {
					return false;
				}
			}

			return true;
		}

		/***********************************************************************
		 * Validation
		 **********************************************************************/

		public static function check($mode, $size, $data)
		{
			if($size <= 0) 
				return false;

			switch($mode) {
				case QR_MODE_NUM:       return self::checkModeNum($size, $data);   break;
				case QR_MODE_AN:        return self::checkModeAn($size, $data);    break;
				case QR_MODE_KANJI:     return self::checkModeKanji($size, $data); break;
				case QR_MODE_8:         return true; break;
				case QR_MODE_STRUCTURE: return true; break;
				
				default:
					break;
			}

			return false;
		}
		
		
		//----------------------------------------------------------------------
		public function estimateBitStreamSize($version)
		{
			$bits = 0;

			foreach($this->items as $item) {
				$bits += $item->estimateBitStreamSizeOfEntry($version);
			}

			return $bits;
		}
		
		//----------------------------------------------------------------------
		public function estimateVersion()
		{
			$version = 0;
			$prev = 0;
			do {
				$prev = $version;
				$bits = $this->estimateBitStreamSize($prev);
				$version = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
				if ($version < 0) {
					return -1;
				}
			} while ($version > $prev);

			return $version;
		}
		
		//----------------------------------------------------------------------
		public static function lengthOfCode($mode, $version, $bits)
		{
			$payload = $bits - 4 - QRspec::lengthIndicator($mode, $version);
			switch($mode) {
				case QR_MODE_NUM:
					$chunks = (int)($payload / 10);
					$remain = $payload - $chunks * 10;
					$size = $chunks * 3;
					if($remain >= 7) {
						$size += 2;
					} else if($remain >= 4) {
						$size += 1;
					}
					break;
				case QR_MODE_AN:
					$chunks = (int)($payload / 11);
					$remain = $payload - $chunks * 11;
					$size = $chunks * 2;
					if($remain >= 6) 
						$size++;
					break;
				case QR_MODE_8:
					$size = (int)($payload / 8);
					break;
				case QR_MODE_KANJI:
					$size = (int)(($payload / 13) * 2);
					break;
				case QR_MODE_STRUCTURE:
					$size = (int)($payload / 8);
					break;
				default:
					$size = 0;
					break;
			}
			
			$maxsize = QRspec::maximumWords($mode, $version);
			if($size < 0) $size = 0;
			if($size > $maxsize) $size = $maxsize;

			return $size;
		}
		
		//----------------------------------------------------------------------
		public function createBitStream()
		{
			$total = 0;

			foreach($this->items as $item) {
				$bits = $item->encodeBitStream($this->version);
				
				if($bits < 0) 
					return -1;
					
				$total += $bits;
			}

			return $total;
		}
		
		//----------------------------------------------------------------------
		public function convertData()
		{
			$ver = $this->estimateVersion();
			if($ver > $this->getVersion()) {
				$this->setVersion($ver);
			}

			for(;;) {
				$bits = $this->createBitStream();
				
				if($bits < 0) 
					return -1;
					
				$ver = QRspec::getMinimumVersion((int)(($bits + 7) / 8), $this->level);
				if($ver < 0) {
					throw new Exception('WRONG VERSION');
					return -1;
				} else if($ver > $this->getVersion()) {
					$this->setVersion($ver);
				} else {
					break;
				}
			}

			return 0;
		}
		
		//----------------------------------------------------------------------
		public function appendPaddingBit(&$bstream)
		{
			$bits = $bstream->size();
			$maxwords = QRspec::getDataLength($this->version, $this->level);
			$maxbits = $maxwords * 8;

			if ($maxbits == $bits) {
				return 0;
			}

			if ($maxbits - $bits < 5) {
				return $bstream->appendNum($maxbits - $bits, 0);
			}

			$bits += 4;
			$words = (int)(($bits + 7) / 8);

			$padding = new QRbitstream();
			$ret = $padding->appendNum($words * 8 - $bits + 4, 0);
			
			if($ret < 0) 
				return $ret;

			$padlen = $maxwords - $words;
			
			if($padlen > 0) {
				
				$padbuf = array();
				for($i=0; $i<$padlen; $i++) {
					$padbuf[$i] = ($i&1)?0x11:0xec;
				}
				
				$ret = $padding->appendBytes($padlen, $padbuf);
				
				if($ret < 0)
					return $ret;
				
			}

			$ret = $bstream->append($padding);
			
			return $ret;
		}

		//----------------------------------------------------------------------
		public function mergeBitStream()
		{
			if($this->convertData() < 0) {
				return null;
			}

			$bstream = new QRbitstream();
			
			foreach($this->items as $item) {
				$ret = $bstream->append($item->bstream);
				if($ret < 0) {
					return null;
				}
			}

			return $bstream;
		}

		//----------------------------------------------------------------------
		public function getBitStream()
		{

			$bstream = $this->mergeBitStream();
			
			if($bstream == null) {
				return null;
			}
			
			$ret = $this->appendPaddingBit($bstream);
			if($ret < 0) {
				return null;
			}

			return $bstream;
		}
		
		//----------------------------------------------------------------------
		public function getByteStream()
		{
			$bstream = $this->getBitStream();
			if($bstream == null) {
				return null;
			}
			
			return $bstream->toByte();
		}
	}