<?php

class LicenseType {
	const Master = "0" ;
	const Client = "1";
	const Reseller = "2";
	const Demo = "9";
}
class ModuleInfo {
	const Waiter = 0 ;
    const Display = 1 ;
    const SelfServe = 2 ;
    const POS = 3;
    const Stock = 4;
    const Sales = 5;
	const HR = 6 ;
	const Payroll = 7 ;
	const Report = 8 ;
	const Attendance = 9 ;
	const StockCount = 10 ;
	const ExpenseClaims = 11 ;
	const eStatement = 12 ;
	const eInvoice = 13 ;
	const bankInterface = 14 ;
    const eRequest = 15;
}
class DeviceStatus {
	const Pending = 0 ;
	const Active = 1 ;
	const Void = 9 ;
}
class LicenseFile {
	const C_LIC_VER = "1";
	
	private $lictype ;
	private $prodver ;	
	private $deviceids ;
	private $filedate ;
	private $expiry ;
	private $sno ;
	private $modules ;
	private $cust ;
	private $productid ;
	private $prodname ;
	private $usercount ;
	private $regkey ;
	private $devicecount ;
	
	function __construct() {
		$this->init() ;
	}
	function __destruct() {
	}
	function getLicenseType() {
		return $this->lictype ;
	}
	function setLicenseType($value) {
		$this->lictype = $value ;
	}
	function getProductVersion() {
		return $this->prodver ;
	}
	function setProductVersion($value) {
		$this->prodver = $value ;
	}
	function getFileDate() {
		return $this->filedate ;
	}
	function setFileDate($value) {
		$this->filedate = $value ;
	}
	function getExpiryDate() {
		return $this->expiry ;
	}
	function setExpiryDate($value) {
		$this->expiry = $value ;
	}
	function getSerialNo() {
		return $this->sno ;
	}
	function setSerialNo($value) {
		$this->sno = $value ;
	}
	function getUserCount() {
		return $this->usercount ;
	}
	function setUserCount($value) {
		$this->usercount = $value ;
	}
	function getDeviceCount() {
		return $this->devicecount ;
	}
	function setDeviceCount($value) {
		$this->devicecount = $value ;
	}
	function getProductId() {
		return $this->productid ;
	}
	function setProductId($value) {
		$this->productid = $value ;
	}
	function getProductName() {
		return $this->prodname ;
	}
	function setProductName($value) {
		$this->prodname = $value ;
	}
	function getCustomer() {
		return $this->cust ;
	}
	function setCustomer($value) {
		$this->cust = $value ;
	}
	function getRegKey() {
		return $this->regkey ;
	}
	function setRegKey($value) {
		$this->regkey = $value ;
	}
	function getModules() {
		return $this->modules ;
	}
	function setModules($value) {
		$this->initModule();
		//Log::write("setModules : " . $value) ;
		$this->set_Module($value) ;
		//$this->modules = $value ;
	}
	function getDeviceIDs() {
		return $this->deviceids ;
	}
	function setDeviceIDs($ids) {
		//$this->deviceids = $devices ;
		$this->set_DeviceIDs($ids);
	}
	function read($file) {
		if (file_exists($file)) {
			try {
				$fh = fopen($file,'r') ;
				$enc = fread($fh,filesize($file)) ;
				fclose($fh) ;
				
				/*
				$datalen = substr($d,0,6) ;
				if (strlen($d) != $datalen) {
					throw new Exception('Invalid License data size - ' . strlen($d) . ':' . $datalen) ;
				}*/
				
				$this->init() ;
				$this->cust = trim(substr($enc,10,120));
				$this->prodname = trim(substr($enc,130,80));
				$enc = trim(substr($enc,210));
				$d = $this->decryptLicense($enc) ;
				
				$cs = trim(substr($d,0,32));
				$len = trim(substr($d,32,6));
				$this->lictype = trim(substr($d,38,2));
				$this->productid = trim(substr($d,40,8));
				$this->prodver = trim(substr($d,48,4));
				$this->usercount = trim(substr($d,52,6));
				$this->sno = trim(substr($d,58,8));
				$this->filedate = trim(substr($d,66,17));
				$this->expiry = trim(substr($d,83,8));
				$this->regkey = trim(substr($d,91,16));
				$this->devicecount = trim(substr($d,107,5));
				$this->set_Module(trim(substr($d,112,80))) ;
				$this->set_DeviceIDs(trim(substr($d,192))) ;
				
				if ($this->validateDate($this->filedate)) {
					$temp = substr($this->filedate,0,4) . "-" . substr($this->filedate,4,2) . "-" . substr($this->filedate,6,2) ;
					if (date_create($temp) > date_create('now')){
						$this->init();
						throw new Exception('Invalid License/System Date - ' . $this->filedate . ',' . date('Y-m-d')) ;
					}
					else 
						$this->filedate = $temp;
				} else {
					$this->init();
					throw new Exception('Invalid License Date - ' . $this->filedate) ;
				}
				
				if ($this->validateDate($this->expiry)) {
					$this->expiry = substr($this->expiry,0,4) . "-" . substr($this->expiry,4,2) . "-" . substr($this->expiry,6,2) ;
				} else {
					$this->init();
					throw new Exception('Invalid Expiry Date - ' . $this->expiry) ;
				}
				
				/*
				$data = substr($d,0,50) ;
				$module = substr($d,50,80) ;
				$ids = substr($d,130,$datalen - 130 - 32);
				$hash = substr($d,$datalen-32,32) ;
				$cs = md5(substr($d,0,$datalen)) ;
				if ($cs != $hash)
					throw new Exception('Invalid data checksum - ' .$cs . ':' .$hash) ;
				$this->type = trim(substr($data,6,2)) ;
				$this->ver = trim(substr($data,8,3)) ;
				$this->sno = trim(substr($data,11,8)) ;
				$dte = trim(substr($data,19,8)) ;
				if ($this->validateDate($dte)) {
					$this->date = substr($dte,0,4) . "-" . substr($dte,4,2) . "-" . substr($dte,6,2) ;
					if (date_create($this->date) > date_create('now'))
						throw new Exception('Invalid License/System Date - ' . $dte . ',' . date('Y-m-d')) ;
				} else {
					throw new Exception('Invalid License Date - ' . $dte) ;
				}
				$dte = trim(substr($data,27,8)) ;
				if ($dte == "") {
					$this->expiry = "" ;
				} else {
					if ($this->validateDate($dte)) {
						$this->expiry = substr($dte,0,4) . "-" . substr($dte,4,2) . "-" . substr($dte,6,2) ;
					} else {
						throw new Exception('Invalid Expiry Date - ' . $dte) ;
					}
				}
				$blank = substr($data,35,15) ;
				$this->setDeviceIDs($ids) ;
				$this->set_Module($module) ;*/
				
			} catch (Exception $e) {
				throw new Exception('Error in reading License File. ' . $e->getMessage()) ;
			}
		} else {
			throw new Exception('License file not found.');
		}
		/*
		if (file_exists($file)) {
			try {
				$fh = fopen($file,'r') ;
				$enc = fread($fh,filesize($file)) ;
				fclose($fh) ;
				
				$d = $this->decryptData($enc) ;
				$datalen = substr($d,0,6) ;
				if (strlen($d) != $datalen) {
					throw new Exception('Invalid License data size - ' . strlen($d) . ':' . $datalen) ;
				}
				$data = substr($d,0,50) ;
				$module = substr($d,50,80) ;
				$ids = substr($d,130,$datalen - 130 - 32);
				$hash = substr($d,$datalen-32,32) ;
				$cs = md5(substr($d,0,$datalen)) ;
				if ($cs != $hash)
					throw new Exception('Invalid data checksum - ' .$cs . ':' .$hash) ;
				$this->init() ;
				$this->type = trim(substr($data,6,2)) ;
				$this->ver = trim(substr($data,8,3)) ;
				$this->sno = trim(substr($data,11,8)) ;
				$dte = trim(substr($data,19,8)) ;
				if ($this->validateDate($dte)) {
					$this->date = substr($dte,0,4) . "-" . substr($dte,4,2) . "-" . substr($dte,6,2) ;
					if (date_create($this->date) > date_create('now'))
						throw new Exception('Invalid License/System Date - ' . $dte . ',' . date('Y-m-d')) ;
				} else {
					throw new Exception('Invalid License Date - ' . $dte) ;
				}
				$dte = trim(substr($data,27,8)) ;
				if ($dte == "") {
					$this->expiry = "" ;
				} else {
					if ($this->validateDate($dte)) {
						$this->expiry = substr($dte,0,4) . "-" . substr($dte,4,2) . "-" . substr($dte,6,2) ;
					} else {
						throw new Exception('Invalid Expiry Date - ' . $dte) ;
					}
				}
				$blank = substr($data,35,15) ;
				$this->setDeviceIDs($ids) ;
				$this->set_Module($module) ;
				
			} catch (Exception $e) {
				throw new Exception('Error in reading License File. ' . $e->getMessage()) ;
			}
		} else {
			throw new Exception('License file not found.');
		}
		*/
	}
	function save($file) {
		if (file_exists($file)) {
			unlink($file) ;
		}
	}
	function generateDeviceLicense_unuse() {
		$data = '';
		$blank = str_repeat(' ',21) ;
		$exp = str_replace("-","",$this->expiry) ;
		$fil = str_replace("-","",$this->filedate) ;
		$data = str_pad($this->lictype,2) . str_pad($this->productid,8) . str_pad($this->prodver,4) . str_pad($this->usercount,6) . str_pad($this->sno,8) . str_pad($fil,17) . str_pad($exp,8) . $blank ;
		$data .= $this->get_Module() ;
		$data .= $this->get_DeviceIDs() ;
		$outdata = str_pad(strlen($data)+38,6,"0",STR_PAD_LEFT) . $data ;
		$cs = md5($outdata) ;//32 bytes
		return str_pad(LicenseFile::C_LIC_VER,10) . str_pad($this->cust,120) . str_pad($this->prodname,80) .  $this->encryptData($cs . $outdata) ;
	}
	function generateLicense($type) {
		$data = '';
		//$blank = str_repeat(' ',5) ;
		$exp = str_replace("-","",$this->expiry) ;
		$fil = str_replace("-","",$this->filedate) ;
		$data = str_pad($this->lictype,2) . str_pad($this->productid,8) . str_pad($this->prodver,4) . str_pad($this->usercount,6) . str_pad($this->sno,8) . str_pad($fil,17) . str_pad($exp,8) . str_pad($this->regkey,16) . str_pad($this->devicecount,5) ;
		$data .= $this->get_Module() ;
		$data .= $this->get_DeviceIDs() ;
		$outdata = str_pad(strlen($data)+38,6,"0",STR_PAD_LEFT) . $data ;
		$cs = md5($outdata) ;//32 bytes
		if ($type == 0) {
			$encdata = $this->encryptLicense($cs . $outdata) ;
		} else {
			//device file for download to mobile device
			$encdata = $this->encryptData($cs . $outdata);
		}
		return str_pad(LicenseFile::C_LIC_VER,10) . str_pad($this->cust,120) . str_pad($this->prodname,80) .  $encdata ;
	}
	private function init() {
		$type = "" ;
		$prodver = "" ;
		$sno = "";
		$filedate = "" ;
		$expiry = "" ;
		$product = "";
		$cust = "";
		$deviceids = "" ;
		$prodname = "";
		$usercount = 0 ;
		$devicecount = 0 ;
		$regkey = "";
		$this->initModule() ;
	}
	private function validateDate($date) {
		if ($date == "")
			return false ;
		$y = substr($date,0,4) ;
		$m = substr($date,4,2) ;
		$d = substr($date,6,2) ;
		return checkdate($m,$d,$y) ;
	}
	private function set_Module($m) {
		if ($m == "")
			return ;
		$len = strlen($m) ;
		for ($i=0;$i < $len;$i++) {
			if ($m[$i] == "1")
				$this->modules[$i] = true ;
			else
				$this->modules[$i] = false ;
		}
		//Log::write("set_Module : " . $m . ",len : " . $len) ;
	}
	private function get_Module() {
		$mod = "";
		for ($i=0;$i<80;$i++) {
			//Log::write("get_Module. idx : " .$i . ",value : " . $this->modules[$i] . "\r\n") ;
			if ($this->modules[$i])
				$mod .= "1";
			else 
				$mod .= "0";
		}
		return $mod ;
	}
	private function initModule() {
		$this->moduels = array() ;
		for ($i=0;$i<80;$i++) {
			$this->modules[$i] = false ;
		}
	}
	private function set_DeviceIDs($ids) {
		if ($ids == "")
			$this->deviceids = array() ;
		else 
			$this->deviceids = explode("|", $ids);
	}
	private function get_DeviceIDs() {
		$dec = "";
		$sep = "";
		if ($this->deviceids != null) {
			for ($i=0;$i<count($this->deviceids);$i++) {
				$dec .= $sep . $this->deviceids[$i] ;
				$sep = "|";
			}
		}
		return $dec ;
	}
	
	private function encryptData($data) {
		return base64_encode($this->packString($data));
	}
	private function decryptData($encdata) {
		$data = base64_decode($encdata);
		$enc = $this->unpackString($data) ;
		return $enc ;
	}
	function packString($data) {
		$inputlen = strlen($data);// Counts number characters in string $input
		$randkey = rand(1, 9); // Gets a random number between 1 and 9
		
		$i = 0;
		while ($i < $inputlen) {
			$inputchr[$i] = (ord($data[$i]) - $randkey);//encrpytion in ascii dec value
			$i++; // For the loop to function
		}
		$encrypted = implode('.', $inputchr) . '.' . (ord($randkey)+50);	
		return $encrypted;	//output ascii dec value. e.g. 45.67.89
	}
	function unpackString($data) {
		//$input_count = strlen($data);
 
		$dec = explode(".", $data);// splits up the string to any array
		$x = count($dec);
		$y = $x-1;// To get the key of the last bit in the array 
 
		$calc = $dec[$y]-50;
		$randkey = chr($calc);// works out the randkey number
 
		$i = 0;
 
		while ($i < $y) {
			//$array[$i] = $dec[$i]+$randkey; // Works out the ascii characters actual numbers
			$tmp = $dec[$i]+$randkey ;
			$real .= chr($tmp); //The actual decryption
 
			$i++;
		};
 
		return $real;
	}
	
	private function encryptLicense($data) {
		$extra = 8 - (strlen($data) % 8);
		// add the zero padding
		if($extra > 0) {
			for($i = 0; $i < $extra; $i++) {
				$data .= "\0";
			}
		}
		$key = $this->getKey() ;
		$iv = $this->getIV() ;
		//return base64_encode(mcrypt_cbc(MCRYPT_3DES, $key, $data, MCRYPT_ENCRYPT, $iv));
		return base64_encode(mcrypt_encrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_ECB, $iv));
		
		//ecb mode
		//$block = mcrypt_get_block_size(MCRYPT_3DES, MCRYPT_MODE_ECB);
		//$pad = $block - (strlen($data) % $block);
		//$data .= str_repeat(chr($pad), $pad);

		//$ciphertext = mcrypt_encrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_ECB);
		//return base64_encode($ciphertext);
	}
	private function decryptLicense($encdata) {
		$data = base64_decode($encdata);
		$key = $this->getKey() ;
		$iv = $this->getIV() ;
		//$enc = mcrypt_decrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_CBC, $iv) ;
		$enc = mcrypt_decrypt(MCRYPT_3DES, $key, $data, MCRYPT_MODE_ECB, $iv);
		//cbc zero padding
		return rtrim($enc, "\0") ;
	}
	private function getKey() {
		//return "cK7uR!pdz8ir%df93Lkdfyo4rsiu)oiE" ;	//256 bits
		return "cK7uR!pdz8ir%df93Lkdfyo4";	//192 bits
	}
	private function getIV() {
		return "*7duT4dk";
	}
}
?>
