<?php
defined('VSIGN') or die("Sorry, you are not allowed to directly access this page.<br /> Please press the back button in your browser.");
  
define('_SESSION', "session");
define('_POST', "post");
define('_GET', "get");
define('_REQUEST', "request");

define('_STRING', "string");
define('_HTMLSTRING', 'htmlstring');
define('_PASSWORD', "password");
define('_INT', "int");
define('_DOUBLE', "double");
define('_BOOL', "bool");
define('_WORD', "word");
define('_ARRAY', "array");
define('_USERNAME', "username");
define('_CHECKBOX', "checkbox");
define('_FILENAME', "filename");
define('_URI', "uri");
define('_INPUTBOX', "inputbox");
define('_PASSWORDBOX', "password");

class Kit 
{
	// Ends the current execution and issues a redirect - should only be called before headers have been sent (i.e. no output)
	static function Redirect($page, $message = '', $pageIsUrl = false)
	{
		$url 	= $page;
		$ajax 	= Kit::GetParam('ajax', _REQUEST, _BOOL, false);
		
		if ($ajax)
		{
			echo json_encode($page);
			die();
		}
		
		// Header or JS redirect
		if (headers_sent()) 
		{
			echo "<script>document.location.href='$url';</script>\n";
		} 
		else 
		{
			header( 'HTTP/1.1 301 Moved Permanently' );
			header( 'Location: ' . $url );
		}
		
		die();
	}
	
	/**
	 * Gets the appropriate Param, making sure its valid
	 * Based on code from Joomla! 1.5
	 * @return 
	 * @param $param Object
	 * @param $source Object[optional]
	 * @param $type Object[optional]
	 * @param $default Object[optional]
	 */
	static public function GetParam($param, $source = _POST, $type = _STRING, $default = '')
	{
		if (is_array($source))
		{
			if(!isset($source[$param])) 
			{
				$return = $default;
			}
			else 
			{
				$return = $source[$param];	
			}
		}
		else
		{
			switch ($source)
			{
				case 'session':
				
					if(!isset($_SESSION[$param])) 
					{
						$return = $default;
					}
					else if ($type == _CHECKBOX)
					{
						// this means that it was defined correctly and it was set
						$return = 1;
					}
					else 
					{
						if ($_SESSION[$param] == '')
						{
							$return = $default;
						} 
						else
						{
							$return = $_SESSION[$param];
						}
					}
				
					break;
				
				case 'request':
				
					if(!isset($_REQUEST[$param])) 
					{
						$return = $default;
					}
					else 
					{
						if ($_REQUEST[$param] == '')
						{
							$return = $default;
						} 
						else
						{
							$return = $_REQUEST[$param];
						}	
					}
				
					break;
					
				case 'get':
				
					if(!isset($_GET[$param])) 
					{
						$return = $default;
					}
					else 
					{
						if ($_GET[$param] == '')
						{
							$return = $default;
						} 
						else
						{
							$return = $_GET[$param];
						}		
					}
				
					break;
					
				case 'post':
		
					if(!isset($_POST[$param])) 
					{
						$return = $default;
					}
					else if ($type == _CHECKBOX)
					{
						// this means that it was defined correctly and it was set
						$return = 1;
					}
					else 
					{
						if ($_POST[$param] == '')
						{
							$return = $default;
						} 
						else
						{
							$return = $_POST[$param];
						}		
					}
				
					break;
				
				default:
					return $default;
			}
		}
		
		// Validate this param	
		return Kit::ValidateParam($return, $type);
	}
	
	/**
	 * Validates a Parameter
	 * Based on code from Joomla! 1.5
	 * @return 
	 * @param $param Object
	 * @param $type Object
	 */
	static function ValidateParam($param, $type)
	{
		// If we are a NULL always return a null
		$return = $param;
		
		// Validate
		// Handle the type constraint
		switch ($type)
		{
			case _INT :
				// Only use the first integer value
				if ($return == '')
                                    return 0;
				
				if (preg_match('/-?[0-9]+/', $return, $matches) == 0)
                                    trigger_error(sprintf(__('No integer match found for %s, and return value is not an int'), $param), E_USER_ERROR);

				$return = @ (int) $matches[0];
				break;

			case _DOUBLE :
				if ($return == '')
				{
					$return = 0;
					break;	
				}
				
				// Only use the first floating point value
				@ preg_match('/-?[0-9]+(\.[0-9]+)?/', $return, $matches);
				$return = @ (float) $matches[0];
				break;

			case _BOOL :
				$return = (bool) $return;
				break;

			case _ARRAY :
				if ($return == '')
				{
					$return = array();
					break;	
				}
				
				if (!is_array($return)) 
				{
					$return = array ($return);
				}
				break;

			case _STRING :
			case _PASSWORD :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				
				$return = preg_replace('/&#(\d+);/me', "chr(\\1)", $return); // decimal notation
				// convert hex
				$return = preg_replace('/&#x([a-f0-9]+);/mei', "chr(0x\\1)", $return); // hex notation
				$return = (string) $return;
				break;
				
			case _HTMLSTRING :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				
				$return = preg_replace('/&#(\d+);/me', "chr(\\1)", $return); // decimal notation
				// convert hex
				$return = preg_replace('/&#x([a-f0-9]+);/mei', "chr(0x\\1)", $return); // hex notation
				$return = (string) $return;
				break;

			case _WORD :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				
				$return = (string) preg_replace( '/[^A-Z_]\\-/i', '', $return );
				break;
				
			case _USERNAME :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				
				$return = (string) preg_replace( '/[\x00-\x1F\x7F<>"\'%&]/', '', $return );
				$return	= strtolower($return);
				break;
				
			case _FILENAME :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				// Remove non alphanumerics
				$return = strtolower($return); 
				$code_entities_match 	= array('&quot;' ,'!' ,'@' ,'#' ,'$' ,'%' ,'^' ,'&' ,'*' ,'(' ,')' ,'+' ,'{' ,'}' ,'|' ,':' ,'"' ,'<' ,'>' ,'?' ,'[' ,']' ,'' ,';' ,"'" ,',' ,'_' ,'/' ,'*' ,'+' ,'~' ,'`' ,'=' ,' ' ,'---' ,'--','--'); 
				$code_entities_replace 	= array('' ,'-' ,'-' ,'' ,'' ,'' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-' ,'' ,'' ,'' ,'' ,'' ,'-' ,'-' ,'-','-'); 
	
				$return = str_replace($code_entities_match, $code_entities_replace, $return);
				break;
				
			case _URI :
				if ($return == '')
				{
					$return = '';
					break;	
				}
				$return = urlencode($return);
				break;
				
			case _CHECKBOX:
				if ($return == 'on') $return = 1;
				if ($return == 'off' || $return == '') $return = 0;

			default :
				// No casting necessary
				break;
		}
		
		return $return;
	}
	
	/**
	 * Gets a formatted Url
	 * @return 
	 * @param $page Object[optional]
	 */
	public static function GetURL($page = "")
	{
		$page = $this->ValidateParam($page, _WORD);
		$fullUrl = 'http';
		
		if(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')
		{
			$fullUrl .=  's';
		}
		
		$fullUrl .=  '://';
		
		if($_SERVER['SERVER_PORT']!='80')
		{
			$fullUrl .=  $_SERVER['HTTP_HOST'].':'.$_SERVER['SERVER_PORT'].$_SERVER['SCRIPT_NAME'];
		}
		else
		{
			$fullUrl .=  $_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
		}
		
		// Append the page if its not empty
		if ($page != '')
		{
			$fullUrl .= '?p=' . $page;
		}
		
		return $fullUrl;
	}

        /**
         * Ensures a the relevant file for a class is inclued
         * @param <string> $class
         * @return <boolean> False on failure
         */
        static function ClassLoader($class)
	{
            if (class_exists($class))
                return;

            $class = strtolower($class);

            // It doesnt already exist - so lets look in some places to try and find it
            if (file_exists('lib/pages/' . $class . '.class.php'))
            {
                include_once('lib/pages/' . $class . '.class.php');
            }

            if (file_exists('lib/data/' . $class . '.data.class.php'))
            {
                include_once('lib/data/' . $class . '.data.class.php');
            }

            if (file_exists('modules/' . $class . '.module.php'))
            {
                include_once('modules/' . $class . '.module.php');
            }

            if (file_exists('modules/' . $class . '.php'))
            {
                include_once('modules/' . $class . '.php');
            }

            if (file_exists('lib/service/' . $class . '.class.php'))
            {
                include_once('lib/service/' . $class . '.class.php');
            }
	}

    /**
     * GetVsignRoot
     * @return <string> The Root of the VSign installation
     */
    public static function GetVsignRoot()
    {

        # Check REQUEST_URI is set. IIS doesn't set it so we need to build it
        # Attribution:
        # Code snippet from http://support.ecenica.com/web-hosting/scripting/troubleshooting-scripting-errors/how-to-fix-server-request_uri-php-error-on-windows-iis/
        # Released under BSD License
        # Copyright (c) 2009, Ecenica Limited All rights reserved.
        if (!isset($_SERVER['REQUEST_URI']))
        {
            $_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'];
            if (isset($_SERVER['QUERY_STRING']))
            {
                $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING'];
            }
        }
        ## End Code Snippet

        $request = explode('?', $_SERVER['REQUEST_URI']);

        $fullUrl = 'http';
        
        if(isset($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) == 'on')
        {
            $fullUrl .=  's';
        }

        $fullUrl .=  '://';

        if($_SERVER['SERVER_PORT']!='80')
        {
            $fullUrl .=  $_SERVER['SERVER_NAME'].':'.$_SERVER['SERVER_PORT'];
        }
        else
        {
            $fullUrl .=  $_SERVER['SERVER_NAME'];
        }

        return $fullUrl . $request[0];
    }

    /**
     * Gets the Current page, optionally with arguments.
     */
    public static function GetCurrentPage()
    {

        # Check REQUEST_URI is set. IIS doesn't set it so we need to build it
        # Attribution:
        # Code snippet from http://support.ecenica.com/web-hosting/scripting/troubleshooting-scripting-errors/how-to-fix-server-request_uri-php-error-on-windows-iis/
        # Released under BSD License
        # Copyright (c) 2009, Ecenica Limited All rights reserved.
        if (!isset($_SERVER['REQUEST_URI']))
        {
            $_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'];
            if (isset($_SERVER['QUERY_STRING']))
            {
                $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING'];
            }
        }
        ## End Code Snippet

        $request = explode('?', $_SERVER['REQUEST_URI']);

        if (isset($request[1]))
            return $request[1];

        return '';
    }

    /**
     * Sends an email alert
     */
    public static function SendEmail($to, $from, $subject, $message)
    {
        $headers  = sprintf("From: %s\r\nX-Mailer: php", $from);
        return mail($to, $subject, $message, $headers);
    }

    public static function SelectList($listName, $listValues, $idColumn, $nameColumn, $selectedId = '', $callBack = '')
    {
        $list = '<select name="' . $listName . '" id="' . $listName . '"' . $callBack . '>';

        foreach ($listValues as $listItem)
        {
            $list .= '<option value="' . $listItem[$idColumn] . '" ' . (($listItem[$idColumn] == $selectedId) ? 'selected' : '') . '>' . $listItem[$nameColumn] . '</option>';
        }

        $list .= '</select>';

        return $list;
    }

    	/**
	* Table for encoding base32
	*
	* @var array
	*/
	private static $encode = array(
        0 => 'A',
        1 => 'B',
        2 => 'C',
        3 => 'D',
        4 => 'E',
        5 => 'F',
        6 => 'G',
        7 => 'H',
        8 => 'I',
        9 => 'J',
        10 => 'K',
        11 => 'L',
        12 => 'M',
        13 => 'N',
        14 => 'O',
        15 => 'P',
        16 => 'Q',
        17 => 'R',
        18 => 'S',
        19 => 'T',
        20 => 'U',
        21 => 'V',
        22 => 'W',
        23 => 'X',
        24 => 'Y',
        25 => 'Z',
        26 => 2,
        27 => 3,
        28 => 4,
        29 => 5,
        30 => 6,
        31 => 7,
        32 => '=',
    );

	/**
	* Table for decoding base32
	*
	* @var array
	*/
	private static $decode = array(
        'A' => 0,
        'B' => 1,
        'C' => 2,
        'D' => 3,
        'E' => 4,
        'F' => 5,
        'G' => 6,
        'H' => 7,
        'I' => 8,
        'J' => 9,
        'K' => 10,
        'L' => 11,
        'M' => 12,
        'N' => 13,
        'O' => 14,
        'P' => 15,
        'Q' => 16,
        'R' => 17,
        'S' => 18,
        'T' => 19,
        'U' => 20,
        'V' => 21,
        'W' => 22,
        'X' => 23,
        'Y' => 24,
        'Z' => 25,
        2 => 26,
        3 => 27,
        4 => 28,
        5 => 29,
        6 => 30,
        7 => 31,
        '=' => 32,
    );

	/**
	* Creates an array from a binary string into a given chunk size
	*
	* @param string $binaryString String to chunk
	* @param integer $bits Number of bits per chunk
	* @return array
	*/
	private static function chunk($binaryString, $bits)
	{
		$binaryString = chunk_split($binaryString, $bits, ' ');

		if (substr($binaryString, (strlen($binaryString)) - 1) == ' ') {
		$binaryString = substr($binaryString, 0, strlen($binaryString)-1);
		}

		return explode(' ', $binaryString);
	}

	/**
	* Encodes into base32
	*
	* @param string $string Clear text string
	* @return string Base32 encoded string
	*/
	public static function base32_encode($string)
	{
		if (strlen($string) == 0) {
			// Gives an empty string
			return '';
		}

		// Convert string to binary
		$binaryString = '';

		foreach (str_split($string) as $s) {
			// Return each character as an 8-bit binary string
			$s = decbin(ord($s));
			$binaryString .= str_pad($s, 8, 0, STR_PAD_LEFT);
		}

		// Break into 5-bit chunks, then break that into an array
		$binaryArray = self::chunk($binaryString, 5);

		// Pad array to be divisible by 8
		while (count($binaryArray) % 8 !== 0) {
			$binaryArray[] = null;
		}

		$base32String = '';

		// Encode in base32
		foreach ($binaryArray as $bin) {
			$char = 32;

			if (!is_null($bin)) {
				// Pad the binary strings
				$bin = str_pad($bin, 5, 0, STR_PAD_RIGHT);
				$char = bindec($bin);
			}

			// Base32 character
			$base32String .= self::$encode[$char];
		}

		return $base32String;
	}

	/**
	* Decodes base32
	*
	* @param string $base32String Base32 encoded string
	* @return string Clear text string
	*/
	public static function base32_decode($base32String)
	{
		if (strlen($base32String) == 0) {
			// Gives an empty string
			return '';
		}
		//return strlen($base32String);

		// Only work in upper cases
		$base32String = strtoupper($base32String);

		// Remove anything that is not base32 alphabet
		$pattern = '/[^A-Z2-7]/';
		$replacement = '';

		$base32Array = str_split($base32String);

		$binaryArray = array();
		$string = '';

		foreach ($base32Array as $str) {
			// dari lookup table, dicari nilai desimalnya
			$char = self::$decode[$str];

			// Ignore the padding character
			if ($char !== 32) {
				// ubah representasinya menjadi teks biner panjang 5 karakter
				$char = decbin($char);
				// sambung-sambungkan
				$string .= str_pad($char, 5, 0, STR_PAD_LEFT);
			}
		}

		// panjang total harus kelipatan 8, buang sisanya
		while (strlen($string) %8 !== 0) {
			$string = substr($string, 0, strlen($string)-1);
		}

		// potong sehingga kelipatan 8
		$binaryArray = self::chunk($string, 8);

		$realString = '';

		foreach ($binaryArray as $bin) {
			// Pad each value to 8 bits
			$bin = str_pad($bin, 8, 0, STR_PAD_RIGHT);
			// Convert binary strings to ascii
			$realString .= chr(bindec($bin));
		}

		// use iconv to prevent invalid input crash the system
		return iconv("UTF-8", "UTF-8//IGNORE", $realString);
	}
}
?>
