PHP Classes
Icontem

File: shared/class.license.lib.php


  Search   All class groups All class groups   Latest entries Latest entries   Top 10 charts Top 10 charts   Newsletter Newsletter   Blog Blog   Forums Forums   Help FAQ Help FAQ  
  Login   Register  
Recommend this page to a friend! ReTweet ReTweet Stumble It! Stumble It! Bookmark in del.icio.us Bookmark in del.icio.us
  Classes of Oliver Lillie  >  PADL (PHP Application Distribution License System)  >  shared/class.license.lib.php  
File: shared/class.license.lib.php
Role: Class source
Content type: text/plain
Description: Class Source
Class: PADL (PHP Application Distribution License System)
Generate PHP application license keys
 

Contents

Class file image Download
<?php

	/**
	* Project:		Distrubution License Class
	* File:			class.license.lib.php
	*
	* Copyright (C) 2005 Oliver Lillie
	* 
	* This program is free software; you can redistribute it and/or modify it 
	* under the terms of the GNU General Public License as published by  the Free 
	* Software Foundation; either version 2 of the License, or (at your option) 
	* any later version.
	*
	* This program 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 General Public License 
	* for more details.
	*
	* You should have received a copy of the GNU General Public License along 
	* with this program; if not, write to the Free Software Foundation, Inc., 
	* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA	
	*
	* @link http://www.buggedcom.co.uk/
	* @link http://www.phpclasses.org/browse/package/2298.html
	* @author Oliver Lillie, buggedcom <publicmail at buggedcom dot co dot uk>
	* @version 0.1
	* @history---------------------------------------------
	* see CHANGELOG
	*/

	class padl {
	
		/**
		* hash key 1 used to encrypt the generate key data.
		* hash key 2 used to encrypt the request data
		* hash key 3 used to encrypt the dial home data
		* NOTE1 : there are three different hash keys for the three different operations
		* NOTE2 : these hash key's are for use by both mcrypt and alternate cryptions
		* 		  and although mcrypts keys are typically short they should be kept long
		*		  for the sake of the other functions
		*
		* @var string
		* @var string
		* @var string
		*/
		 var $HASH_KEY1 	= 'YmUzYWM2sNGU24NbA363zA7IDSDFGDFGB5aVi35BDFGQ3YNO36ycDFGAATq4sYmSFVDFGDFGps7XDYEzGDDw96OnMW3kjCFJ7M+UV2kHe1WTTEcM09UMHHT';
		 var $HASH_KEY2 	= '80dSbqylf4Cu5e5OYdAoAVkzpRDWAt7J1Vp27sYDU52ZBJprdRL1KE0il8KQXuKCK3sdA51P9w8U60wohX2gdmBu7uVhjxbS8g4y874Ht8L12W54Q6T4R4a';
		 var $HASH_KEY3 	= 'ant9pbc3OK28Li36Mi4d3fsWJ4tQSN4a9Z2qa8W66qR7ctFbljsOc9J4wa2Bh6j8KB3vbEXB18i6gfbE0yHS0ZXQCceIlG7jwzDmN7YT06mVwcM9z0vy62T';
		 
		/**
		* You may not want to use mcrypt even if your system has it installed
		* make this false to use a regular encryption method
		*
		* @var boolean
		*/
		var $USE_MCRYPT	= true;

		/**
		* The algorythm to be used by mcrypt
		*
		* @var string
		*/
		var $ALGORITHM		= 'blowfish';

		/**
		* use time binding vars inited.
		*/
		var $USE_TIME;
		
		/**
		* time checking start period difference allowance ie if the user has slightly different time 
		* setting on their server make an allowance for the diff period. carefull to not make it too 
		* much otherwise they could just reset their server to a time period before the license expires.
		*
		* @var number (seconds)
		*/
		var $START_DIF		= 129600;  
		
		/**
		* id 1 used to validate license keys
		* id 2 used to validate license key requests
		* id 2 used to validate dial home data
		*
		* @var string
		* @var string
		* @var string
		*/
		# id to check for to validate source
		var $ID1			= 'nSpkAHRiFfM2hE588eB';
		var $ID2			= 'NWCy0s0JpGubCVKlkkK';
		var $ID3			= 'G95ZP2uS782cFey9x5A';

		/**
		* begining and end strings
		*
		* @var strings
		*/
		var $BEGIN1 		= 'BEGIN LICENSE KEY';
		var $END1			= 'END LICENSE KEY';

		/**
		* wrap key settings
		*
		* @var number
		* @var string
		* @var string
		*/
		var $_WRAPTO		= 80;
		var $_PAD			= "-";
		
		/**
		* init the linebreak var
		*/
		var $_LINEBREAK;
		
		/**
		* dial home return query deliminators
		*
		* @var string
		* @var string
		*/
		var $BEGIN2	 	= '_DATA{';
		var $END2	 		= '}DATA_';
			
		/**
		* init the key data array.
		*
		* @var array
		*/
		var $_DATA			= array();

		/**
		* use server binding vars inited.
		*/
		var $USE_SERVER;
		var $_SERV;
		var $_MAC;
		var $ALLOW_LOCAL;
		var $_SERVER_INFO = array();
		
		/**
		* this is the number of required server stats for the key generation to be successfull
		* if the server can't produce this number of details then the key fails to be generated
		* you can set it to however many you wish, the max is 5
		*
		* @var number
		*/
		var $REQUIRED_URIS	= 2;

		/**
		* the date string for human readable format
		*
		* @var string
		*/
		var $DATE_STRING	= 'd/M/Y H:i:s';
		
		/**
		* Constructor
		*
		* @access private 
		**/
		function padl()
		{
			# check to see if the class has been secured
			$this->_check_secure();
		}

		/**
		* init
		*
		* init the license class
		*
		* @access public 
		* @param $use_mcrypt boolean Determines if mcrypt encryption is used or not (defaults to true, 
		*					 however if mcrypt is not available, it is set to false) 
		* @param $use_time boolean Sets if time binding should be used in the key (defaults to true) 
		* @param $use_server boolean Sets if server binding should be used in the key (defaults to true) 
		* @param $allow_local boolean Sets if server binding is in use then localhost servers are valid (defaults to false) 
		**/
		function init($use_mcrypt=true, $use_time=true, $use_server=true, $allow_local=false)
		{
			# check to see if the class has been secured
			$this->_check_secure();
			$this->USE_MCRYPT			= ($use_mcrypt && function_exists('mcrypt_generic'));
			$this->USE_TIME			= $use_time;
			$this->ALLOW_LOCAL			= $allow_local;
			$this->USE_SERVER			= $use_server;
			$this->_LINEBREAK			= $this->_get_os_linebreak();
		}
		
		/**
		* _get_os_linebreak
		*
		* get's the os linebreak
		*
		* @access private 
		* @param $true_val boolean If the true value is needed for writing files, make true
		*							defaults to false
  		* @return string Returns the os linebreak
		**/
		function _get_os_linebreak($true_val=false)
		{
			$os = strtolower(PHP_OS);
			switch($os)
			{
				# not sure if the string is correct for FreeBSD
				# not tested
				case 'freebsd' : 
				# not sure if the string is correct for NetBSD
				# not tested
				case 'netbsd' : 
				# not sure if the string is correct for Solaris
				# not tested
				case 'solaris' : 
				# not sure if the string is correct for SunOS
				# not tested
				case 'sunos' : 
				# linux variation
				# tested on server
				case 'linux' : 
					$nl = "\n";
					break;
				# darwin is mac os x
				# tested only on the client os
				case 'darwin' : 
					# note os x has \r line returns however it appears that the ifcofig
					# file used to source much data uses \n. let me know if this is
					# just my setup and i will attempt to fix.
					if($true_val) $nl = "\r";
					else $nl = "\n";
					break;
				# defaults to a win system format;
				default :
					$nl = "\r\n";
			}
			return $nl;
		}
		
		/**
		* _post_data
		*
		* Posts data to and recieves data from dial home server. Returned info
		* contains the dial home validation result
		*
		* @access private 
		* @param $host string Host name of the server to be contacted
		* @param $path string Path of the script for the data to be sent to
		* @param $query_array array Array that contains the license key info to be validated
		* @param $port number Port Number to send the data through
  		* @return array Result of the dialhome validation
  		* @return string - SOCKET_FAILED will be returned if it was not possible to open a socket to the home server
		**/
		function _post_data($host, $path, $query_array, $port=80)
		{
			# generate the post query info
			$query 	 = 'POSTDATA='.$this->_encrypt($query_array, 'HOMEKEY');
			$query 	 .= '&MCRYPT='.$this->USE_MCRYPT;
			# init the return string
			$return  = '';
			
			# generate the post headers
			$post  	 = "POST $path HTTP/1.1\r\n";
			$post 	.= "Host: $host\r\n";
			$post 	.= "Content-type: application/x-www-form-urlencoded\r\n";
			$post 	.= "Content-length: ".strlen($query)."\r\n";
			$post 	.= "Connection: close\r\n";
			$post 	.= "\r\n";
			$post 	.= $query;

			# open a socket
			$header = @fsockopen($host, $port);
			if(!$header)
			{
				# if the socket fails return failed
				return array('RESULT'=>'SOCKET_FAILED');
			}
			@fputs($header, $post);
			# read the returned data
			while (!@feof($header))
			{
				$return .= @fgets($header, 1024);
			}
			fclose($header);
			
			# seperate out the data using the delims
			$leftpos = strpos($return, $this->BEGIN2)+strlen($this->BEGIN2);
			$rightpos = strpos($return, $this->END2)-$leftpos;

			#trace($return);
			
			# decrypt and return the data
			return $this->_decrypt(substr($return, $leftpos, $rightpos), 'HOMEKEY');
		}

		/**
		* _compare_domain_ip
		*
		* uses the supplied domain in the key and runs a check against the collected
		* ip addresses. If there are matching ips it returns true as the domain
		* and ip address match up
		*
		* @access private 
  		* @return boolean
		**/
		function _compare_domain_ip($domain, $ips=false)
		{
			# if no ips are supplied get the ip addresses for the server
			if(!$ips) $ips = $this->_get_ip_address();
			# get the domain ip list
			$domain_ips = gethostbynamel($domain);
			# loop through the collected ip's searching for matches against the domain ips
			if(is_array($domain_ips) && count($domain_ips) > 0)
			{
				foreach($domain_ips as $ip)
				{
					if(in_array($ip, $ips)) return true;
				}
			}
			return false;
		}

		/**
		* _pad
		*
		* pad out the begin and end seperators
		*
		* @access private 
		* @param $str string The string to be padded
  		* @return string Returns the padded string
		**/
		function _pad($str)
		{
			$str_len 	= strlen($str);
			$spaces 	= ($this->_WRAPTO-$str_len)/2;
			$str1 = '';
			for($i=0; $i<$spaces; $i++)
			{
				$str1 = $str1.$this->_PAD;
			}
			if($spaces/2 != round($spaces/2))
			{
				$str = substr($str1, 0, strlen($str1)-1).$str;
			}
			else
			{
				$str = $str1.$str;
			}
			$str = $str.$str1;
			return $str;
		}
		
		/**
		* _get_key
		*
		* gets the hash key for the current encryption
		*
		* @access private 
		* @param $key_type string The license key type being produced
  		* @return string Returns the hash key
		**/
		function _get_key($key_type)
		{
			switch($key_type)
			{
				case 'KEY' :
					return $this->HASH_KEY1;
				case 'REQUESTKEY' :
					return $this->HASH_KEY2;
				case 'HOMEKEY' :
					return $this->HASH_KEY3;
				default :
			}
		}

		/**
		* _get_begin
		*
		* gets the begining license key seperator text
		*
		* @access private 
		* @param $key_type string The license key type being produced
  		* @return string Returns the begining string
		**/
		function _get_begin($key_type)
		{
			switch($key_type)
			{
				case 'KEY' :
					return $this->BEGIN1;
				case 'REQUESTKEY' :
					return $this->BEGIN2;
				case 'HOMEKEY' :
					return '';
			}
		}
		
		/**
		* _get_end
		*
		* gets the ending license key seperator text
		*
		* @access private 
		* @param $key_type string The license key type being produced
  		* @return string Returns the ending string
		**/
		function _get_end($key_type)
		{
			switch($key_type)
			{
				case 'KEY' :
					return $this->END1;
				case 'REQUESTKEY' :
					return $this->_END2;
				case 'HOMEKEY' :
					return '';
			}
		}
		
		/**
		* _generate_random_string
		*
		* generates a random string
		*
		* @access private 
		* @param $length number The length of the random string
		* @param $seeds string The string to pluck the characters from
  		* @return string Returns random string
		**/
		function _generate_random_string($length=10, $seeds='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234567890123456789')
		{
			$str = '';
			$seeds_count = strlen($seeds);
		
			list($usec, $sec) = explode(' ', microtime());
			$seed = (float) $sec + ((float) $usec * 100000);
			mt_srand($seed);
		
			for ($i = 0; $length > $i; $i++) {
				$str .= $seeds{mt_rand(0, $seeds_count - 1)};
			}
			return $str;
		}
		
		/**
		* _encrypt
		*
		* encrypts the key
		*
		* @access private 
		* @param $src_array array The data array that contains the key data
  		* @return string Returns the encrypted string
		**/
		function _encrypt($src_array, $key_type='KEY')
		{
			# check to see if the class has been secured
			$this->_check_secure();
			
			$rand_add_on = $this->_generate_random_string(3);
			# get the key
			$key 	= $this->_get_key($key_type);
			$key 	= $rand_add_on . $key;
			
			# check to see if mycrypt exists
			if($this->USE_MCRYPT)
			{
				# openup mcrypt
				$td 	= mcrypt_module_open($this->ALGORITHM, '', 'ecb', '');
				$iv 	= mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
				# process the key
				$key 	= substr($key, 0, mcrypt_enc_get_key_size($td));
				# init mcrypt
				mcrypt_generic_init($td, $key, $iv);
				
				# encrypt data
				# double base64 gets makes all the characters alpha numeric 
				# and gets rig of the special characters
				$crypt 	= mcrypt_generic($td, serialize($src_array));
			
				# shutdown mcrypt
				mcrypt_generic_deinit($td);
				mcrypt_module_close($td);
			}
			else
			{
				# if mcrypt doesn't exist use regular encryption method
				# init the vars
				$crypt = '';
				$str = serialize($src_array);
				
				# loop through the str and encrypt it
				for($i=1; $i<=strlen($str); $i++)
				{
					$char 		= substr($str, $i-1, 1);
					$keychar 	= substr($key, ($i % strlen($key))-1, 1);
					$char 		= chr(ord($char)+ord($keychar));
					$crypt		.= $char;
				}
				
			}
			# return the key
			return $rand_add_on.base64_encode(base64_encode(trim($crypt)));
		}
		
		/**
		* _decrypt
		*
		* decrypts the key
		*
		* @access private 
		* @param $enc_string string The key string that contains the data
  		* @return array Returns decrypted array
		**/
		function _decrypt($str, $key_type='KEY')
		{
			# check to see if the class has been secured
			$this->_check_secure();
			
			$rand_add_on = substr($str, 0, 3);
			$str = base64_decode(base64_decode(substr($str, 3)));
			# get the key
			$key 	= $rand_add_on . $this->_get_key($key_type);
			
			# check to see if mycrypt exists
			if($this->USE_MCRYPT)
			{
				# openup mcrypt
				$td 	= mcrypt_module_open($this->ALGORITHM, '', 'ecb', '');
				$iv 	= mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
				# process the key
				$key 	= substr($key, 0, mcrypt_enc_get_key_size($td));
				# init mcrypt
				mcrypt_generic_init($td, $key, $iv);
	
				# decrypt the data and return
				$decrypt = mdecrypt_generic($td, $str);
	
				# shutdown mcrypt
				mcrypt_generic_deinit($td);
				mcrypt_module_close($td);
			}
			else
			{
				# if mcrypt doesn't exist use regular decryption method
				# init the decrypt vars
				$decrypt 	= '';

				# loop through the text and decode the string
				for($i=1; $i<=strlen($str); $i++)
				{
					$char 		= substr($str, $i-1, 1);
					$keychar 	= substr($key, ($i % strlen($key))-1, 1);
					$char 		= chr(ord($char)-ord($keychar));
					$decrypt   .= $char;
				}
			}
			# return the key
			return unserialize($decrypt);
		}
		
		/**
		* _wrap_license
		*
		* wraps up the license key in a nice little package
		*
		* @access private 
		* @param $src_array array The array that needs to be turned into a license str
		* @param $key_type string The type of key to be wrapped (KEY=license key, REQUESTKEY=license request key)
  		* @return string Returns encrypted and formatted license key
		**/
		function _wrap_license($src_array, $key_type='KEY')
		{
			# sort the variables
			$begin 	= $this->_pad($this->_get_begin($key_type));
			$end 	= $this->_pad($this->_get_end($key_type));
			
			# encrypt the data
			$str 	= $this->_encrypt($src_array, $key_type);
			
			# return the wrap
			return $begin.$this->_LINEBREAK.wordwrap($str, $this->_WRAPTO, $this->_LINEBREAK, 1).$this->_LINEBREAK.$end;
		}
		
		/**
		* _unwrap_license
		*
		* unwraps license key back into it's data array
		*
		* @access private 
		* @param $enc_str string The encrypted license key string that needs to be decrypted
		* @param $key_type string The type of key to be unwrapped (KEY=license key, REQUESTKEY=license request key)
  		* @return array Returns license data array
		**/
		function _unwrap_license($enc_str, $key_type='KEY')
		{
			# sort the variables
			$begin 	= $this->_pad($this->_get_begin($key_type));
			$end 	= $this->_pad($this->_get_end($key_type));
			
			# get string without seperators
			$str 	= trim(str_replace(array($begin, $end, "\r", "\n", "\t"), '', $enc_str));

			# decrypt and return the key
			return $this->_decrypt($str, $key_type);
		}
		
		/**
		* make_secure
		*
		* deletes all class values to prevent re-writing of a key;
		*
		* @access public 
		**/
		function make_secure($report=false)
		{
			if($report) define('_PADL_REPORT_ABUSE_', true);
			# walkthrough and delete the class vars
			foreach(array_keys(get_object_vars($this)) as $value)
			{
				unset($this->$value);
			}
			# define that class is secure
			define('_PADL_SECURE_', 1);
		}
		
		/**
		* _check_secure
		*
		* checks to see if the class has been made secure
		*
		* @access private 
		**/
		function _check_secure()
		{
			# check to see if padl has been made secure
			if(defined('_PADL_SECURE_')) 
			{	
				# if(defined('_PADL_REPORT_ABUSE_')) $this->_post_data($this->_HOST, $this->_PATH, array());
				# trigger the error because user has attempted to access secured functions
				# after the call has been made to 'make_secure'
				trigger_error("<br /><br /><span style='color: #F00;font-weight: bold;'>The PHP Application Distribution License System (PADL) has been made secure.<br />You have attempted to use functions that have been protected and this has terminated your script.<br /><br /></span>", E_USER_ERROR);
				exit;
			}
		}
		
	}

	/**
	* custom functions to aid in debugging
	*
	* @var mixed
	*/
	function trace()
	{
		$message = '';
		for ($i=0; $i<func_num_args(); $i++) 
		{
			if(is_array(func_get_arg($i)))
			{
				trace_r(func_get_arg($i));
			}
			else
			{
				$message .= func_get_arg($i);
			}
			if($i <= func_num_args()-2)
			{
				$message.=' : ';
			}
		}
		echo "<br><b>\r\r".$message."\r\r</b>";
	}
	function trace_r($array="array is empty")
	{
		echo "<pre><b>\r\r";
		print_r($array);
		echo "\r\r</b></pre>";
	}
	
?>

 
  Advertise on this site Advertise on this site   Site map Site map   Statistics Statistics   Site tips Site tips   Privacy policy Privacy policy   Contact Contact  

For more information send a message to :
info at phpclasses dot org.
Copyright (c) Icontem 1999-2009 PHP Classes - PHP Class Scripts
  PHP Book Reviews - Reviews of books and other products