Current File : //proc/self/root/var/softaculous/sitepad/editor/site-inc/sitepad_functions2.php
<?php

/**
 * Part of sitemush DB changing
 * This is just below $wpdb connection
 * By Default we connect to sitemush DB to verify session
 */

// We need the ABSPATH
if (!defined('ABSPATH')) exit;

global $sitepad, $globals, $l, $SESS;
	
function cleanpath($path){
	$path = str_replace('\\\\', '/', $path);
	$path = str_replace('\\', '/', $path);
	$path = str_replace('//', '/', $path);
	return rtrim($path, '/');
}

function r_print($array){

	echo '<pre>';
	print_r($array);
	echo '</pre>';

}


// Generate a random string
function generateRandStr($length = 10){
	$characters = '0123456789abcdefghijklmnopqrstuvwxyz';
	$charactersLength = strlen($characters);
	$randomString = '';
	for($i = 0; $i < $length; $i++){
		$randomString .= $characters[rand(0, $charactersLength - 1)];
	}
	return $randomString;
}

// Connect to the database
function soft_mysql_connect($host, $user, $pass, $newlink = false){
	
	// Error handling for php8.1
	try{
		if(extension_loaded('mysqli')){
			//echo 'mysqli';
			$sconn = @mysqli_connect($host, $user, $pass);
		}else{
			//echo 'mysql';
			$sconn = @mysql_connect($host, $user, $pass, $newlink);
		}
		
	}catch(Exception $e){
		return false;
	}

	return $sconn;
}

// Select the DB
function soft_mysql_select_db($db, $conn){
	// Error handling for php8.1
	try{
		if(extension_loaded('mysqli')){
			$return = @mysqli_select_db($conn, $db);
		}else{
			$return = @mysql_select_db($db, $conn);
		}
		
	}catch(Exception $e){
		return false;
	}
	
	return $return;
}


// Verifies an email
function emailvalidation($email){

	if(!preg_match("/^([a-zA-Z0-9])+([a-zA-Z0-9\+._-])*@([a-zA-Z0-9_-])+([.])+([a-zA-Z0-9\._-]+)+$/", $email)){
	
		return false;
	
	}else{
	
		return true;
	
	}

}

function _unserialize($str){

	$var = @unserialize($str);
	
	if(empty($var)){
	
		$str = preg_replace('!s:(\d+):"(.*?)";!se', "'s:'.strlen('$2').':\"$2\";'", $str);
		
		$var = @unserialize($str);
	
	}
	
	//If it is still empty false
	if(empty($var)){
	
		return false;
	
	}else{
	
		return $var;
	
	}

}

// Presently takes care of Slashes
function inputsec($string){
	
	//get_magic_quotes_gpc is depricated in php 7.4
	if(version_compare(PHP_VERSION, '7.4', '<')){
		if(!get_magic_quotes_gpc()){
		
			$string = addslashes($string);
		
		}else{
		
			$string = stripslashes($string);
			$string = addslashes($string);
		
		}
	}else{
		$string = addslashes($string);
	}
	
	// This is to replace ` which can cause the command to be executed in exec()
	$string = str_replace('`', '\`', $string);
	
	return $string;

}

// Takes care of characters
function htmlizer($string){

global $globals;
	
	$charset = !empty($globals['charset']) ? $globals['charset'] : null;
	
	$string = htmlentities($string, ENT_QUOTES | ENT_IGNORE, $charset);
	
	//$string = preg_replace('/(&amp;#(\d{1,7}|x[0-9a-fA-F]{1,6});)/e', 'entity_check(\\2);', $string);
	
	return $string;
	
}

/////////////////////
// POSTING Functions
/////////////////////

function POST($name, $e, $isset = 1){

global $error;

	//Check the POSTED NAME was posted
	if(($isset && (!isset($_POST[$name]) || strlen(trim($_POST[$name])) < 1)) || 
	(empty($isset) && empty($_POST[$name]))){
	
		$error[$name] = $e;
		
	}else{
	
		return inputsec(htmlizer(trim($_POST[$name])));
	
	}

}

// No htmlizer post - Dont use in SQL Queries
function iPOST($name, $e, $isset = 1){

global $error;

	//Check the POSTED NAME was posted
	if(($isset && (!isset($_POST[$name]) || strlen(trim($_POST[$name])) < 1)) || 
	(empty($isset) && empty($_POST[$name]))){
	
		$error[$name] = $e;
		
	}else{
	
		return inputsec(trim($_POST[$name]));
	
	}

}

//OPTIONAL Post
function optPOST($name, $default = ''){

global $error;

	//Check the POSTED NAME was posted
	if(isset($_POST[$name])){
	
		return inputsec(htmlizer(trim($_POST[$name])));
		
	}else{
		
		return $default;
	
	}

}

/**
 * Return the value of the POSTED key i.e. $_POST[$key]. Is mainly used for Themes to fill the forms again automatically.
 *
 * @package      forms
 * @subpackage   post
 * @author       Pulkit Gupta
 * @param        string $name The key of the $_POST array i.e. the name of the input / textarea / select text 
 * @param        string $default (Optional) Default value when the POST is empty
 * @return       string The value of the POSTED Key or the $default value when the POST is empty
 * @since     	 1.0
 */
function POSTval($name, $default = ''){
	
	return (!empty($_POST) ? (empty($_POST[$name]) ? '' : inputsec(htmlizer(trim($_POST[$name])))) : $default);

}

/**
 * Return the value of the POSTED key i.e. $_POST[$key]. Is mainly used for Themes to fill the forms again automatically.
 * The difference betweern aPOSTval() and POSTval() is that aPOSTval() just trims the value while POSTval will do 
 * inputsec(htmlizer(trim($_POST[$name]))))
 *
 * @package      forms
 * @subpackage   post
 * @author       Pulkit Gupta
 * @param        string $name The key of the $_POST array i.e. the name of the input / textarea / select text 
 * @param        string $default (Optional) Default value when the POST is empty
 * @return       string The value of the POSTED Key or the $default value when the POST is empty
 * @since     	 1.0
 */
function aPOSTval($name, $default = ''){
	
	return (!empty($_POST) ? (empty($_POST[$name]) ? '' : trim($_POST[$name])) : $default);

}

//OPTIONAL REQUEST
function optREQ($name, $default = ''){

global $error;

	//Check the POSTED NAME was posted
	if(isset($_REQUEST[$name])){
	
		return inputsec(htmlizer(trim($_REQUEST[$name])));
		
	}else{
		
		return $default;
	
	}

}

// Clean FOR var directly
function optInput($val){

global $error;

	return inputsec(htmlizer(trim($val)));

}

//Check if isset in REQUEST Array else return error lang
function REQUEST($name, $e){

global $error;

	//Check the REQUEST NAME was sent
	if(!isset($_REQUEST[$name]) || strlen(trim($_REQUEST[$name])) < 1){
	
		$error[$name] = $e;
		
	}else{
	
		return inputsec(htmlizer(trim($_REQUEST[$name])));
	
	}

}

//Checkbox
function checkbox($name){

global $error;

	//Check the Checkbox posted
	if(isset($_POST[$name])){
	
		return true;
		
	}else{
		
		return false;
	
	}

}


function GET($name, $e){

global $error;

	//Check the POSTED NAME was posted
	if(!isset($_GET[$name]) || strlen(trim($_GET[$name])) < 1){
	
		$error[$name] = $e;
		
	}else{
	
		return inputsec(htmlizer(trim($_GET[$name])));
	
	}

}

//OPTIONAL GET
function optGET($name, $default = ''){

global $error;

	//Check the GETED NAME was GETed
	if(isset($_GET[$name])){
	
		return inputsec(htmlizer(trim($_GET[$name])));
		
	}else{
		
		return $default;
	
	}

}

// Strips slashes if GPC was on
function rawGPC($v){
	//get_magic_quotes_gpc is depricated in php 7.4
	if(version_compare(PHP_VERSION, '7.4', '<')){
		if(get_magic_quotes_gpc()){		
			$v = stripslashes($v);
		}
	}
	return $v;
}

// Make a curl call
function curl_call($url, $post = array()){	
	
	// Set the curl parameters.
	$ch = curl_init();
	curl_setopt($ch, CURLOPT_URL, $url);
		
	// Connection Time OUT
	curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, (!empty($GLOBALS['globals']['curl_timeout']) ? $GLOBALS['globals']['curl_timeout'] : 10));
	
	// You can timeout in one hour max
	curl_setopt($ch, CURLOPT_TIMEOUT, 3600);
	
	// Turn off the server and peer verification (TrustManager Concept).
	curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
	curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
		
	// UserAgent and Cookies
	curl_setopt($ch, CURLOPT_USERAGENT, 'Softaculous');
	
	if(!empty($post)){
		curl_setopt($ch, CURLOPT_POST, 1);
		curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($post));
	}
	
	curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
	
	// Get response from the server.
	$resp = curl_exec($ch);
	$curl_err = curl_error($ch);
	$meta = curl_getinfo($ch);
	curl_close($ch);
	
	if($meta['http_code'] == 405){
		return curl_call($url);
	}
	
	if(empty($resp)){
		return false;
	}
	
	return $resp;
	
}


/**
 * phpMyAdmin SPLIT SQL function which splits the SQL data into seperate chunks that can be passed as QUERIES.
 *
 * @package      database 
 * @author       Pulkit Gupta
 * @param        string $data The SQL RAW data
 * @returns 	 array The chunks of SQL Queries
 * @since     	 1.0
 */
function sqlsplit($data){

	$ret = array();
	$buffer = '';
	// Defaults for parser
	$sql = '';
	$start_pos = 0;
	$i = 0;
	$len= 0;
	$big_value = 200000000;
	$sql_delimiter = ';';
	
	$finished = false;
	
	while (!($finished && $i >= $len)) {
	
		if ($data === FALSE) {
			// subtract data we didn't handle yet and stop processing
			//$offset -= strlen($buffer);
			break;
		} elseif ($data === TRUE) {
			// Handle rest of buffer
		} else {
			// Append new data to buffer
			$buffer .= $data;
			// free memory
			$data = false;
			// Do not parse string when we're not at the end and don't have ; inside
			if ((strpos($buffer, $sql_delimiter, $i) === FALSE) && !$finished)  {
				continue;
			}
		}
		// Current length of our buffer
		$len = strlen($buffer);
		
		// Grab some SQL queries out of it
		while ($i < $len) {
			$found_delimiter = false;
			// Find first interesting character
			$old_i = $i;
			// this is about 7 times faster that looking for each sequence i
			// one by one with strpos()
			if (preg_match('/(\'|"|#|-- |\/\*|`|(?i)DELIMITER)/', $buffer, $matches, PREG_OFFSET_CAPTURE, $i)) {
				// in $matches, index 0 contains the match for the complete 
				// expression but we don't use it
				$first_position = $matches[1][1];
			} else {
				$first_position = $big_value;
			}
			/**
			 * @todo we should not look for a delimiter that might be
			 *       inside quotes (or even double-quotes)
			 */
			// the cost of doing this one with preg_match() would be too high
			$first_sql_delimiter = strpos($buffer, $sql_delimiter, $i);
			if ($first_sql_delimiter === FALSE) {
				$first_sql_delimiter = $big_value;
			} else {
				$found_delimiter = true;
			}
	
			// set $i to the position of the first quote, comment.start or delimiter found
			$i = min($first_position, $first_sql_delimiter);
	
			if ($i == $big_value) {
				// none of the above was found in the string
	
				$i = $old_i;
				if (!$finished) {
					break;
				}
				// at the end there might be some whitespace...
				if (trim($buffer) == '') {
					$buffer = '';
					$len = 0;
					break;
				}
				// We hit end of query, go there!
				$i = strlen($buffer) - 1;
			}
	
			// Grab current character
			$ch = $buffer[$i];
	
			// Quotes
			if (strpos('\'"`', $ch) !== FALSE) {
				$quote = $ch;
				$endq = FALSE;
				while (!$endq) {
					// Find next quote
					$pos = strpos($buffer, $quote, $i + 1);
					// No quote? Too short string
					if ($pos === FALSE) {
						// We hit end of string => unclosed quote, but we handle it as end of query
						if ($finished) {
							$endq = TRUE;
							$i = $len - 1;
						}
						$found_delimiter = false;
						break;
					}
					// Was not the quote escaped?
					$j = $pos - 1;
					while ($buffer[$j] == '\\') $j--;
					// Even count means it was not escaped
					$endq = (((($pos - 1) - $j) % 2) == 0);
					// Skip the string
					$i = $pos;
	
					if ($first_sql_delimiter < $pos) {
						$found_delimiter = false;
					}
				}
				if (!$endq) {
					break;
				}
				$i++;
				// Aren't we at the end?
				if ($finished && $i == $len) {
					$i--;
				} else {
					continue;
				}
			}
	
			// Not enough data to decide
			if ((($i == ($len - 1) && ($ch == '-' || $ch == '/'))
			  || ($i == ($len - 2) && (($ch == '-' && $buffer[$i + 1] == '-')
				|| ($ch == '/' && $buffer[$i + 1] == '*')))) && !$finished) {
				break;
			}
	
			// Comments
			if ($ch == '#'
			 || ($i < ($len - 1) && $ch == '-' && $buffer[$i + 1] == '-'
			  && (($i < ($len - 2) && $buffer[$i + 2] <= ' ')
			   || ($i == ($len - 1)  && $finished)))
			 || ($i < ($len - 1) && $ch == '/' && $buffer[$i + 1] == '*')
					) {
				// Copy current string to SQL
				if ($start_pos != $i) {
					$sql .= substr($buffer, $start_pos, $i - $start_pos);
				}
				// Skip the rest
				$j = $i;
				$i = strpos($buffer, $ch == '/' ? '*/' : "\n", $i);
				// didn't we hit end of string?
				if ($i === FALSE) {
					if ($finished) {
						$i = $len - 1;
					} else {
						break;
					}
				}
				// Skip *
				if ($ch == '/') {
					// Check for MySQL conditional comments and include them as-is
					if ($buffer[$j + 2] == '!') {
						$comment = substr($buffer, $j + 3, $i - $j - 3);
						if (preg_match('/^[0-9]{5}/', $comment, $version)) {
							if ($version[0] <= 50000000) {
								$sql .= substr($comment, 5);
							}
						} else {
							$sql .= $comment;
						}
					}
					$i++;
				}
				// Skip last char
				$i++;
				// Next query part will start here
				$start_pos = $i;
				// Aren't we at the end?
				if ($i == $len) {
					$i--;
				} else {
					continue;
				}
			}
			// Change delimiter, if redefined, and skip it (don't send to server!)
			if (strtoupper(substr($buffer, $i, 9)) == "DELIMITER"
			 && ($buffer[$i + 9] <= ' ')
			 && ($i < $len - 11)
			 && strpos($buffer, "\n", $i + 11) !== FALSE) {
			   $new_line_pos = strpos($buffer, "\n", $i + 10);
			   $sql_delimiter = substr($buffer, $i + 10, $new_line_pos - $i - 10);
			   $i = $new_line_pos + 1;
			   // Next query part will start here
			   $start_pos = $i;
			   continue;
			}
	
			// End of SQL
			if ($found_delimiter || ($finished && ($i == $len - 1))) {
				$tmp_sql = $sql;
				if ($start_pos < $len) {
					$length_to_grab = $i - $start_pos;
	
					if (! $found_delimiter) {
						$length_to_grab++;
					}
					$tmp_sql .= substr($buffer, $start_pos, $length_to_grab);
					unset($length_to_grab);
				}
				// Do not try to execute empty SQL
				if (! preg_match('/^([\s]*;)*$/', trim($tmp_sql))) {
					$sql = $tmp_sql;
					$ret[] = $sql;
					
					$buffer = substr($buffer, $i + strlen($sql_delimiter));
					// Reset parser:
					$len = strlen($buffer);
					$sql = '';
					$i = 0;
					$start_pos = 0;
					// Any chance we will get a complete query?
					//if ((strpos($buffer, ';') === FALSE) && !$finished) {
					if ((strpos($buffer, $sql_delimiter) === FALSE) && !$finished) {
						break;
					}
				} else {
					$i++;
					$start_pos = $i;
				}
			}
		} // End of parser loop
	} // End of import loop

	return $ret;

}

function resetfilelist(){
global $directorylist;
	$directorylist = array();
}


function rmdir_recursive_fn($path){
	
	//if(!is_safe_file($path)) return false;
	
	$path = (substr($path, -1) == '/' || substr($path, -1) == '\\' ? $path : $path.'/');
	
	resetfilelist();
	
	$files = filelist_fn($path, 1, 0, 'all');
	$files = (!is_array($files) ? array() : $files);
	
	//First delete the files only
	foreach($files as $k => $v){
		//if(is_safe_file($k)){ // Security Fix
			@chmod($k, 0777);
		//}
		if(file_exists($k) && is_file($k) && @filetype($k) == "file"){
			@unlink($k);
		}
	}
	
	@clearstatcache();
	
	$folders = filelist_fn($path, 1, 1, 'all');
	$folders = (!is_array($folders) ? array() : $folders);
	@krsort($folders);

	//Now Delete the FOLDERS
	foreach($folders as $k => $v){
		//if(is_safe_file($k)){ // Security Fix
			@chmod($k, 0777);
		//}
		if(is_dir($k)){
			@rmdir($k);
		}
	}
	
	@rmdir($path);
	
	@clearstatcache();

}


function filelist_fn($startdir="./", $searchSubdirs=1, $directoriesonly=0, $maxlevel="all", $level=1, $reset = 1) {
	//list the directory/file names that you want to ignore
	$ignoredDirectory[] = ".";
	$ignoredDirectory[] = "..";
	$ignoredDirectory[] = "_vti_cnf";
	global $directorylist;    //initialize global array

	if(substr($startdir, -1) != '/'){
		$startdir = $startdir.'/';
	}

	if (is_dir($startdir)) {
		if ($dh = opendir($startdir)) {
			while (($file = readdir($dh)) !== false) {
				if (!(array_search($file,$ignoredDirectory) > -1)) {
					if (@filetype($startdir . $file) == "dir") {
						 
						//build your directory array however you choose;
						//add other file details that you want.

						$directorylist[$startdir . $file]['level'] = $level;
						$directorylist[$startdir . $file]['dir'] = 1;
						$directorylist[$startdir . $file]['name'] = $file;
						$directorylist[$startdir . $file]['path'] = $startdir;
						if ($searchSubdirs) {
							if ((($maxlevel) == "all") or ($maxlevel > $level)) {
								filelist_fn($startdir . $file . "/", $searchSubdirs, $directoriesonly, $maxlevel, ($level + 1), 0);
							}
						}
						  
						   
					} else {
						if (!$directoriesonly) {
							 
							//  echo substr(strrchr($file, "."), 1);
							//if you want to include files; build your file array 
							//however you choose; add other file details that you want.
							$directorylist[$startdir . $file]['level'] = $level;
							$directorylist[$startdir . $file]['dir'] = 0;
							$directorylist[$startdir . $file]['name'] = $file;
							$directorylist[$startdir . $file]['path'] = $startdir;
							  
						 
						}
					}
				}
			
			}
			
			closedir($dh);
		}
	}

	if(!empty($reset)){
		$r = $directorylist;
		$directorylist = array();
		return($r);
	}
}


/**
 * Get a web file but add little Softaculous information like the license key, unique, panel, is_vps, env, soft_email as 
 * arguments to the $url given. This is mainly used to FETCH FILES from Softaculous.com and related softaculous websites.
 *
 * @package      files 
 * @author       Pulkit Gupta
 * @param        string $url The URL from which the DATA is to be fetched
 * @param        string $path (Optional) If given the FETCHED data is saved in the file instead of having it returned 
 * @return       string The FETCHED DATA
 * @since     	 1.0
 */
function get_softaculous_file($url, $return_url = 0){

global $sitepad;
	
	$license = (!empty($sitepad['license']) ? $sitepad['license']['license'] : $sitepad['server_license']['license']);
	
	if(strstr($url, '?')){
		$url = $url.'&license='.$license;
	}else{
		$url = $url.'?license='.$license;
	}
	
	if(!empty($return_url)){
		return $url;
	}
	
	return curl_call($url);
	
}

/**
 * This function will preg_match the pattern and return the respective values in $var
 * @package      Softaculous 
 * @author       Brijesh Kothari
 * @param		 $pattern This should be the pattern to be matched
 * @param		 $file This should have the data to search from
 * @param		 $var This will be the variable which will have the preg matched data
 * @param		 $valuenum This should be the no of regular expression to be returned in $var
 * @param		 $stripslashes 0 or 1 depending upon whether the stripslashes function is to be applied (1) or not (0)
 * @return       string Will pass value by reference in $var
 * @since     	 4.5.4
 */
function soft_preg_replace($pattern, $file, &$var, $valuenum, $stripslashes = ''){	
	preg_match($pattern, $file, $matches);
	if(empty($stripslashes)){
		$var = @trim($matches[$valuenum]);
	}else{
		$var = @stripslashes(trim($matches[$valuenum]));
	}
}

function makedate($date, $format = 'd/m/Y'){
	
	if(empty($date)) return false;
	
	$year = substr($date, 0, 4);
	
	$month = substr($date, 4, 2);
	
	$day = substr($date, 6, 2);
	
	if($format == 'd/m/Y'){
		
		// Check the Max DAY possible
		$maxday = (int) date('t', mktime(0, 0, 0, $month, 1, $year));
		
		return ($day > $maxday ? $maxday : $day).'/'.$month.'/'.$year;
	}
	
	return date($format, mktime(0, 0, 0, $month, $day, $year));

}

/**
 * Copies Recrsively a File / Folder and also maintains the PERMISSIONS and UID and GID
 *
 * @package      softaculous
 * @subpackage   settings
 * @author       Pulkit Gupta
 * @param        string $path The Source Path
 * @param        string $dest The Destination Path
 * @return       bool
 * @since     	 1.0
 */
function copy_r($path, $dest, $exclude = array()){
	
	global $__settings;
	
	foreach($exclude as $skip){
		//echo 'Skip path : '.$skip.'<br />';
		if(preg_match('#'.preg_quote($skip, '/').'#', $path)){
			//echo 'Skipping : '.$path.'<br />';
			return true;
		}
	}
	
	// Is it a Directory ?
	if( is_dir($path) ){
		
		// Create the Destination Dir
		@mkdir($dest);
		
		$stat = stat($path);
		
		// Set the mode of the destination
		if(!empty($stat['mode'])){
			@chmod($dest, $stat['mode']);
		}
		
		// Set the UID
		if(!empty($stat['uid'])){
			@chown($dest, $stat['uid']);
		}
		
		// Set the GID
		if(!empty($stat['gid'])){
			@chgrp($dest, $stat['gid']);
		}
		
		// Start reading the current directory
		$objects = scandir($path);
		if( sizeof($objects) > 0 ){
			foreach( $objects as $file )
			{
				if( $file == "." || $file == ".." ){
					continue;
				}
				
				// Go on
				copy_r( $path.'/'.$file, $dest.'/'.$file, $exclude);
			}
		}
		
		return true;
		
	}elseif( is_file($path) ){
		
		$ret = copy($path, $dest);
		$stat = stat($path);
		
		// Set the mode of the destination
		if(!empty($stat['mode'])){
			@chmod($dest, $stat['mode']);
		}
		
		// Set the UID
		if(!empty($stat['uid'])){
			@chown($dest, $stat['uid']);
		}
		
		// Set the GID
		if(!empty($stat['gid'])){
			@chgrp($dest, $stat['gid']);
		}
		
		return $ret;
		
	}else{
		return false;
	}
}


function error_handle($error, $table_width = '100%', $center = false, $return = false){

global $l;
	
	$str = "";

	$table_width = preg_match('/%/is', $table_width) ? $table_width : $table_width.'px';

	//on error call the form
	if(!empty($error)){
		$str .= '<script language="javascript" type="text/javascript"><!-- // --><![CDATA[		
		</script>';
		
		$str .= '<div class="alert alert-danger " style="width:'.$table_width.';'.(($center) ? 'margin:auto' : '').'"><a href="#" class="close" data-dismiss="alert">&times;</a><div>';
		$str .= '<p style="margin-top:4px; font-size:16px;">&nbsp;&nbsp;'.__('The following errors were found').' :</p>
			<ul type="square" style="margin-top:-4px;">';
		
		foreach($error as $ek => $ev){
		
			$str .= '<li style="font-size:13px;">'.$ev.'</li>';
		
		}
		
		$str .= '</ul>
		</div></div>';
		
		if(empty($return)){
			echo $str;
		}else{
			return $str;	
		}
		
	}

}


/**
 * Checks if a file is symlink or hardlink
 * @package      softaculous 
 * @author       Pulkit Gupta
 * @returns 	 bool false if file is a symlink or a hardlink else true
 * @since     	 4.4.3
 */
function is_safe_file($path){

	// Is it a symlink ?
	if(is_link($path)) return false;
	
	// Is it a file and is a link ?
	$stat = @stat($path);
	if(!is_dir($path) && $stat['nlink'] > 1) return false;
	
	return true;
}

function mkdir_recursive($pathname, $mode){
    is_dir(dirname($pathname)) || mkdir_recursive(dirname($pathname), $mode);
    return is_dir($pathname) || @mkdir($pathname, $mode);
}