<?php
/**
* @version	$Id: globals.php 14519 2011-09-16 14:15:50Z alex $
* @package	In-Portal
* @copyright	Copyright (C) 1997 - 2009 Intechnic. All rights reserved.
* @license      GNU/GPL
* In-Portal is Open Source software.
* This means that this software may have been modified pursuant
* 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 http://www.in-portal.org/license for copyright notices and details.
*/

	defined('FULL_PATH') or die('restricted access!');

	if( !function_exists('array_merge_recursive2') ) {
		/**
		 * array_merge_recursive2()
		 *
		 * Similar to array_merge_recursive but keyed-valued are always overwritten.
		 * Priority goes to the 2nd array.
		 *
		 * @static yes
		 * @param $paArray1 array
		 * @param $paArray2 array
		 * @return array
		 * @access public
		 */
		function array_merge_recursive2($paArray1, $paArray2)
		{
			if (!is_array($paArray1) or !is_array($paArray2)) { return $paArray2; }
			foreach ($paArray2 AS $sKey2 => $sValue2)
			{
				$paArray1[$sKey2] = isset($paArray1[$sKey2]) ? array_merge_recursive2($paArray1[$sKey2], $sValue2) : $sValue2;
//				$paArray1[$sKey2] = array_merge_recursive2( getArrayValue($paArray1,$sKey2), $sValue2);
			}
			return $paArray1;
		}
	}

	/**
	 * @return int
	 * @param $array array
	 * @param $value mixed
	 * @desc Prepend a reference to an element to the beginning of an array. Renumbers numeric keys, so $value is always inserted to $array[0]
	 */
	function array_unshift_ref(&$array, &$value)
	{
		$return = array_unshift($array,'');
		$array[0] =& $value;
		return $return;
	}

	/**
	 * Same as print_r, budet designed for viewing in web page
	 *
	 * @param Array $data
	 * @param string $label
	 */
	function print_pre($data, $label='', $on_screen = false)
	{
		$is_debug = false;
		if (class_exists('kApplication') && !$on_screen) {
			$application =& kApplication::Instance();
			$is_debug = $application->isDebugMode();
		}

		if ($is_debug) {
			if ($label) $application->Debugger->appendHTML('<b>'.$label.'</b>');
			$application->Debugger->dumpVars($data);
		}
		else
		{
			if ($label) echo '<b>', $label, '</b><br>';
			echo '<pre>', print_r($data, true), '</pre>';
		}
	}

	/**
	 * Returns array value if key exists
	 *
	 * @param Array $array searchable array
	 * @param int $key array key
	 * @return string
	 * @access public
	 */
	//
	function getArrayValue(&$array, $key)
	{
//		global $debugger;
//		if (is_object($debugger)) $debugger->ProfilePoint('getArrayValue', 1);
		$ret = isset($array[$key]) ? $array[$key] : false;
		if ($ret && func_num_args() > 2) {
			for ($i = 2; $i < func_num_args(); $i++) {
				$cur_key = func_get_arg($i);
				$ret = getArrayValue( $ret, $cur_key );
				if ($ret === false) break;
			}
		}
		return $ret;
	}

	/**
	 * Rename key in associative array, maintaining keys order
	 *
	 * @param Array $array Associative Array
	 * @param mixed $old Old key name
	 * @param mixed $new New key name
	 * @access public
	 */
	function array_rename_key(&$array, $old, $new)
	{
		$new_array = Array ();
		foreach ($array as $key => $val) {
			$new_array[ $key == $old ? $new : $key] = $val;
		}

		$array = $new_array;
	}

	/**
	 * Define constant if it was not already defined before
	 *
	 * @param string $const_name
	 * @param string $const_value
	 * @access public
	 */
	function safeDefine($const_name, $const_value)
	{
		if(!defined($const_name)) define($const_name,$const_value);
	}

	function parse_portal_ini($parse_section = false)
	{
		$file = FULL_PATH . DIRECTORY_SEPARATOR . 'system' . DIRECTORY_SEPARATOR . 'config.php';

		if (!file_exists($file)) {
			return Array ();
		}

		if (file_exists($file) && !is_readable($file)) {
			die('Could Not Open Ini File');
		}

		$contents = file($file);

		if ($contents && $contents[0] == '<' . '?' . 'php die() ?' . ">\n") {
			// format of "config.php" file before 5.1.0 version
			array_shift($contents);

			return parse_ini_string(implode('', $contents), $parse_section);
		}

		$_CONFIG = Array ();
		require($file);

		if ($parse_section) {
			return $_CONFIG;
		}

		$ret = Array ();

		foreach ($_CONFIG as $section => $section_variables) {
			$ret = array_merge($ret, $section_variables);
		}

		return $ret;
	}

if ( !function_exists('parse_ini_string') ) {
	/**
	 * Equivalent for "parse_ini_string" function available since PHP 5.3.0
	 *
	 * @param string $ini
	 * @param bool $process_sections
	 * @param int $scanner_mode
	 * @return Array
	 */
	function parse_ini_string($ini, $process_sections = false, $scanner_mode = null)
	{
		# Generate a temporary file.
		$tempname = tempnam('/tmp', 'ini');
		$fp = fopen($tempname, 'w');
		fwrite($fp, $ini);
		$ini = parse_ini_file($tempname, !empty($process_sections));
		fclose($fp);
		@unlink($tempname);

		return $ini;
	}
}

if( !function_exists('getmicrotime') )
{
	function getmicrotime()
	{
	    list($usec, $sec) = explode(" ",microtime());
	    return ((float)$usec + (float)$sec);
	}
}

if( !function_exists('k4_include_once') )
{
	function k4_include_once($file)
	{
		global $debugger;
		if ( defined('DEBUG_MODE') && DEBUG_MODE && isset($debugger) && constOn('DBG_PROFILE_INCLUDES') )
		{

			if ( in_array($file, get_required_files()) ) return;
			global $debugger;

/*			$debugger->IncludeLevel++;
			$before_mem = memory_get_usage();
*/
			$debugger->ProfileStart('inc_'.crc32($file), $file);
			include_once($file);
			$debugger->ProfileFinish('inc_'.crc32($file));
			$debugger->profilerAddTotal('includes', 'inc_'.crc32($file));

/*			$used_mem = memory_get_usage() - $before_mem;
			$debugger->IncludeLevel--;
			$debugger->IncludesData['file'][] = str_replace(FULL_PATH, '', $file);
			$debugger->IncludesData['mem'][] = $used_mem;
			$debugger->IncludesData['time'][] = $used_time;
			$debugger->IncludesData['level'][] = $debugger->IncludeLevel;
*/

		}
		else
		{
			include_once($file);
		}
	}
}

	/**
	 * Checks if string passed is serialized array
	 *
	 * @param string $string
	 * @return bool
	 */
	function IsSerialized($string)
	{
		if( is_array($string) ) return false;
		return preg_match('/a:([\d]+):{/', $string);
	}

	if (!function_exists('makepassword4')){

		function makepassword4($length=10)
		{
		  $pass_length=$length;

		  $p1=array('b','c','d','f','g','h','j','k','l','m','n','p','q','r','s','t','v','w','x','y','z');
		  $p2=array('a','e','i','o','u');
		  $p3=array('1','2','3','4','5','6','7','8','9');
		  $p4=array('(','&',')',';','%');    // if you need real strong stuff

		  // how much elements in the array
		  // can be done with a array count but counting once here is faster

		  $s1=21;// this is the count of $p1
		  $s2=5; // this is the count of $p2
		  $s3=9; // this is the count of $p3
		  $s4=5; // this is the count of $p4

		  // possible readable combinations

		  $c1='121';    // will be like 'bab'
		  $c2='212';      // will be like 'aba'
		  $c3='12';      // will be like 'ab'
		  $c4='3';        // will be just a number '1 to 9'  if you dont like number delete the 3
		// $c5='4';        // uncomment to active the strong stuff

		  $comb='4'; // the amount of combinations you made above (and did not comment out)

		  for ($p=0;$p<$pass_length;)
		  {
		    mt_srand((double)microtime()*1000000);
		    $strpart=mt_rand(1,$comb);
		    // checking if the stringpart is not the same as the previous one
		    if($strpart<>$previous)
		    {
		      $pass_structure.=${'c'.$strpart};

		      // shortcutting the loop a bit
		      $p=$p+mb_strlen(${'c'.$strpart});
		    }
		    $previous=$strpart;
		  }


		  // generating the password from the structure defined in $pass_structure
		  for ($g=0;$g<mb_strlen($pass_structure);$g++)
		  {
		    mt_srand((double)microtime()*1000000);
		    $sel=mb_substr($pass_structure,$g,1);
		    $pass.=${'p'.$sel}[mt_rand(0,-1+${'s'.$sel})];

		  }
		  return $pass;
		}
	}

	if( !function_exists('unhtmlentities') )
	{
		function unhtmlentities($string)
		{
			$trans_tbl = get_html_translation_table(HTML_ENTITIES);
			$trans_tbl = array_flip ($trans_tbl);
			return strtr($string, $trans_tbl);
		}
	}

	if( !function_exists('curl_post') )
	{
		/**
		 * submits $url with $post as POST
		 *
		 * @param string $url
		 * @param unknown_type $post
		 * @return unknown
		 */
		function curl_post($url, $post, $headers=null, $request_type = 'POST', $curl_options=null)
		{
			if( is_array($post) )
			{
				$params_str = '';
				foreach($post as $key => $value) $params_str .= $key.'='.urlencode($value).'&';
				$post = $params_str;
			}

			$ch = curl_init($url);

			$dbg = false;
			if (defined('DEBUG_MODE') && DEBUG_MODE && constOn('DBG_CURL')) {
				$dbg = true;
				safeDefine('DBG_CURL_LOGFILE', '/curl.log');
				$log = fopen(FULL_PATH.DBG_CURL_LOGFILE, 'a');

				curl_setopt($ch, CURLOPT_FILE, $log);
				curl_setopt($ch, CURLOPT_VERBOSE, TRUE);
				curl_setopt($ch, CURLOPT_STDERR, $log);
				//curl_setopt($ch, CURLOPT_WRITEHEADER, $log);
			}

			if (!is_null($headers)) {
				curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
			}

			// if we have post data, then POST else use GET method instead
			if ($request_type == 'POST') {
				curl_setopt($ch, CURLOPT_POST, 1);
				curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
			}
			elseif ($request_type == 'GET' && isset($post) && strlen($post) > 0) {
				curl_setopt($ch, CURLOPT_URL, preg_match('/\?/', $url) ? $url.'&'.$post : $url.'?'.$post);
			}

			curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

			curl_setopt($ch,CURLOPT_REFERER, PROTOCOL.SERVER_NAME);

			if ( isset($_SERVER['HTTP_USER_AGENT']) ) {
				curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']);
			}

			curl_setopt($ch,CURLOPT_FOLLOWLOCATION, 0);
			curl_setopt($ch, CURLOPT_TIMEOUT, 90);

			if (is_array($curl_options)) {
				foreach ($curl_options as $option => $value) {
					curl_setopt($ch, $option, $value);
				}
			}
			$ret = curl_exec($ch);
			$GLOBALS['curl_errorno'] = curl_errno($ch);
			$GLOBALS['curl_error'] = curl_error($ch);
			curl_close($ch);

			if ($dbg) {
				fwrite($log, "\n".$ret);
				fclose($log);
			}

			return $ret;
		}
	}

	if( !function_exists('memory_get_usage') )
	{
		function memory_get_usage(){ return -1;	}
	}

	function &ref_call_user_func_array($callable, $args)
	{
		if( is_scalar($callable) )
		{
			// $callable is the name of a function
			$call = $callable;
		}
		else
		{
			if( is_object($callable[0]) )
			{
				// $callable is an object and a method name
				$call = "\$callable[0]->{$callable[1]}";
			}
			else
			{
				// $callable is a class name and a static method
				$call = "{$callable[0]}::{$callable[1]}";
			}
		}

		// Note because the keys in $args might be strings
		// we do this in a slightly round about way.
		$argumentString = Array();
		$argumentKeys = array_keys($args);
		foreach($argumentKeys as $argK)
		{
			$argumentString[] = "\$args[$argumentKeys[$argK]]";
		}
		$argumentString = implode($argumentString, ', ');
		// Note also that eval doesn't return references, so we
		// work around it in this way...
		eval("\$result =& {$call}({$argumentString});");
		return $result;
	}

	/**
	 * Checks if constant is defined and has positive value
	 *
	 * @param string $const_name
	 * @return bool
	 */
	function constOn($const_name)
	{
		return defined($const_name) && constant($const_name);
	}

	function Kg2Pounds($kg, $pounds_only = false)
	{
		$major = floor( round($kg / POUND_TO_KG, 3) );
		$minor = abs(round(($kg - $major * POUND_TO_KG) / POUND_TO_KG * 16, 2));
		if ($pounds_only) {
			$major += round($minor * 0.0625, 2);
			$minor = 0;
		}
		return array($major, $minor);
	}

	function Pounds2Kg($pounds, $ounces=0)
	{
		return round(($pounds + ($ounces / 16)) * POUND_TO_KG, 5);
	}

	/**
	 * Formats file/memory size in nice way
	 *
	 * @param int $bytes
	 * @return string
	 * @access public
	 */
	function formatSize($bytes)
	{
		if ($bytes >= 1099511627776) {
			$return = round($bytes / 1024 / 1024 / 1024 / 1024, 2);
			$suffix = "TB";
		} elseif ($bytes >= 1073741824) {
			$return = round($bytes / 1024 / 1024 / 1024, 2);
			$suffix = "GB";
		} elseif ($bytes >= 1048576) {
			$return = round($bytes / 1024 / 1024, 2);
			$suffix = "MB";
		} elseif ($bytes >= 1024) {
			$return = round($bytes / 1024, 2);
			$suffix = "KB";
		} else {
			$return = $bytes;
			$suffix = "Byte";
		}
		$return .= ' '.$suffix;
		return $return;
	}

	/**
	 * Enter description here...
	 *
	 * @param resource $filePointer the file resource to write to
	 * @param Array $data the data to write out
	 * @param string $delimiter the field separator
	 * @param string $enclosure symbol to enclose field data to
	 * @param string $recordSeparator symbols to separate records with
	 */
	function fputcsv2($filePointer, $data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
	{
		foreach($data as $field_index => $field_value) {
			// replaces an enclosure with two enclosures
			$data[$field_index] = str_replace($enclosure, $enclosure.$enclosure, $field_value);
		}

		$line = $enclosure.implode($enclosure.$delimiter.$enclosure, $data).$enclosure.$recordSeparator;
		$line = preg_replace('/'.preg_quote($enclosure, '/').'([0-9\.]+)'.preg_quote($enclosure, '/').'/', '$1', $line);
		fwrite($filePointer, $line);
	}

	/**
	 * Enter description here...
	 *
	 * @param resource $filePointer the file resource to write to
	 * @param Array $data the data to write out
	 * @param string $delimiter the field separator
	 * @param string $enclosure symbol to enclose field data to
	 * @param string $recordSeparator symbols to separate records with
	 */
	function getcsvline($data, $delimiter = ',', $enclosure = '"', $recordSeparator = "\r\n")
	{
		foreach($data as $field_index => $field_value) {
			// replaces an enclosure with two enclosures
			$data[$field_index] = str_replace($enclosure, $enclosure.$enclosure, $field_value);
		}
		$line = $enclosure.implode($enclosure.$delimiter.$enclosure, $data).$enclosure.$recordSeparator;
		$line = preg_replace('/'.preg_quote($enclosure, '/').'([0-9\.]+)'.preg_quote($enclosure, '/').'/', '$1', $line);
		return $line;
	}
	/**
	 * Allows to replace #section# within any string with current section
	 *
	 * @param string $string
	 * @return string
	 */
	function replaceModuleSection($string)
	{
		$application =& kApplication::Instance();
		$module_section = $application->RecallVar('section');
		if ($module_section) {
			// substitute section instead of #section# parameter in title preset name
			$module_section = explode(':', $module_section);
			$section = preg_replace('/(configuration|configure)_(.*)/i', '\\2', $module_section[count($module_section) == 2 ? 1 : 0]);
			$string = str_replace('#section#', mb_strtolower($section), $string);
		}
		return $string;
	}

	/**
	 * Checks, that user IP address is within allowed range
	 *
	 * @param string $ip_list semi-column (by default) separated ip address list
	 * @param string $separator ip address separator (default ";")
	 *
	 * @return bool
	 */
	function ipMatch($ip_list, $separator = ';')
	{
		if ( !isset($_SERVER['REMOTE_ADDR']) ) {
			return false;
		}

		$ip_match = false;
		$ip_addresses = $ip_list ? explode($separator, $ip_list) : Array ();
		foreach ($ip_addresses as $ip_address) {
			if (netMatch($ip_address, $_SERVER['REMOTE_ADDR'])) {
				$ip_match = true;
				break;
			}
		}

		return $ip_match;
	}

	function netMatch($network, $ip)
	{
		$network = trim($network);
		$ip = trim($ip);

		if ( preg_replace('/[\d\.\/-]/', '', $network) != '' ) {
			$network = gethostbyname($network);
		}

		if ($network == $ip) {
			// comparing two ip addresses directly
			return true;
		}

		$d = strpos($network, '-');
		if ($d !== false) {
			// ip address range specified
			$from = ip2long(trim(substr($network, 0, $d)));
			$to = ip2long(trim(substr($network, $d + 1)));

			$ip = ip2long($ip);
			return ($ip >= $from && $ip <= $to);
		}
		elseif (strpos($network, '/') !== false) {
			// sigle subnet specified
			$ip_arr = explode('/', $network);

			if (!preg_match("@\d*\.\d*\.\d*\.\d*@", $ip_arr[0], $matches)) {
				$ip_arr[0] .= '.0';    // Alternate form 194.1.4/24
			}

			$network_long = ip2long($ip_arr[0]);
			$x = ip2long($ip_arr[1]);

			$mask = long2ip($x) == $ip_arr[1] ? $x : (0xffffffff << (32 - $ip_arr[1]));
			$ip_long = ip2long($ip);

			return ($ip_long & $mask) == ($network_long & $mask);
		}

		return false;
	}

	function request_headers()
	{
		if(function_exists("apache_request_headers")) // If apache_request_headers() exists...
		{
			if($headers = apache_request_headers()) // And works...
			{
				return $headers; // Use it
			}
		}

		$headers = array();

		foreach(array_keys($_SERVER) as $skey)
		{
			if(substr($skey, 0, 5) == "HTTP_")
			{
				$headername = str_replace(" ", "-", ucwords(strtolower(str_replace("_", " ", substr($skey, 0, 5)))));
				$headers[$headername] = $_SERVER[$skey];
			}
		}

		return $headers;
	}

	if (!function_exists('easter_date')) {
		// calculates easter date, when calendar extension not installed in php
		// see also: http://php.prod.intechnic.lv/manual/en/function.easter-date.php
		function easter_date ($Year) {
			/*
			G is the Golden Number-1
			H is 23-Epact (modulo 30)
			I is the number of days from 21 March to the Paschal full moon
			J is the weekday for the Paschal full moon (0=Sunday,
			1=Monday, etc.)
			L is the number of days from 21 March to the Sunday on or before
			the Paschal full moon (a number between -6 and 28)
			*/


			$G = $Year % 19;
			$C = (int)($Year / 100);
			$H = (int)($C - ($C / 4) - ((8*$C+13) / 25) + 19*$G + 15) % 30;
			$I = (int)$H - (int)($H / 28)*(1 - (int)($H / 28)*(int)(29 / ($H + 1))*((int)(21 - $G) / 11));
			$J = ($Year + (int)($Year/4) + $I + 2 - $C + (int)($C/4)) % 7;
			$L = $I - $J;
			$m = 3 + (int)(($L + 40) / 44);
			$d = $L + 28 - 31 * ((int)($m / 4));
			$y = $Year;
			$E = mktime(0,0,0, $m, $d, $y);

			return $E;
		}
	}

	if (!function_exists('imagecreatefrombmp')) {
		// just in case if GD will add this function in future
		function imagecreatefrombmp($filename)
		{
			//Ouverture du fichier en mode binaire
			if (! $f1 = fopen($filename,"rb")) return FALSE;

			//1 : Chargement des ent�tes FICHIER
			$FILE = unpack("vfile_type/Vfile_size/Vreserved/Vbitmap_offset", fread($f1,14));
			if ($FILE['file_type'] != 19778) return FALSE;

			//2 : Chargement des ent�tes BMP
			$BMP = unpack('Vheader_size/Vwidth/Vheight/vplanes/vbits_per_pixel'.
			'/Vcompression/Vsize_bitmap/Vhoriz_resolution'.
			'/Vvert_resolution/Vcolors_used/Vcolors_important', fread($f1,40));
			$BMP['colors'] = pow(2,$BMP['bits_per_pixel']);
			if ($BMP['size_bitmap'] == 0) $BMP['size_bitmap'] = $FILE['file_size'] - $FILE['bitmap_offset'];
			$BMP['bytes_per_pixel'] = $BMP['bits_per_pixel']/8;
			$BMP['bytes_per_pixel2'] = ceil($BMP['bytes_per_pixel']);
			$BMP['decal'] = ($BMP['width']*$BMP['bytes_per_pixel']/4);
			$BMP['decal'] -= floor($BMP['width']*$BMP['bytes_per_pixel']/4);
			$BMP['decal'] = 4-(4*$BMP['decal']);
			if ($BMP['decal'] == 4) $BMP['decal'] = 0;

			//3 : Chargement des couleurs de la palette
			$PALETTE = array();
			if ($BMP['colors'] < 16777216)
			{
				$PALETTE = unpack('V'.$BMP['colors'], fread($f1,$BMP['colors']*4));
			}

			//4 : Cr�ation de l'image
			$IMG = fread($f1,$BMP['size_bitmap']);
			$VIDE = chr(0);

			$res = imagecreatetruecolor($BMP['width'],$BMP['height']);
			$P = 0;
			$Y = $BMP['height']-1;
			while ($Y >= 0)
			{
				$X=0;
				while ($X < $BMP['width'])
				{
					if ($BMP['bits_per_pixel'] == 24)
					$COLOR = unpack("V",substr($IMG,$P,3).$VIDE);
					elseif ($BMP['bits_per_pixel'] == 16)
					{
						$COLOR = unpack("n",substr($IMG,$P,2));
						$COLOR[1] = $PALETTE[$COLOR[1]+1];
					}
					elseif ($BMP['bits_per_pixel'] == 8)
					{
						$COLOR = unpack("n",$VIDE.substr($IMG,$P,1));
						$COLOR[1] = $PALETTE[$COLOR[1]+1];
					}
					elseif ($BMP['bits_per_pixel'] == 4)
					{
						$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
						if (($P*2)%2 == 0) $COLOR[1] = ($COLOR[1] >> 4) ; else $COLOR[1] = ($COLOR[1] & 0x0F);
						$COLOR[1] = $PALETTE[$COLOR[1]+1];
					}
					elseif ($BMP['bits_per_pixel'] == 1)
					{
						$COLOR = unpack("n",$VIDE.substr($IMG,floor($P),1));
						if     (($P*8)%8 == 0) $COLOR[1] =  $COLOR[1]        >>7;
						elseif (($P*8)%8 == 1) $COLOR[1] = ($COLOR[1] & 0x40)>>6;
						elseif (($P*8)%8 == 2) $COLOR[1] = ($COLOR[1] & 0x20)>>5;
						elseif (($P*8)%8 == 3) $COLOR[1] = ($COLOR[1] & 0x10)>>4;
						elseif (($P*8)%8 == 4) $COLOR[1] = ($COLOR[1] & 0x8)>>3;
						elseif (($P*8)%8 == 5) $COLOR[1] = ($COLOR[1] & 0x4)>>2;
						elseif (($P*8)%8 == 6) $COLOR[1] = ($COLOR[1] & 0x2)>>1;
						elseif (($P*8)%8 == 7) $COLOR[1] = ($COLOR[1] & 0x1);
						$COLOR[1] = $PALETTE[$COLOR[1]+1];
					}
					else
					return FALSE;
					imagesetpixel($res,$X,$Y,$COLOR[1]);
					$X++;
					$P += $BMP['bytes_per_pixel'];
				}
				$Y--;
				$P+=$BMP['decal'];
			}

			//Fermeture du fichier
			fclose($f1);

			return $res;
		}
	}