<?php if (!defined('BASEPATH'))
	exit('No direct script access allowed');

class Ob_license
{

	//	private $_salt = "";

	//	private $_prefix = "OB";

	//	private $_randLen = 4;

	//	private $_hashLen = 20;

	public $message = "";

	public $reqKey = "";

	private $wrap = 0;

	public $actUrl = "";

	function __construct()
	{
		if (defined("OB_ACTIVATION_URL")) {
			$this->actUrl = OB_ACTIVATION_URL;
		} else {
			$this->actUrl = "https://cp.outputbooks.com";
		}
	}

	private function __prefix__()
	{
		return "OB";
	}

	private function __salt__()
	{
		return "IdN1a9P9h1S6e0R7u1S";
	}

	private function __randLen__()
	{
		return 4;
	}

	private function __hashLen__()
	{
		return 20;
	}

	public function hash_ob_password($password = '', $hashed = '', $len = 56)
	{
		$hash = hash('sha512', $this->__salt__() . $password);
		$hash = substr($hash, 0, $len);

		if (!empty($hashed)) {
			return $hashed == $hash ? true : false;
		}

		return $hash;
	}

	function getLicenseKey($uId, $data, $date = null, $licDuration = "28", $plan = "T")
	{
		if (!$date) {
			$date = time();
		}

		$date = date('ymd', $date);
		$rand = $this->randstr($this->__randLen__());

		$plan = strtoupper($plan);
		$plain_text = $date . $licDuration . $plan . $uId . $rand;

		$enc_text = hash('sha512', $this->__salt__() . $plain_text);
		$hash = substr($enc_text, 0, $this->__hashLen__());

		$data = $this->_encrypt(json_encode($data), $enc_text);

		$serial_key = $this->__prefix__() . '-' . $date . $licDuration . $plan . $uId . '-' . $rand . $hash . $data;

		// Wraped Serial Key
		if ($this->wrap) {
			$serial_key = wordwrap($serial_key, $this->wrap, "\n", true);
		}

		return $serial_key;
	}

	public function isValidLicenseKey($serial_key = "")
	{
		try {
			if (empty($serial_key)) {
				return false;
			}
			$serial_key = str_replace("\n", "", $serial_key);

			$serial_key = explode("-", $serial_key);

			if ($serial_key[0] == $this->__prefix__()) {
				$pattern = "/(\d{0,6})(\d+)([T|t|D|d|F|f|P|p|S|s|E|e])(\d+)/";
				$matches;
				preg_match($pattern, $serial_key[1], $matches);
				if ($matches && count($matches) == 5) {
					$ret = array();

					$ret['date'] = $matches[1];
					$ret['licDuration'] = $matches[2];
					$ret['plan'] = $matches[3];
					$ret['uId'] = $matches[4];

					$rand = substr($serial_key[2], 0, $this->__randLen__());
					$orgHash = substr($serial_key[2], $this->__randLen__(), $this->__hashLen__());
					$data = substr($serial_key[2], $this->__randLen__() + $this->__hashLen__());

					$plain_text = $ret['date'] . $ret['licDuration'] . $ret['plan'] . $ret['uId'] . $rand;
					$enc_text = hash('sha512', $this->__salt__() . $plain_text);
					$hash = substr($enc_text, 0, $this->__hashLen__());

					if ($hash == $orgHash) {
						$data = $this->_decrypt($data, $enc_text);
						if ($data === false) {
							return false;
						}
						$ret['data'] = $data;
						// $this->log($ret, "isValidLicenseKey : 131");
						$this->format_lic_data($ret);
						return $ret;
					} else {
						return false;
					}
				}
			}
		} catch (Exception $ex) {
			return false;
		}

		return false;
	}

	private function format_lic_data(&$licData = array())
	{
		if (!empty($licData['data'])) {
			$licData["data"] = json_decode($licData["data"], true);
		}

		$date = date_parse_from_format("ymd", $licData['date']);

		$date = strtotime($date['year'] . "-" . $date['month'] . "-" . $date['day']);
		$licData['dateStamp'] = $date;
		$licData['dateF'] = date("Y-m-d", $date);
		$toDate = strtotime("+" . ($licData['licDuration'] + 1) . " days", $date) - 1;// +1 day & -1 mili second for set toDate to the end of day (11:59)

		$licData['expiredOn'] = $toDate;
		$licData['expiredOnF'] = date("Y-m-d", $toDate);

		$licData['isExpired'] = (time() > $toDate) ? true : false;
		$licData['isTrial'] = ($licData['plan'] == 'T') ? true : false;
		$licData['isDemo'] = ($licData['plan'] == 'D') ? true : false;
		$licData['isFree'] = ($licData['plan'] == 'F') ? true : false;
		$licData['isPro'] = ($licData['plan'] == 'P' || $licData['plan'] == 'S' || $licData['plan'] == 'E') ? true : false;
		$licData['isStandard'] = ($licData['plan'] == 'S') ? true : false;
		$licData['isEnterprise'] = ($licData['plan'] == 'E') ? true : false;

		// Plan Permissions Begins
		$licData["allowNewComp"] = false;
		$licData["allowBranch"] = false;
		$licData["customerLogin"] = false;
		$licData["maxBranch"] = 0; // BL - Branch Location
		$licData["maxUsers"] = 0; // U - Users
		$licData["maxTrans"] = 0; // MT - Max Trans

		$licData["hasEcommerce"] = false;
		$licData["hasProject"] = false;
		$licData["hasSalesRep"] = false;

		if (defined('IS_DEMO') && IS_DEMO === true) {
			$licData["allowNewComp"] = true;
			$licData["data"]["mod"] = "EC,RP,PJ";
		}

		if ((defined('IS_DEMO') && IS_DEMO === true) || $licData['isDemo'] || $licData['isTrial']) {
			$licData["maxBranch"] = 0;
			$licData["salRepLogin"] = true;
			$licData["allowBranch"] = true;
			$licData["customerLogin"] = true;
			$licData["maxTrans"] = 0;
			$licData["data"]["mod"] = "EC,RP,PJ";
			$licData['isPro'] = $licData['isStandard'] = $licData['isEnterprise'] = true;
		}

		if ($licData['isStandard'] || $licData['isEnterprise']) {
			$licData["salRepLogin"] = true;
			$licData["allowBranch"] = true;
			$licData["data"]["mod"] = "EC,RP,PJ";
			$licData["maxBranch"] = empty($licData["data"]["BL"]) ? 10 : $licData["data"]["BL"];
			$licData["maxTrans"] = 40000;

			if ($licData['isEnterprise']) {
				$licData["customerLogin"] = true;
				$licData["maxBranch"] = empty($licData["data"]["BL"]) ? 20 : $licData["data"]["BL"];
				$licData["maxTrans"] = 60000;
			}
		} else if ($licData['isPro']) {
			$licData["maxTrans"] = 20000;

			if (!empty($licData["data"]["BL"])) {
				$licData["allowBranch"] = true;
				$licData["maxBranch"] = $licData["data"]["BL"];
			}
		}

		if (!empty($licData["data"]["U"])) {
			$licData["maxUsers"] = $licData["data"]["U"];
		}

		$licData["maxTrans"] = empty($licData["data"]["MT"]) ? $licData["maxTrans"] : $licData["data"]["MT"];

		// Modules : BL = Branch/Location, EC = E-Commerce, RP = Sales Rep, PJ = Project
		if (!empty($licData["data"]["mod"])) {
			$licData["hasEcommerce"] = (strpos($licData["data"]["mod"], "EC") > -1) ? true : false;
			$licData["hasSalesRep"] = (strpos($licData["data"]["mod"], "RP") > -1) ? true : false;
			$licData["hasProject"] = (strpos($licData["data"]["mod"], "PJ") > -1) ? true : false;
		}
		// Plan Permissions End

		$plans = array(
			"T" => "Trial",
			"D" => "Demo",
			"F" => "Free",
			"P" => "Basic",
			"S" => "Standard",
			"E" => "Enterprise"
		);

		$licData['planTxt'] = $plans[strtoupper($licData['plan'])];
	}

	public function get_uuid()
	{
		$result = "";

		$uuid = FCPATH . "uuid.txt";
		if (is_file($uuid)) {
			$uuid = file_get_contents($uuid);
			if (!empty($uuid)) {
				$result = base64_decode($uuid);
			}
		} else if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
			if (function_exists('shell_exec') && is_callable('shell_exec')) {
				$temp = sys_get_temp_dir() . DIRECTORY_SEPARATOR . "diskpartscript.txt";
				if (!file_exists($temp) && !is_file($temp)) {
					file_put_contents($temp, "select disk 0\ndetail disk");
				}
				$output = shell_exec("diskpart /s " . $temp);
				$lines = explode("\n", $output);
				$result = array_filter($lines, function ($line) {
					return stripos($line, "ID:") !== false;
				});

				if (count($result) > 0) {
					$result = array_values($result);
					$result = array_shift($result);
					$result = explode(":", $result);
					$result = trim(end($result));
				} else {
					$result = $output;
				}
			}

			if (empty($result)) {
				$result = str_shuffle("0123456789abcdef0123456789abcdef");
			}

			file_put_contents($uuid, base64_encode($result));
		} else {
			if (function_exists('shell_exec') && is_callable('shell_exec')) {
				$result = shell_exec("blkid -o value -s UUID");

				if (!empty($result) && stripos($result, "blkid") !== false) {
					$result = php_uname();
				}
			}

			if (empty($result)) {
				$result = str_shuffle("0123456789abcdef0123456789abcdef");
			}

			file_put_contents($uuid, base64_encode($result));
		}

		return md5($result);
	}

	private function __get_activation_key__($uId = "", $uuId = "")
	{
		$actData = "OB-ACTIVATION-" . $uId . "-" . $uuId;
		$actKey = $this->hash_ob_password($actData, null, 25);
		$actKey = strtoupper($actKey);
		$actKey = str_split($actKey, 5);
		$actKey = implode("-", $actKey);

		return $actKey;
	}

	public function get_activation_key($licenseKey, $uuid)
	{
		$licData = $this->isValidLicenseKey($licenseKey);
		$actKey = $this->__get_activation_key__($licData["uId"], $uuid);
		return $actKey;
	}

	public function is_activated($licenseKey, $activationKey, $uuid = "")
	{
		$licData = $this->isValidLicenseKey($licenseKey);
		if (empty($uuid)) {
			$uuid = $this->get_uuid();
		}

		if (defined('APP_ACTIVE') && APP_ACTIVE == 1) {
			return true;
		}

		$actKey = $this->__get_activation_key__($licData["uId"], $uuid);

		//$this->log($licData, "licData");
//$this->log($activationKey, "activationKey");
//$this->log($licenseKey, "licenseKey");
//$this->log($actKey, "actKey");
		return ($activationKey == $actKey);
	}

	public function get_machine_info()
	{
		$sysData = array();
		$sysData["uuid"] = $this->get_uuid();
		$sysData["host"] = php_uname("n");
		$sysData["uname"] = php_uname();
		$sysData["locip"] = getHostByName($sysData["host"]);

		$sysData = json_encode($sysData);
		$encSysData = base64_encode($sysData);

		// $passKey = $this->randstr(8);
		// $encSysData = $passKey . $this->_encrypt($sysData, $passKey);

		return $encSysData;
	}

	public function decrypt_machine_info($encSysData = "")
	{
		/*
		$passKey = substr($encSysData, 0, 8);
		$encSysData = substr($encSysData, 8);
		$sysData = $this->_decrypt($encSysData, $passKey);
		*/
		$encSysData = base64_decode($encSysData);
		$sysData = json_decode($encSysData);

		return $sysData;
	}

	private function _post_data($url = "", $postData = array())
	{
		$postData = http_build_query($postData);

		$opts = array(
			'http' => array(
				'method' => 'POST',
				'header' => 'Content-type: application/x-www-form-urlencoded',
				'content' => $postData
			)
		);

		$context = stream_context_create($opts);

		$result = file_get_contents($url, false, $context);

		return $result;
	}

	public function activate($licenseKey = "")
	{
		$licData = $this->isValidLicenseKey($licenseKey);
		if ($licData["isTrial"]) {
			// $this->message = "Trial license not need to activate.";
			// return false;
		}

		$reqKey = $this->get_machine_info();

		$this->reqKey = $reqKey;

		$postData = array(
			"licKey" => $licenseKey,
			"reqKey" => $reqKey
		);

		$curl_url = $this->actUrl . "/index.php/home/activate/1";

		$CI =& get_instance();
		$CI->load->library("curl");

		if (defined('OB_PROXY') && OB_PROXY && OB_PROXY_HOST && OB_PROXY_PORT) {
			$this->curl->proxy(OB_PROXY_HOST, OB_PROXY_PORT);

			if (defined('OB_PROXY_USER') && defined('OB_PROXY_PASS')) {
				$this->curl->proxy_login(OB_PROXY_USER, OB_PROXY_PASS);
			}
		}

		$CI->curl->ssl(false);

		$result = $CI->curl->simple_post($curl_url, $postData, array(
			CURLOPT_BUFFERSIZE => 10,
			CURLOPT_FOLLOWLOCATION => true,
			CURLOPT_POSTREDIR => 7
		));

		if (!empty($result)) {
			try {
				$result = json_decode($result, true);
				if ($result[0] == 1 && !empty($result[2])) {
					if (!empty($result[2]["actKey"])) {
						return $result[2]["actKey"];
					}
				} else if (!empty($result[1])) {
					$this->message = "Activation Error : " . $result[1];
					return false;
				}
			} catch (Exception $ex) {
				$this->message = "Activation Error : " . $ex->getMessage();
				return false;
			}
		}

		return false;
	}

	public function encId($inp = "", $isValidation = false)
	{
		$randLen = 3;
		$hashLen = 2;

		$rand = "";
		$txt = "";

		if ($isValidation) {
			$rand = substr($inp, $hashLen, $randLen);
			$txt = substr($inp, $randLen + $hashLen);
		} else {
			$rand = substr(str_shuffle("0123456789"), 0, $randLen);
			$txt = $inp;
		}

		$hash = substr(crc32("Output" . $rand . $txt . "Books"), 0, $hashLen);
		$ret = $hash . $rand . $txt;

		if ($isValidation) {
			return ($ret == $inp) ? $txt : false;
		}

		return $ret;
	}

	public function _encrypt($data, $key)
	{
		$res = '';
		for ($i = 0, $keyLen = strlen($key), $iLen = strlen($data); $i < $iLen; $i++) {
			$c = ord(substr($data, $i));
			$c += ord(substr($key, (($i + 1) % $keyLen)));
			$res .= chr($c & 0xFF);
		}

		$res = base64_encode($res);
		$res = hash("crc32", $res) . $res;

		return $res;
	}

	public function _decrypt($data, $key)
	{
		$crc32 = substr($data, 0, 8);
		$data = substr($data, 8);

		if ($crc32 != hash("crc32", $data)) {
			return false;
		}

		$data = base64_decode($data);
		$res = '';
		for ($i = 0, $keyLen = strlen($key), $iLen = strlen($data); $i < $iLen; $i++) {
			$c = ord(substr($data, $i));
			$c -= ord(substr($key, (($i + 1) % $keyLen)));
			$res .= chr(abs($c) & 0xFF);
		}

		return $res;
	}

	public function randstr($len = 8, $pool = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
	{
		return substr(str_shuffle($pool), 0, $len);
	}

	private function log($content = "", $key = "")
	{
		file_put_contents(FCPATH . "lic_log.txt", print_R($key, true) . " : " . print_R($content, true), FILE_APPEND);
	}
}

