Current File : /home/lecoinf/www/iwp/controllers/appFunctions.php
<?php
/************************************************************
 * InfiniteWP Admin panel									*
 * Copyright (c) 2012 Revmakx								*
 * www.revmakx.com											*
 *															*
 ************************************************************/
 
function DBConnectAndSetOptions(){
	$isConnected = DB::connect(Reg::get('config.SQL_HOST'), Reg::get('config.SQL_USERNAME'), Reg::get('config.SQL_PASSWORD'), Reg::get('config.SQL_DATABASE'), Reg::get('config.SQL_PORT'));
	if(!$isConnected){
		die('Mysql connect error: (' . DB::connectErrorNo().') '.DB::connectError() );
	}
	DB::setTableNamePrefix(Reg::get('config.SQL_TABLE_NAME_PREFIX'));
	DB::doQuery("SET SESSION sql_mode = ' '");
	checkDBStatus();
}

function processCallReturn($Array){
	return $Array;
}

function isPluginResponse($data){ // Checking if we got the rite data / it didn't time out
 
	if(stripos($data,'IWPHEADER') === false){
		return false;
	}
	return true;
}
function signData($data, $isOpenSSLActive, $privateKey, $randomSignature){
	if( function_exists('openssl_verify') && $isOpenSSLActive ){
		openssl_sign($data, $signature, base64_decode($privateKey));
	}
	elseif(!$isOpenSSLActive){
		$signature =  md5($data . $randomSignature);
	}
	else{
		return false;	
	}
	return $signature;
}

function secureData($data, $isOpenSSLActive, $privateKey, $randomSignature){
	if(!empty($data) && $isOpenSSLActive && !empty($privateKey)){
	   $secureData = serialize($data);		 
	   $secureDataArray = str_split($secureData, 96); //max length 117
		   
	   $secureDataEncrypt = array();
	   
		foreach($secureDataArray as $secureDataPart){				 			  
			openssl_private_encrypt($secureDataPart, $secureDataEncryptPart, base64_decode($privateKey));
			$secureDataEncrypt[] = $secureDataEncryptPart;
		}
		$data = $secureDataEncrypt;
	}	
	return $data;	
}

function addHistory($historyData, $historyAdditionalData= array()){
	$historyData['userID'] = $GLOBALS['userID'];
	$historyData['microtimeAdded']=microtime(true);
	$historyID =  DB::insert('?:history', $historyData);
	if(!empty($historyAdditionalData)){
		foreach($historyAdditionalData as $row){			
			$row['historyID'] = $historyID;
			DB::insert("?:history_additional_data", $row);
			
		}
	}
	
	return $historyID;
}

function updateHistory($historyData, $historyID, $historyAdditionalData=false){
	$where = array(
      		'query' =>  "historyID=':historyID'",
      		'params' => array(
               ':historyID'=>$historyID
				)
		);
	DB::update('?:history', $historyData, $where);
	
	if(!empty($historyAdditionalData)){
		DB::update('?:history_additional_data', $historyAdditionalData, $where);
	}
}

function getHistory($historyID, $getAdditional=false){
	$where = array(
      		'query' =>  "historyID=':historyID'",
      		'params' => array(
               ':historyID'=>$historyID
				)
		);
	$historyData = DB::getRow('?:history', '*', $where);
	if($getAdditional){
		$historyData['additionalData'] = DB::getArray('?:history_additional_data', '*', $where);
	}
	return $historyData;
}

function getSiteData($siteID, $byPassAccess = NULL, $byPassStaging = NULL){
	if($siteID){
		if(userStatus() == "admin" || $byPassAccess === "true" ){
			$where = array(
	      		'query' =>  "siteID=':siteID'",
	      		'params' => array(
	               ':siteID'=>$siteID
					)
			);
			return DB::getRow("?:sites","*",$where);
		}
		else{
			if (function_exists('stagingGetStagingSiteData') && $byPassStaging != true) {
				$siteTempData = stagingGetStagingSiteData($siteID);
				if (!empty($siteTempData) && is_array($siteTempData)) {
					foreach ($siteTempData as $key => $data) {
						$siteData = $data;
					}
					return $siteData;
				}
			}
			$where = array(
	      		'query' =>  "UA.userID =':userID' AND  UA.siteID IN (:siteID) AND S.siteID=UA.siteID",
	      		'params' => array(
	               ':userID'=>$GLOBALS['userID'],
	               ':siteID'=>$siteID
					)
			);
			return DB::getRow("?:user_access UA, ?:sites S", "S.*, UA.siteID", $where);
		}
	}
}

function getSitesData($siteIDs=false, $where='1', $byPassAccess = NULL){ //for current user
	if(userStatus() == "admin" || $byPassAccess == true){
		if(!empty($siteIDs)){
			$where = "siteID IN ('". implode("','", DB::esc($siteIDs)) ."')";
		} else {
			$where = "type = 'normal'";
		}
	
		return DB::getArray("?:sites", "*", $where, "siteID");
	}
	else{
		if(!empty($siteIDs)){
			if (function_exists('stagingGetStagingSiteData')) {
				$siteData = stagingGetStagingSiteData($siteIDs);
				if (!empty($siteData) && is_array($siteData)) {
					return $siteData;
				}
			}
			$where = " AND UA.siteID IN ('". implode("','", DB::esc($siteIDs)) ."') ";
			return DB::getArray("?:user_access UA, ?:sites S", "S.*, UA.siteID", "UA.userID =".DB::esc($GLOBALS['userID'])." AND UA.siteID IN ('". implode("','", DB::esc($siteIDs)) ."') AND S.siteID=UA.siteID ", "siteID");
		}
		return DB::getArray("?:user_access UA, ?:sites S", "S.*, UA.siteID", "UA.userID ='".DB::esc($GLOBALS['userID'])."' AND S.siteID=UA.siteID AND type = 'normal'", "siteID");
	}
}

function prepareRequestAndAddHistory($PRP){	
	$defaultPRP = array('doNotExecute' 		=> false,
						'exitOnComplete' 	=> false,
						'doNotShowUser' 	=> false,//hide in history
						'directExecute' 	=> false,
						'signature' 		=> false,
						'timeout' 			=> DEFAULT_MAX_CLIENT_REQUEST_TIMEOUT,
						'runCondition'		=> false,
						'status'			=> 'pending',
						'isPluginResponse'	=> 1,
						'sendAfterAllLoad'	=> false,
						'callOpt'			=> array()
						);
						
	$PRP = array_merge($defaultPRP, $PRP);
	@extract($PRP);
	
	if(empty($historyAdditionalData)){
		echo 'noHistoryAdditionalData';
		return false;	
	}
	
	if( ($siteData['connectURL'] == 'default' || defined('CONNECT_USING_SITE_URL') && CONNECT_USING_SITE_URL == 1) || $siteData['connectURL'] == 'siteURL'){
		$URL = $siteData['URL'];
	}
	else{//if($siteData['connectURL'] == 'default' || $siteData['connectURL'] == 'adminURL')
		$URL = $siteData['adminURL'];
	}
	
	if ($siteData['connectURL'] != 'siteURL' && ($siteData['connectURL'] == 'default' && $siteData['network'])) {
		$URL = $siteData['adminURL'];
		$siteData['connectURL'] = 'adminURL';
	}
	$historyData = array('siteID' 	=> $siteData['siteID'], 
						 'actionID' => Reg::get('currentRequest.actionID'),
						 'userID' 	=> $GLOBALS['userID'],
						 'type' 	=> $type,
						 'action' 	=> $action,
						 'events' 	=> $events,
						 'URL' 		=> trim($URL),
						 'timeout' 	=> $timeout,
						 'isPluginResponse' => $isPluginResponse);	
	if($doNotShowUser){
		$historyData['showUser'] = 'N';
	}
	
	if($parentHistoryID){
		$historyData['parentHistoryID'] = $parentHistoryID;
	}

	if(!empty($actionID)){
		$historyData['actionID'] = $actionID;
	}
	
	if(!empty($siteData['callOpt'])){
		$callOpt = @unserialize($siteData['callOpt']);
	}
	
	if ($siteData['connectURL'] == 'adminURL') {
		$callOpt['connectURL'] = 'adminURL';
	}
	if(!empty($siteData['httpAuth'])){
		$callOpt['httpAuth'] = @unserialize($siteData['httpAuth']);
	}
	if(!empty($runCondition)){
		$historyData['runCondition'] = $runCondition;
	}
	if(!empty($timeScheduled)){
		$historyData['timeScheduled'] = $timeScheduled;
	}
	if(!empty($notifyFailed)){
		$historyData['notifyFailed'] = $notifyFailed;
	}
	if (isV3Panel()) {
		$historyData['isV3'] = 1;
	}
	if(!empty($param1)){
		$historyData['param1'] = $param1;
	}
	
	$historyData['callOpt'] = serialize($callOpt);
	$historyID = addHistory($historyData, $historyAdditionalData);
		
	if($signature === false){
		$signature = signData($requestAction.$historyID, $siteData['isOpenSSLActive'], $siteData['privateKey'], $siteData['randomSignature']);
	}
	$signature = base64_encode($signature);
	$requestParams['username'] =  $siteData['adminUsername'];
	setHook('PRPRequest', $requestParams, $historyData);
	if(isset($requestParams['secure'])){
		$requestParams['secure'] = secureData($requestParams['secure'], $siteData['isOpenSSLActive'], $siteData['privateKey'], $siteData['randomSignature']);
		$requestParams['secure'] = base64_encode(serialize($requestParams['secure']));
	}
	
	if(!empty($requestParams['args'])){
		$requestParams['args']['parentHID'] = $historyID;
	}
	$requestData = array('iwp_action' => $requestAction, 'params' => $requestParams, 'id' => $historyID, 'signature' => $signature, 'iwp_admin_version' => APP_VERSION, 'is_save_activity_log' => isSaveActivityLogInClient(), 'activities_log_datetime' => date('Y-m-d H:i:s', time()));
	$requestData = array('iwp_action' => $requestAction, 'params' => $requestParams, 'id' => $historyID, 'signature' => $signature, 'iwp_admin_version' => APP_VERSION, 'is_save_activity_log' => isSaveActivityLogInClient(), 'activities_log_datetime' => date('Y-m-d H:i:s', time()));
		
	$updateHistoryData = array('status' => $status);
	
	updateHistory($updateHistoryData, $historyID);
	
	DB::insert("?:history_raw_details", array('historyID' => $historyID, 'request' => base64_encode(serialize($requestData)), 'panelRequest' => serialize($_REQUEST) ) );
	
	if($directExecute){
		set_time_limit(0);
		echo 'direct_execute<br />';
		executeRequest($historyID, $type, $action, $siteData['URL'], $requestData, $timeout, true, $callOpt);
	}
	else{
		echo 'async_call_it_should_be<br />';
		if($exitOnComplete){ set_time_limit(0); echo "async_call_it_should_be_working"; Reg::set('currentRequest.exitOnComplete', true); }
		elseif($sendAfterAllLoad){ Reg::set('currentRequest.sendAfterAllLoad', true); }
	}
	return $historyID;
}



function executeRequest($historyID, $type='', $action='', $URL='', $requestData='', $timeout='', $isPluginResponse=true, $callOpt=array()){	
	$responseProcessor = array();
	$responseProcessor['plugins']['install'] = $responseProcessor['themes']['install'] = 'installPluginsThemes';
	$responseProcessor['plugins']['manage'] = $responseProcessor['themes']['manage'] = 'managePluginsThemes';	
	$responseProcessor['plugins']['get'] = $responseProcessor['themes']['get'] = 'getPluginsThemes';
	$responseProcessor['stats']['getStats'] = 'getStats';
	if (isV3Panel()) {
		$responseProcessor['addtionalStats']['getAdditionalStats'] = 'getAdditionalStats';
	}
	$responseProcessor['PTC']['update'] = 'updateAll';
	$responseProcessor['backup']['now'] = 'backup';
	$responseProcessor['backup']['multiCallNow'] = 'backup';
	$responseProcessor['backup']['restore'] = 'restoreBackup';
	$responseProcessor['backup']['multiCallRestore'] = 'restoreBridgeUpload';
	$responseProcessor['backup']['bridgeExtractMulticallRestore'] = 'bridgeExtractMulticallRestore';
	$responseProcessor['backup']['restoreNew'] = 'restoreNewBackup';
	$responseProcessor['backup']['restoreBackupDownlaod'] = 'restoreBackupDownlaod';
	$responseProcessor['backup']['triggerBackupDownlaod'] = 'triggerBackupDownlaod';
	$responseProcessor['backup']['remove'] = 'removeBackup';
	$responseProcessor['cronTask']['runCron'] = 'pheonixBackupCron';
	$responseProcessor['cronDoAction']['pheonixBackupCronDoAction'] = 'pheonixBackupCronDoAction';
	$responseProcessor['site']['add'] = 'addSite';
	$responseProcessor['site']['readd'] = 'readdSite';
	$responseProcessor['site']['maintain'] = 'iwpMaintenance';
	$responseProcessor['site']['auto_updater_settings'] = 'editSite';
	$responseProcessor['site']['remove'] = 'removeSite';
	$responseProcessor['site']['backupTest'] = 'backupTest';
	$responseProcessor['clientPlugin']['update'] = 'updateClient';
	$responseProcessor['backup']['trigger'] = 'triggerRecheck';
	$responseProcessor['cookie']['get'] = 'getCookie';
	$responseProcessor['credentials']['getDBDetails'] = 'getDBDetails';
	
	if (file_exists(APP_ROOT."/addons/scheduleBackup/controllers/manageClientsScheduleBackup.php") && isAddonActive('scheduleBackup'))
		@include_once(APP_ROOT."/addons/scheduleBackup/controllers/manageClientsScheduleBackup.php");
	
	setHook('responseProcessors', $responseProcessor);
	$skipJsonCommunication = array('deleteSite');
	$historyData = getHistory($historyID);
	$actionResponse = $responseProcessor[$historyData['type']][$historyData['action']];
	$where = array(
			      		'query' =>  "historyID=':historyID'",
			      		'params' => array(
			               ':historyID'=>$historyID
           				)
        			);

	if(manageClients::methodPreExists($actionResponse)){
		manageClients::executePre($actionResponse, $historyID);
		$historyDataTemp = getHistory($historyID);
		if($historyDataTemp['status'] != 'pending'){
			return false;	
		}
		unset($historyDataTemp);
	}	
	updateHistory(array('microtimeInitiated' => microtime(true), 'status' => 'running'), $historyID);
	
	if(empty($type) || empty($action) || empty($URL) || empty($requestData)){
		
		$historyRawDetails = DB::getRow("?:history_raw_details", "*", $where);
		$requestData = unserialize(base64_decode($historyRawDetails['request']));
		$historyData = getHistory($historyID);
		$type = $historyData['type'];
		$action = $historyData['action'];
		$URL = $historyData['URL'];
		$timeout =  $historyData['timeout'];
		$isPluginResponse =  $historyData['isPluginResponse'];
		$callOpt = @unserialize($historyData['callOpt']);
	}
	
	$isAdminURL = false;
	if ($callOpt['connectURL'] == 'adminURL') {
		$isAdminURL = true;
	}
	$siteID = $historyData['siteID'];
	$callOpt = buildCookie($callOpt, $siteID, $historyData);
	addReferrerURL($callOpt, $siteID);
	addWPLoadToURL($URL, $historyData, $isAdminURL, $siteID);
	addNoCacheToURL($URL, $historyData);

	$updateHistoryData = array();
	if (isIWPDebugModeEabled()) {
		$param3 = DB::getField("?:history", "param3", $where);
		$newParam3 = debug_backtrace();
		$newParam3 = base64_encode(serialize($newParam3));
		if (!empty($param3)) {
			$newParam3 = '<IWPOLD>'.$param3.'</IWPOLD>'.$newParam3;
		}
		DB::update("?:history", array('param3' => $newParam3), $where);
	}
	list($rawResponseData, $updateHistoryData['microtimeStarted'], $updateHistoryData['microtimeEnded'], $curlInfo, $rawResponseHeader, $redirectedUrl)  = doCall($URL, $requestData, $timeout, $callOpt);
	$isCompressionDisabled = getOption('disableRawTableCompression');
	if (empty($isCompressionDisabled)) {
		$commpressResponse = maybeCompress($rawResponseData);
	}else{
		$commpressResponse = addslashes($rawResponseData);
	}

	if (isIWPDebugModeEabled()) {
		$oldResponse = DB::getField("?:history_raw_details", "response", $where);
		if (!empty($oldResponse)) {
			$commpressResponse = '<IWPOLD>'.$oldResponse.'</IWPOLD>'.$commpressResponse;
		}
		$commpressResponse .= time();
	}
	DB::update("?:history_raw_details", array('response' => $commpressResponse, 'callInfo' => serialize($curlInfo)), $where);

	if (function_exists('mb_strpos')) {
		$is_gzip = 0 === mb_strpos($rawResponseData, "\x1f" . "\x8b" . "\x08", 0, "US-ASCII");
		if ($is_gzip) {
			$unzipRaw = @gzdecode($rawResponseData);
			$rawResponseData = $unzipRaw;
		}
	}
	
	$cookie = extractCookie($rawResponseHeader);
	saveCookie($cookie, $siteID);
	if (isIWPDebugModeEabled()) {
		if ( empty( $GLOBALS['iwp_testing']['historyIDs'] ) || (!empty( $GLOBALS['iwp_testing']['historyIDs'] ) && in_array($historyID, $GLOBALS['iwp_testing']['historyIDs'] )) ) {
			$isTesting = (!empty($GLOBALS['iwp_testing']) && $GLOBALS['iwp_testing']['type'] == $type && $GLOBALS['iwp_testing']['action'] == $action && in_array($siteID, $GLOBALS['iwp_testing']['siteIDs']) );
			if ($isTesting) {
				if ($GLOBALS['iwp_testing']['network_error'] && !empty($GLOBALS['iwp_testing']['info'])) {
					$curlInfo = $GLOBALS['iwp_testing']['info'];
					$rawResponseData = '';
				}
			}
		}
	}
	$cURLErrors = new cURLErrors($curlInfo);
	$retryErrors = new errorManager();

	if(!$cURLErrors->isOk() && ($type !='clientReporting' && $action != 'runReport')){
		$updateHistoryAdditionalData = array();
		$updateHistoryAdditionalData = $cURLErrors->getErrorDetails();
		$updateHistoryData['status'] = $updateHistoryAdditionalData['status'];
		$updateHistoryData['error'] = $updateHistoryAdditionalData['error'];
		if(!isPluginResponse($rawResponseData)){//sometimes 500 error with proper IWP Client Response, so if it not proper response continue set error and exit

			if($type=='site' && $action == 'add'){
				addSiteRetry($historyID);
				$GLOBALS['storage']['newSite']['recursiveCount'] = $GLOBALS['storage']['newSite']['recursiveCount']-1;
				if ($GLOBALS['storage']['newSite']['recursiveCount'] > 0 || $GLOBALS['storage']['newSite']['recursiveCount'] < 0) {
					return false;
				}
			}
			
			if ($retryErrors->checkErrorExists($updateHistoryData['error'],'phoenixRetryCheck') && triggerPhoenixBackupFailedTask($historyID, $actionResponse, $curlInfo['errorNo'], $curlInfo['info']['http_code'])) {
				return checkTriggerStatus();
			}
			if ($retryErrors->checkErrorExists($updateHistoryData['error'], 'multicallInitialCheck') && retriggerInitialMultical($historyID)) {
				return false;
			}
			if (!retryFailedTasksChecker($historyID, $actionResponse, $curlInfo['errorNo'], $curlInfo['info']['http_code'])) {
				if($type=='stats' && $action == 'getStats'){
					$where = array(
				      		'query' =>  "siteID=':siteID'",
				      		'params' => array(
				               ':siteID'=>$siteID
	           				)
	        			);
					DB::update("?:sites", array('connectionStatus' => '0'), $where);
				}
				$errorResponse = true;
				if(manageClients::methodErrorResponseExists($actionResponse)){
					$errorData['status'] = 'processingResponse';
					$errorData['microtimeStarted'] = $updateHistoryData['microtimeStarted'];
					$errorData['microtimeEnded'] = $updateHistoryData['microtimeEnded'];
					updateHistory($errorData, $historyID);
					$errorResponse = manageClients::executeErrorResponse($actionResponse, $historyID, $updateHistoryData);
				}
				if ($errorResponse) {
					updateHistory($updateHistoryData, $historyID, $updateHistoryAdditionalData);
				}
			}
			if (!$retryErrors->checkErrorExists($updateHistoryData['error'], 'multicallArrayCheck')) {
				multicallRestoreHisIDkill($updateHistoryData, $historyID, $updateHistoryAdditionalData);
			}
			insertHTTPCodeErrorsOfICIntoTempStorage($historyData['type'] ,$historyData['action'] ,$historyID, $cURLErrors->getErrorMsg());
			if (!$retryErrors->checkErrorExists($updateHistoryData['error'], 'multicallArrayCheck')) {
				multicallParentHisIDkill($updateHistoryData, $historyID, $updateHistoryAdditionalData);
			}
			if ($retryErrors->checkErrorExists($updateHistoryData['error'], 'multicallArrayCheck') &&  ($historyData['action'] == 'restoreNew' || $historyData['action'] == 'bridgeExtractMulticallRestore' || $historyData['action'] == 'triggerBackupDownlaod')) {
				multicallParentHisIDkill($updateHistoryData, $historyID, $updateHistoryAdditionalData);
			}
			return checkTriggerStatus();
		}
	}

	if($isPluginResponse){//$isPluginResponse is set to true then expecting result should be pluginResponse
		//checking response is the plugin data
		if(!isPluginResponse($rawResponseData)){ //Checking the timeout	
			//For left menu color codes
			if($type=='site' && $action == 'add'){
				addSiteRetry($historyID);
				$GLOBALS['storage']['newSite']['recursiveCount'] = $GLOBALS['storage']['newSite']['recursiveCount']-1;
				if ($GLOBALS['storage']['newSite']['recursiveCount'] > 0 || $GLOBALS['storage']['newSite']['recursiveCount'] < 0) {
					return false;
				}
			}	
			if (($type=='stats' && $action == 'getStats')) {
    			$isVaildRedirect = isRedirectedURLValid($URL, $redirectedUrl);
    			if ($isVaildRedirect) {
    				$where = array(
						  'query' =>  "siteID=':siteID'",
						  'params' => array(
							   ':siteID'=>$siteID
							   )
						);
    				$whereHis = array(
		      		'query' =>  "historyID=':historyID'",
		      		'params' => array(
			               ':historyID'=>$historyID
	       				)
	    			);
	    			$trimRedirectedUrl = trimURL($redirectedUrl);
					if ($isAdminURL) {
						$retriedTask = array('status'=>'retry', 'URL' => $trimRedirectedUrl);
						DB::update("?:sites", array('adminURL' => $trimRedirectedUrl), $where);
						DB::update('?:history', $retriedTask, $whereHis);
						return true;
					}else{
						$where = array(
						  'query' =>  "siteID=':siteID'",
						  'params' => array(
							   ':siteID'=>$siteID
							   )
						);
						$retriedTask = array('status'=>'retry', 'URL' => $trimRedirectedUrl);
						DB::update("?:sites", array('URL' => $trimRedirectedUrl), $where);
						DB::update('?:history', $retriedTask, $whereHis);
						return true;
					}
    			}
			}
			if($type=='stats' && $action == 'getStats'){
				$where = array(
			      		'query' =>  "siteID=':siteID'",
			      		'params' => array(
			               ':siteID'=>$siteID
           				)
        			);
				DB::update("?:sites", array('connectionStatus' => '0'), $where);
			}
			$where = array(
		      		'query' =>  "siteID=':siteID'",
		      		'params' => array(
		               ':siteID'=>$siteID
       				)
    			);
			$clientVersion =DB::getField("?:sites","pluginVersion",$where);
			if (!empty($clientVersion) && version_compare($clientVersion, '1.6.2','<')) {
				$errorMsg = 'Please update your IWP Client plugin to the latest version ';
			}else{
				$errorMsg = 'IWP Client plugin connection error.';
			}
			if (triggerPhoenixBackupFailedTask($historyID, $actionResponse, $curlInfo['errorNo'], $curlInfo['info']['http_code'])) {
				return checkTriggerStatus();
			}
			
			$errorResponse = true;
			if(manageClients::methodErrorResponseExists($actionResponse)){
				$errorData['status'] = 'processingResponse';
				$errorData['microtimeStarted'] = $updateHistoryData['microtimeStarted'];
				$errorData['microtimeEnded'] = $updateHistoryData['microtimeEnded'];
				updateHistory($errorData, $historyID);
				$errorResponse = manageClients::executeErrorResponse($actionResponse, $historyID, $updateHistoryData);
			}
			if ($errorResponse) {
				$updateHistoryAdditionalData = array();
				$updateHistoryAdditionalData['status'] = $updateHistoryData['status'] = 'error';	
				$updateHistoryAdditionalData['error'] = $updateHistoryData['error'] = 'main_plugin_connection_error';
				$updateHistoryAdditionalData['errorMsg'] = $errorMsg;
				updateHistory($updateHistoryData, $historyID, $updateHistoryAdditionalData);
			}
			
			if ($action == 'getAdditionalStats') {
				setHook('googleAutoRefresh', $siteID);
			}
			return checkTriggerStatus();	
		 }
		removeResponseJunk($rawResponseData);
		if (strrpos($rawResponseData, '_IWP_JSON_PREFIX_') !== false) {
			$responseDataArray = explode('_IWP_JSON_PREFIX_', $rawResponseData);
			$responseRawData = $responseDataArray[1];
			$responseData = processCallReturn( json_decode(base64_decode($responseRawData), true) );
		} else{
			$responseData = processCallReturn( unserialize(base64_decode($rawResponseData)) );
		}
	} else{
		$responseData = $rawResponseData;
	}
	
	$updateHistoryData['status'] = 'processingResponse';
	updateHistory($updateHistoryData, $historyID);
	
	//handling reponseData below
	
	if(manageClients::methodResponseExists($actionResponse)){
		$response = manageClients::executeResponse($actionResponse, $historyID, $responseData);
		//call_user_func('manageClients::'.$funcName, $historyID, $responseData);
		$status = "completed";
		$historyReponseStatus = Reg::get("historyResponseStatus");
		if(isset($historyReponseStatus[$historyID])){
			$status = $historyReponseStatus[$historyID];
		}
		if ($response !== 'notUpdate') {
			updateHistory(array('status' => $status), $historyID);
		}
		if ($action == 'getAdditionalStats') {
			setHook('googleAutoRefresh', $siteID);
		}
		panelRequestManager::spawnNonBlocking($historyID);
		return true;
	}
	else{
		if (in_array($type, array('backup', 'scheduleBackup'))) {
			if (file_exists(APP_ROOT."/addons/scheduleBackup/controllers/manageClientsScheduleBackup.php")) {
				@include_once(APP_ROOT."/addons/scheduleBackup/controllers/manageClientsScheduleBackup.php");
				manageClientsScheduleBackup::scheduleBackupRunTaskResponseProcessor($historyID, $responseData);
				$historyDataTemp = getHistory($historyID);
				if($historyDataTemp['status'] != 'multiCallWaiting'){
					$updateHistoryAdditionalData['status'] = $updateHistoryData['status'] = 'error';	
					$updateHistoryAdditionalData['error'] = $updateHistoryData['error'] = 'unable_process_response_processor';
					$updateHistoryAdditionalData['errorMsg'] = 'Unable to process response processor';
					updateHistory($updateHistoryData, $historyID, $updateHistoryAdditionalData);
				}
			}else{
				$updateHistoryAdditionalData['status'] = $updateHistoryData['status'] = 'error';	
				$updateHistoryAdditionalData['error'] = $updateHistoryData['error'] = 'no_response_processor';
				$updateHistoryAdditionalData['errorMsg'] = 'There is no response processor for this task ('.$actionResponse.')';
				updateHistory($updateHistoryData, $historyID, $updateHistoryAdditionalData);
			}
		}else{
			updateHistory(array('status' => 'completed', 'param2' => 'no_response_processor'), $historyID);
		}
		echo '<br>no_response_processor';
		return 'no_response_processor';
	}
}

function multicallParentHisIDkill($updateHistoryData, $historyID, $updateHistoryAdditionalData){
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyID
					)
			);
	$historyData = DB::getRow("?:history", "*", $where);
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyData['parentHistoryID']
					)
			);
	$parentHistoryData = DB::getRow("?:history", "*", $where);
	if ($parentHistoryData['status'] == 'multiCallWaiting') {
		updateHistory($updateHistoryData, $historyData['parentHistoryID'], $updateHistoryAdditionalData);
	}
}

function multicallRestoreHisIDkill($updateHistoryData, $historyID, $updateHistoryAdditionalData){
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyID
					)
			);
	$historyData = DB::getRow("?:history", "*", $where);
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyData['parentHistoryID']
					)
			);
	$parentHistoryData = DB::getRow("?:history", "*", $where);
	if ($parentHistoryData['status'] == 'multiCallWaiting' && $parentHistoryData['action'] == 'restoreBackupDownlaod') {
		updateHistory($updateHistoryData, $historyData['parentHistoryID'], $updateHistoryAdditionalData);
	}
}

function isTasksRunningByActionID($actionID){
	$where = array(
			'query'		=> "actionID = ':actionID' AND status NOT IN ('completed', 'netError', 'error')",
			'params' 	=> array(
					':actionID'	=> $actionID
				)
			);
	return DB::getExists("?:history", "historyID", $where);
}

function getCompletedTaskIDsByActionID($actionID){
	$where = array(
			'query' => "actionID = ':actionID' AND status IN ('completed', 'netError', 'error')",
			'params' => array(
				':actionID'	=> $actionID,
				)
			);
	$completedTask = DB::getArray("?:history", "historyID, siteID", $where);
	return $completedTask;
}

function getHistoryAdditionalDataByHistoryID($historyID){
	$where = array(
			'query'  => "historyID = :historyID" ,
			'params' => array(
				':historyID' => $historyID,
				)
			);
	$data = DB::getArray("?:history_additional_data", "historyID, status, error, errorMsg, uniqueName", $where);
	return $data;
}

function stripHeaders(&$rawResponseData, $curlInfo){  
    if(isset($curlInfo["info"]["header_size"])) { 
        $header_size = $curlInfo["info"]["header_size"];  
        $rawResponseData = substr($rawResponseData, $header_size);        
    } 
}

function retryFailedTasksChecker($historyID, $actionResponse, $errorNo = NULL, $http_code = NULL){
	$retryErrors = new errorManager();
	$needRetryActionResponse = array('getStats', 'getPluginsThemes', 'installPluginsThemes', 'updateAll'); // actions of IWP
	$where = array(
		      		'query' =>  "historyID=':historyID'",
			      	'params' => array(
		               ':historyID'=>$historyID
					)
				);

	$currentRetryStatus = DB::getFields("?:history", "retried", $where);

    if ($currentRetryStatus[0] == 0 && (in_array($actionResponse, $needRetryActionResponse)) && ($retryErrors->checkErrorExists($errorNo, 'retryFailedTasksChecker') || $retryErrors->checkErrorExists($http_code, 'retryFailedTasksChecker'))) {
		$retriedTask = array('status'=>'retry','param2'=>'retryFailedTasksChecker');
    	if (isIWPDebugModeEabled()) {
	    	$param1['actionResponse'] = base64_encode($actionResponse);
	    	$param1['errorNo'] = $errorNo;
	    	$param1['http_code'] = $http_code;
	    	$retriedTask['param1'] = serialize($param1);
    	}
		DB::update('?:history', $retriedTask, $where);
		return true;
	} else {
		return false;
	}
}

function insertHTTPCodeErrorsOfICIntoTempStorage($type, $action, $historyID, $errorData){
	if ($type != 'installClone' && $action != 'testConnection') {
		return '';
	}
	$actionID = DB::getField("?:history","actionID", "historyID = ".$historyID);
	DB::insert("?:temp_storage", array('type' => 'getICTestConnection', 'paramID' => $actionID, 'time' => time(), 'data' =>  serialize(array('error' => $errorData))));

}

function isNonCookieSites($siteID, $historyData){
    $type = $historyData['type'];
    $action = $historyData['action'];
    $isPluginResponse = $historyData['isPluginResponse'];
    
    $emptySiteID = empty($siteID);
    $isNonPluginResponse = ($isPluginResponse != 1);
    $addNewSite = ($action === 'newSite' && $type === 'installClone');
    return $emptySiteID || $isNonPluginResponse || $addNewSite;
}

function buildCookie($callOpt, $siteID, $historyData){
    if(isNonCookieSites($siteID, $historyData)){
        return $callOpt;
    }
    $useCookie = !defined('USECOOKIE_OPT') || (defined('USECOOKIE_OPT') && USECOOKIE_OPT === TRUE);
    if($useCookie){
        $where = array(
		      		'query' =>  "siteID = ':siteID'",
		      		'params' => array(
		               ':siteID'=>$siteID
       				)
    			);
        $cookie = DB::getField("?:sites", "siteCookie", $where);
        if(!empty($callOpt) || !empty($cookie)){
            $callOpt['useCookie'] = 1;
            $type = $historyData['type'];
            if($type === 'cookie'){
                return $callOpt;
            }
            if(hasCookieExpired($cookie)){
                $swap = Reg::get('currentRequest.actionID');
                Reg::set('currentRequest.actionID', uniqid('', true)); 
                manageClientsFetch::getCookieProcessor($siteID);// direct execute
                Reg::set('currentRequest.actionID', $swap); 
                $cookie = DB::getField("?:sites", "siteCookie", $where );
            }
            $callOpt['cookie'] = $cookie;
        }else{
            $callOpt = array('useCookie'=>1);
        }
        return $callOpt;
    }
}

function hasCookieExpired($siteCookie){
    if(!trim($siteCookie)){
        return true;
    }

    $cookieDelimiter = ';';
    $cookies = explode($cookieDelimiter, $siteCookie);
    $encodedPipe = '%7C';
    foreach ($cookies as $cookie) {
        $isWPCookie = strpos(trim($cookie), 'wordpress') === 0;
        $tokens = explode($encodedPipe, $cookie);
        $timeToken = $tokens[1];
        if ($isWPCookie && is_numeric($timeToken)) {
            $now = time();
            $isExpired = $now > $timeToken;
            return $isExpired;
        }
    }
    return false;
}

function extractCookie($rawResponseData){
    preg_match_all('/^Set-Cookie: (.*?;)/sim', $rawResponseData, $cookieTemp);
    return implode(" ", $cookieTemp[1]);
}
	
function saveCookie($cookie, $siteID){
	if (!hasValidCookie($cookie)) {
		return false;
	}
    if(!empty($cookie)){
    	 $where = array(
			      		'query' =>  "siteID = ':siteID'",
			      		'params' => array(
			               ':siteID'=>$siteID
           				)
        			);
        DB::update("?:sites", "siteCookie='".$cookie."'", $where);
    }
}

function hasValidCookie($siteCookie){
	$cookieDelimiter = ';';
    $cookies = explode($cookieDelimiter, $siteCookie);
    $encodedPipe = '%7C';
    foreach ($cookies as $cookie) {
        $isWPCookie = strpos(trim($cookie), 'wordpress') === 0;
        $tokens = explode($encodedPipe, $cookie);
        $timeToken = $tokens[1];
        if ($isWPCookie && is_numeric($timeToken)) {
            return true;
        }
    }
    return false;
}

function addNoCacheToURL(&$URL, $historyData){

	if( defined('DISABLE_NO_CACHE_TO_URL') && DISABLE_NO_CACHE_TO_URL ){
		return false;
	}

	$noCacheCalls = array();
	$noCacheCalls['plugins']['install'] = $noCacheCalls['themes']['install'] = 1;
	$noCacheCalls['plugins']['manage'] = $noCacheCalls['themes']['manage'] = 1;	
	$noCacheCalls['plugins']['get'] = $noCacheCalls['themes']['get'] = 1;
	$noCacheCalls['stats']['getStats'] = 1;
	$noCacheCalls['PTC']['update'] = 1;
	$noCacheCalls['clientPlugin']['update'] = 1;
	$noCacheCalls['site']['add'] = 1;

	$type = $historyData['type'];
	$action = $historyData['action'];

	if( $noCacheCalls[$type][$action] ){

		$randStr = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), rand(3, 16), 8);//generating random 8 char str

		$URLParts = parse_url($URL);

		//adding new get variable to URL
		parse_str($URLParts['query'], $getVars);
		$getVars['no_cache_'.$randStr] = time();
		$URLParts['query'] = $getVars;

		$URL = httpBuildURLCustom($URLParts);
	}
}

function addWPLoadToURL(&$URL, $historyData, $isAdminURL, $siteID){
	if( (defined('DISABLE_WPLOAD_URL') && DISABLE_WPLOAD_URL) || $isAdminURL == true ){
		return false;
	}
	$skipActions = array('get', 'add', 'restoreNew', 'bridgeExtractMulticallRestore', 'deleteSite', 'cloneRun', 'cloneRunMulticall', 'newSite', 'newSiteWithoutFTP', 'testConnection');
	$requestURL = getSiteURLFromStatsBySiteID($siteID);
	if (!empty($requestURL) && !in_array($historyData['action'], $skipActions)) {
		$requestURLAddress = str_ireplace(array('www.', 'http://', 'https://'), '', $requestURL);
		$requestURLAddress = rtrim($requestURLAddress, '/');
		$siteAddress = str_ireplace(array('www.', 'http://', 'https://'), '', $URL);
		$siteAddress = rtrim($siteAddress, '/');
		if ($requestURLAddress != $siteAddress) {
			$URL = $requestURL;
		}
	}
	if (!empty($historyData['isPluginResponse']) && $historyData['isPluginResponse'] == 1 && !in_array($historyData['action'], $skipActions)) {
		$wpLoaodURL = trim($URL, '/').'/wp-load.php';
		$URL = $wpLoaodURL;
	}

}

function addReferrerURL(&$callOpt, $siteID){
	if (!empty($siteID)) {
		$where = array(
			      		'query' =>  "siteID = ':siteID'",
			      		'params' => array(
			               ':siteID'=>$siteID
           				)
        			);
		$URL = DB::getField("?:sites", "URL", $where);
		$callOpt['referrerURL'] = trim($URL, '/').'/';
	}
}

function onAsyncFailUpdate($historyID, $info){
	
	if($info['status'] == true){
            updateConnectionMode($info['modeData'], $historyID);
            return false; 
        }
	
	$errorMsg = 'Connection error: ';
	$error = 'connection_error';
	
	if(!empty($info['error'])){
		$errorMsg .= $info['error'];
		$error =  'connection_error_info';
	}
	
	if($info['writable'] === false){
		$errorMsg .= 'Unable to write request';
		$error = 'connection_error_unable_to_write_request';
	}	
	
	$updateHistoryAdditionalData = array();
	$updateHistoryAdditionalData['status'] = $updateHistoryData['status'] = 'error';	
	$updateHistoryAdditionalData['error'] = $updateHistoryData['error'] = $error;
	$updateHistoryAdditionalData['errorMsg'] = $errorMsg;
	updateHistory($updateHistoryData, $historyID, $updateHistoryAdditionalData);
	return true;
	
}

function updateConnectionMode($modeData, $historyID){
    $where = array(
        'query' =>   "H.historyID = :historyID",
        'params' => array(
                    ':historyID'=> $historyID
                    )
            );
    $updateRequest = array(
        'connection_method' => serialize($modeData)
    );
    $isUpdated = DB::update("?:history H", $updateRequest, $where);
    return $isUpdated;
}

function removeResponseJunk(&$response){
	$headerPos = stripos($response, '<IWPHEADER');
	if($headerPos !== false){
		$response = substr($response, $headerPos);
		$response = substr($response, strlen('<IWPHEADER>'), stripos($response, '<ENDIWPHEADER')-strlen('<IWPHEADER>'));
	}
}

function getServiceResponseToArray($response){
	removeResponseJunk($response);
	$response = @base64_decode($response);
	$response = @unserialize($response);
	return $response;
}

function responseDirectErrorHandler($historyID, $responseData){
	
	if(!empty($responseData['error']) && is_string($responseData['error'])){
		$where = array(
			      		'query' =>  "historyID=':historyID'",
			      		'params' => array(
			               ':historyID'=>$historyID
           				)
        			);
		DB::update("?:history_additional_data", array('status' => 'error', 'errorMsg' => strip_tags($responseData['error']), 'error' => $responseData['error_code']), $where);
		return true;
	}
	return false;
	
}

function responseDirectErrorHandlerForRestore($historyID, $responseData){
	
	if(!empty($responseData['error']) && is_string($responseData['error'])){
		$where = array(
			      		'query' =>  "historyID=':historyID'",
			      		'params' => array(
			               ':historyID'=>$historyID
           				)
        			);
		DB::update("?:history_additional_data", array('status' => 'error', 'errorMsg' => strip_tags($responseData['error']), 'error' => $responseData['error_code']), $where);
		$historyData = DB::getRow("?:history", "*", $where);
		$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			      		   ':historyID' => $historyData['parentHistoryID']
           				)
        			);
		DB::update("?:history_additional_data", array('status' => 'error', 'errorMsg' => strip_tags($responseData['error']), 'error' => $responseData['error_code']), $where);
		DB::update("?:history", array('status' => 'error'), $where);
		return true;
	}
	return false;
	
}

function exitOnComplete(){
	$maxTimeoutSeconds = 60;//1 min
	if(!empty($GLOBALS['offline'])){
		$maxTimeoutSeconds = 60 * 15;//15 min
	}
	$where = array(
			      		'query' =>  "actionID = ':actionID' AND status NOT IN('completed', 'error', 'netError')",
			      		'params' => array(
			               ':actionID'=>Reg::get('currentRequest.actionID')
           				)
        			);
	$maxTimeoutTime = time() + $maxTimeoutSeconds;
	while(DB::getExists("?:history", "historyID", $where) && $maxTimeoutTime > time()){
		usleep(100000);//1000000 = 1 sec
	}
}

function sendAfterAllLoad(&$requiredData){//changing exit on complete technique

	$_requiredData = array();
	if(!empty($requiredData)){
		$exceptionRequireData = array('getHistoryPanelHTML');
		foreach($requiredData as $key => $value){
			if(!in_array($key, $exceptionRequireData)){
				$_requiredData[$key] = $requiredData[$key];
				unset($requiredData[$key]);
			}
		}
	}
	
        $waitActions= manageCookies::cookieGet('waitActions');
        if(empty($waitActions)) {
            $waitActions = array();
        } 
        
	$actionID = Reg::get('currentRequest.actionID');
	$currentTime = time();
	$waitActions[$actionID] = array('timeInitiated' => $currentTime,
									'timeExpiresFromSession' => $currentTime + (20 * 60),
									'requiredData' => $_requiredData
									);
	if (!headers_sent()) {
        manageCookies::cookieSet('waitActions',$waitActions,array('expire'=>0));
	}
}

function clearUncompletedTask(){
	$addtionalTime = 30;//seconds
	$time = time();
	
	//$updateData = array( 'H.status' => 'netError',
	//					 'H.error' => 'timeoutClear',
	//					 'HAD.status' => 'netError',
	//					 'HAD.error' => 'timeoutClear',
	//					 'HAD.errorMsg' => 'Timeout'
	//					);
	
	$updateData  = "H.status = IF(H.status IN('initiated', 'running'), 'netError', IF(H.status = 'processingResponse', 'error', 'error'))";
	$updateData .= ", HAD.status = IF(H.status IN('initiated', 'running'), 'netError', IF(H.status = 'processingResponse', 'error', 'error'))";
	$updateData .= ", H.error = IF(H.status IN('initiated', 'running'), 'timeoutClear', IF(H.status = 'processingResponse', 'processingResponseDied', 'unknownError'))";
	$updateData .= ", HAD.error = IF(H.status IN('initiated', 'running'), 'timeoutClear', IF(H.status = 'processingResponse', 'processingResponseDied', 'unknownError'))";
	$updateData .= ", HAD.errorMsg = IF(H.status IN('initiated', 'running'), 'Timeout', IF(H.status = 'processingResponse', 'Error in processing data', 'Connection error: please try different connection methods '))";
	$where = "H.historyID = HAD.historyID";
	$where .= " AND ( H.status IN('initiated', 'running') OR (H.status = 'processingResponse' AND (H.microtimeEnded + 150) < ".DB::esc($time).") )";//150 seconds
	$where .= " AND (H.microtimeInitiated + H.timeout + ".DB::esc($addtionalTime).") < ".DB::esc($time)."";
	$where .= " AND H.microtimeInitiated > 0";//this will prevent un-initiated task from clearing
	DB::update("?:history H, ?:history_additional_data HAD", $updateData, $where);
}

//Generate the passcodeMail and send it
function sendPasscodeMail($passcode, $userID) {
	$where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=>$userID
           				)
        			);
    $user = DB::getRow("?:users", "email, name", $where);
    $passlinkInfo = array(
        'passcodeLink'  =>  APP_URL."login.php?passlink=".  base64_encode($passcode),
        'passcode'      =>  $passcode,
        'userEmail'     =>  $user['email'],
        'requestIp'     =>  $_SERVER['REMOTE_ADDR'],
        'appUrl'        =>  APP_URL,
        'expired'       =>  date("g:i a \o\\n F j", time()+(60*60)),    //Set the expired as 1 hrs
        'userID'        =>  $userID
    );
    return sendAppMail($passlinkInfo, $contentTPL = '/templates/email/passcodeLink.tpl.php');
}

//Verifying by Passcode
function verifyPasscode($params,$type="code") {
    
    $authInfo = unserialize(manageCookies::cookieGet('authCookieInfo'));
    $where1 = array(
			      		'query' =>  "userID = ':userID'" ,
			      		'params' => array(
			               ':userID'=>$authInfo['userId']
           				)
        			);
    $email = DB::getField("?:users", "email" ,$where1);
    if(time()<=$authInfo['validity']) {
    	$where = array(
			      		'query' =>  "userID = ':userID'" ,
			      		'params' => array(
			               ':userID'=>$authInfo['userId']
           				)
        			);
        $dbAuthInfo = DB::getField("?:users", "authInfo", $where);
        $dbAuthInfo = unserialize(base64_decode($dbAuthInfo));
        $passcode = ($type=="code")?$params['passcode']:base64_decode($params);
        if(!empty($passcode) && !empty($dbAuthInfo['passcode']) && (string)$dbAuthInfo['passcode'] === (string)$passcode) {
            manageCookies::cookieUnset('authCookieInfo');
            DB::update("?:users", array("authInfo" => ""), $where);
            loginByUserId($authInfo['userId']);
            addLoginLog($email, 'authBasic', 'success', '');
            header('Location: '.APP_URL); //'Location: ' => index.php
            exit;
        } else {
            $passVerifyCount =  manageCookies::cookieGet('passVerifyCount');
            if(empty($passVerifyCount) || $passVerifyCount <2) {
                $passVerifyCount = ($passVerifyCount=="")?1:$passVerifyCount+1;
                manageCookies::cookieSet('passVerifyCount', $passVerifyCount,array('expire'=>0));
                $errorMsg = 'passcodeInvalid';
                addLoginLog($email, 'authBasic', 'error', getLoginPageMsg($errorMsg));
                header('Location: login.php?view=getPasscode&errorMsg='.$errorMsg);
                exit;
            } else {
                manageCookies::cookieUnset('passVerifyCount');
                $lockOutTime = time()+(60*15);
                DB::update("?:users", array("authInfo" => $lockOutTime), $where);
                $lockOut = base64_encode($lockOutTime);
                $errorMsg = 'accountLock';
                $errorMsgFormat = getLoginPageMsg($errorMsg);
                addLoginLog($email, 'authBasic', 'error', sprintf($errorMsgFormat, convertToMinSec($lockOutTime-time())));
                header('Location: login.php?errorMsg='.$errorMsg.'&lockOut='.$lockOut);
                exit;
            }
            
        }
    } else {
        $errorMsg = 'passcodeValidity';
        addLoginLog($email, 'authBasic', 'error', getLoginPageMsg($errorMsg));
        header('Location: login.php?errorMsg='.$errorMsg);
        exit;
    }
    exit;
}

//login by userID
function loginByUserId($userID) {
	$where = array(
			      		'query' =>  "userID = ':userID' ORDER BY userID ASC LIMIT 1",
			      		'params' => array(
			               ':userID'=>$userID
           				)
        			);
    $userInfo = DB::getRow("?:users", "userID, accessLevel, email,password", $where);
    loginByUser($userInfo);
}

//login by userID
function loginByUserName($userName) {
	$where = array(
			      		'query' =>  "email = ':email' ORDER BY userID ASC LIMIT 1" ,
			      		'params' => array(
			               ':email'=>$userName
           				)
        			);
    $userInfo = DB::getRow("?:users", "userID, accessLevel, email,password", $where);
    loginByUser($userInfo);
}

//Login by given user info
function loginByUser($userInfo) {
	$userID   = $userInfo["userID"];
    $userEmail = strtolower(trim($userInfo["email"]));
	$userRole = $userInfo['accessLevel'];
    $userPass = $userInfo["password"];
    $userCookie = md5($userEmail.$userPass);
    $userCookie = $userEmail . '||' . $userCookie. '||'.$userRole;
    manageCookies::cookieSet('userCookie', $userCookie,array('expire'=>0));
    $where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=>$userID
           				)
        			);
    DB::update("?:users", array("recentlyLoggedIn" => time()), $where);
}

//Login .
function userLogin($params){
	
	if(empty($params)){ return false; }
	/*if($isUserExists){*/	
		if(function_exists('multiUserStatus')){
			if(multiUserStatus($params)){
				$isUserExists = true;
			}
			else{
				$isUserExists = false;
			}
		}
		else{
			$where = array(
			      		'query' =>  "email = ':email' AND password = ':password' ORDER BY userID ASC LIMIT 1" ,
			      		'params' => array(
			               ':email'=>trim($params["email"]),
			               ':password'=>sha1($params["password"])
           				)
        			);
			$userName = DB::getRow("?:users", "userID, accessLevel, email", $where);
			$isUserExists = !empty($userName["userID"]) ? true : false;
			
			$userID = $userName["userID"];
			if($isUserExists) $GLOBALS['userID'] = $userID;
			if($userName['accessLevel'] != 'admin' && $isUserExists){
				$errorMsg = 'onlyAdmin';
				addLoginLog($params['email'], 'authNone', 'error', getLoginPageMsg($errorMsg));
				header('Location: login.php?errorMsg='.$errorMsg);
				exit;
			}
		}
	/*}*/
	
        // If user enter wrong passcode 3times, We set authInfo+1hrs. So user not able to login the panel by next 1 hrs.
        //We use the $authData to identify the authInfo have serialize data or not. If its not serialize data there means unserialize will return the false(boolion) value
        //echo $GLOBALS['userID'];die;
		$where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=>$GLOBALS['userID']
           				)
        			);
		$dbAuthInfo = DB::getField("?:users", "authInfo", $where );
        $authData = @unserialize($dbAuthInfo);
		if($authData === false && $dbAuthInfo!="" && (is_base64($dbAuthInfo) == false) && (time()<$dbAuthInfo)) {
            $lockOut = base64_encode($dbAuthInfo);
            $errorMsg = 'accountLock';
            $errorMsgFormat = getLoginPageMsg($errorMsg);
            addLoginLog($params['email'], 'authBasic', 'error', sprintf($errorMsgFormat, convertToMinSec(base64_decode($lockOut)-time())));
            header('Location: login.php?errorMsg='.$errorMsg.'&lockOut='.$lockOut);
            die;
        }elseif($authData === false && $dbAuthInfo!="" && (time()>=$dbAuthInfo)){
            DB::update("?:users", array("authInfo" => ""), $where);
        }
        
		$allowedLoginIPs = DB::getFields("?:allowed_login_ips", "IP", "1", "IP");
		$allowedLoginIPsClear = 1;
		if($isUserExists && !empty($allowedLoginIPs)){
			$allowedLoginIPsClear = 0;
			foreach($allowedLoginIPs as $IP){
				if($returnFlag = IPInRange($_SERVER['REMOTE_ADDR'], trim($IP))){
					$allowedLoginIPsClear = 1;
					break;
				}
			}
		}
	
	if($isUserExists && $allowedLoginIPsClear == 1){
            //After all login check done, we look the authendication method.
            if(isExistOption('loginAuthType')) { $loginAuthType = getOption('loginAuthType'); } else { $loginAuthType = 'authNone'; }
            if (defined('DISABLE_2FA') && DISABLE_2FA) {
           		$loginAuthType = 'authNone';	
            }
            if($loginAuthType=="authBasic") {
                $passcode = mt_rand(100000, 999999);
                $mailPasscode= base64_encode($passcode);
                $validity = time()+(60*60);
                $authInfo = base64_encode(serialize(array('userId'=>$GLOBALS['userID'],'passcode'=>$passcode,'validity'=>$validity)));
                $authCookieInfo = serialize(array('userId'=>$GLOBALS['userID'],'validity'=>$validity));
                manageCookies::cookieSet('authCookieInfo', $authCookieInfo,array('expire'=>0));
                DB::update("?:users", array("authInfo" => $authInfo), $where);
                if(sendPasscodeMail($passcode,$GLOBALS['userID'])) {
                    addLoginLog($params['email'], 'authNone', 'success', '', 'authBasic');
                    header('Location: login.php?view=getPasscode&successMsg=passcodeMailSent');
                    exit;
                } else {
                    $errorMsg = 'passcodeMailError';
                    addLoginLog($params['email'], $loginAuthType, 'error', getLoginPageMsg($errorMsg));
                    header('Location: login.php?errorMsg='.$errorMsg);
                    exit;
                }
            }elseif(function_exists ('getDuoFrame') && $loginAuthType=="authDuo") {
                if(!($GLOBALS['duoFrameStr'] = getDuoFrame($params["email"]))) {
                    $errorMsg = 'duoConnectionError';
                    addLoginLog($params['email'], $loginAuthType, 'error', getLoginPageMsg($errorMsg));
                    header('Location: login.php?errorMsg='.$errorMsg);
                    exit;
                } else {
                    $_GET['view'] = "duoFrame";
                }
            }else {
                loginByUserId($GLOBALS['userID']);
                addLoginLog($params['email'], 'authNone', 'success');
                header('Location: '.APP_URL); //'Location: ' => index.php
                exit;
            }
	}
	else{
            manageCookies::cookieUnset('userCookie');
            $errorMsg = 'invalid';
            if($allowedLoginIPsClear == 0){
                    $errorMsg = 'access';
            }
            addLoginLog($params['email'], 'authNone', 'error', getLoginPageMsg($errorMsg));
            header('Location: login.php?errorMsg='.$errorMsg);
            exit;
	}
}

function userLogout($userRequest=false){
	$authCookieInfo = manageCookies::cookieGet('authCookieInfo');
	if (empty($authCookieInfo)) {
		manageCookies::cookieAllUnset();
	}
	if($userRequest){
		$successMsg = 'logout';
		if(!defined('IS_AJAX_FILE')){
			header('Location: login.php?successMsg='.$successMsg);
			exit;
		}
	}else{
		if(!defined('IS_AJAX_FILE')){
				header('Location: login.php');
				exit;
		}
	}
}

function resetPasswordLinkValidate($params){
	
	$isValidLink = false;
	$isExpired = false;
	$isValidAttempt = false;

	$userDetails = DB::getRow("?:users", "userID, resetPassword", "sha1(email) = '".DB::realEscapeString($params['transID'])."'");

	if(!empty($userDetails) && is_array($userDetails)){
		$userID = $userDetails['userID'];
		$resetDetails = $userDetails['resetPassword'];
		if(!empty($resetDetails)){
			$resetDetails = unserialize($resetDetails);

			if(!empty($resetDetails) && is_array($resetDetails) && !empty($resetDetails['resetHash']) && !empty($resetDetails['validity'])){
				if($resetDetails['resetHash'] === $params['resetHash']){
					$isValidLink = true;
					if($resetDetails['validity'] > 0  && $resetDetails['validity'] < time()){
						$isExpired = true;
					}
					if (isset($resetDetails['attempt']) && $resetDetails['attempt']<3) {
						$resetDetails['attempt'] += 1;
						$where = array(
				      		'query' =>  "userID = ':userID' ",
				      		'params' => array(
				               ':userID'=>$userID
	           				)
	        			);
						DB::update("?:users", array("resetPassword" => serialize($resetDetails)), $where);
						$isValidAttempt = true;
					}
				}
			}
		}

	}
	return array('isValidLink' => $isValidLink, 'isExpired' => $isExpired, 'isValidAttempt' => $isValidAttempt);
}

function userLoginResetPassword($params){

	
	if( (isset($params['view']) && $params['view'] == 'resetPasswordChange') ||  (isset($params['action']) && $params['action'] == 'resetPasswordChange') ){//validate IWP reset password link, before showing the form or saving new password

		$result = resetPasswordLinkValidate(array('resetHash' => $params['resetHash'], 'transID' => $params['transID']));
		
		if($result['isValidLink'] == true && $result['isExpired'] == true){
			header("Location: login.php?errorMsg=resetPasswordLinkExpired");
			exit;
		}
		elseif($result['isValidLink'] == false){
			$errorMsg = 'resetPasswordLinkInvalid';
			header("Location: login.php?errorMsg=resetPasswordLinkInvalid");
			exit;
		}elseif($result['isValidAttempt'] == false){
			$errorMsg = 'resetPasswordLinkExceedAttempt';
			header("Location: login.php?errorMsg=resetPasswordLinkExceedAttempt");
			exit;
		}
		//if above if conditions fails, then it all good, allow to load reset password form

	}
	

	if(isset($params['action']) && $params['action'] == 'resetPasswordChange'){

		//above code should validate the resetHash and transID

		if(!isset($params['newPassword']) || empty($params['newPassword'])){
			header('Location: login.php?view=resetPasswordChange&resetHash='.$params['resetHash'].'&transID='.$params['transID'].'&errorMsg=resetPasswordInvalidPassword');
			exit;
		}
		$where = array(
			      		'query' =>  "sha1(email) = ':email' ",
			      		'params' => array(
			               ':email'=>$params['transID']
           				)
        			);
		$isUpdated = DB::update("?:users", array( "password" => sha1($params['newPassword']), "resetPassword" => serialize(array()) ), $where);
		if($isUpdated){
			header('Location: login.php?successMsg=resetPasswordChanged');
			exit;
		}else{
			header('Location: login.php?view=resetPasswordChange&resetHash='.$params['resetHash'].'&transID='.$params['transID'].'&errorMsg=resetPasswordFailed');
			exit;
		}


	}
	elseif(isset($params['action']) && $params['action'] == 'resetPasswordSendMail'){
		$params["email"] = DB::realEscapeString($params['email']);
		$where = array(
			      		'query' =>  "email = ':email'",
			      		'params' => array(
			               ':email'=>$params["email"]
           				)
        			);
		$userDets = DB::getRow("?:users", "userID", $where );
		$isUserExists = !empty($userDets["userID"]) ? true : false;	
		if(!$isUserExists){
			header('Location: login.php?view=resetPassword&errorMsg=resetPasswordEmailNotFound');
			exit;
		}

		$microtime = microtime(true);
		
		$hashValue = serialize(array('hashCode' => APP_INSTALL_HASH, 'uniqueTime' => $microtime+rand(5, 15), 'userPin' => $userDets['userID']));
		$resetHash = sha1($hashValue);
		
		$where = array(
			      		'query' =>  "userID = ':userID' ",
			      		'params' => array(
			               ':userID'=>$userDets['userID']
           				)
        			);
		DB::update("?:users", array("resetPassword" => serialize(array("resetHash" => $resetHash, "validity" => time()+86400, "attempt"=>0))), $where);
		
		$verificationURL = APP_URL."login.php?view=resetPasswordChange&resetHash=".$resetHash."&transID=".sha1($params["email"]);
		
		$isSent = sendAppMail(array('userID' => $userDets["userID"], 'verificationURL' => $verificationURL), '/templates/email/resetPassword.tpl.php');
		
		if(!empty($isSent)){
			header('Location: login.php?successMsg=resetPasswordMailSent');
			exit;
		}
		else{
			header('Location: login.php?view=resetPassword&errorMsg=resetPasswordMailError');
			exit;
		}

	}
}

function checkUserLoggedIn(){
	
	$return = false;
        $userCookie = manageCookies::cookieGet('userCookie');
        if($userCookie!='') {
            list($userEmail,$userSlat, $accessLevel) = explode('||', $userCookie);
            $userEmail = filterParameters($userEmail);
            if($userEmail!='' && $userSlat!='') {
            		$where = array(
			      		'query' =>  "email = ':email'" ,
			      		'params' => array(
			               ':email'=>trim($userEmail)
           				)
        			);
                    $userInfo = DB::getRow("?:users", "userID,email,password, accessLevel", $where );
                    
                    $GLOBALS['userID'] = $userInfo['userID'];
                    $GLOBALS['email'] = strtolower($userInfo['email']);
                    $stringtoSalt = $GLOBALS['email'].$userInfo['password'];
                    if(!empty($stringtoSalt)){
                        $dbSlat = md5($GLOBALS['email'].$userInfo['password']);
                        if($userSlat==$dbSlat && (empty($accessLevel) || $accessLevel === $userInfo['accessLevel'])) {
                            $return = true;
                        }
                    }
            }
        }
   

	if($return == false){
		userLogout();
	}
	return $return;
}

function checkUserLoggedInAndRedirect(){
	//check session, if not logged in redirect to login page
	if(!defined('USER_SESSION_NOT_REQUIRED') && !defined('IS_EXECUTE_FILE')){
		if(!checkUserLoggedIn()){
			echo jsonEncoder(array('logout' => true));
			exit;
		}
	}
}

function checkRawHistoryAndDelete(){
	$currentTime = time();
	$nextSchedule = getOption('deleteRawHistoryNextSchedule');
	if($currentTime > $nextSchedule){
		$nextSchedule = $currentTime + 86400;
		$thirtyDaysAgo = $currentTime - (30 * 86400);
		$where = "H.microtimeAdded < '".DB::esc($thirtyDaysAgo)."' ";
		$historyIDCount = DB::getField("?:history_raw_details HRD INNER JOIN ?:history H ON HRD.historyID = H.historyID","count(HRD.historyID)",$where);
		if(!empty($historyIDCount)){
			$limitSQL = '';
			if ($historyIDCount >= '2000') {
				$limitSQL = ' LIMIT 2000';
			}
			$historyIDs = DB::getFields("?:history_raw_details HRD INNER JOIN ?:history H ON HRD.historyID = H.historyID","HRD.historyID",$where.$limitSQL);
			if(!empty($historyIDs)){
				$historyIDs = implode("','", DB::esc($historyIDs));
				$isDeleted = DB::delete("?:history_raw_details", "historyID IN ('".$historyIDs."') $limitSQL");
				if($isDeleted && $historyIDCount <= 2000){
					updateOption('deleteRawHistoryNextSchedule', $nextSchedule);
					DB::doQuery("OPTIMIZE TABLE `?:history_raw_details`");		
				}
			}
		}else{
			updateOption('deleteRawHistoryNextSchedule', $nextSchedule);
			return true;
		}
	}
}

function anonymousDataRunCheck(){

	if(!Reg::get('settings.sendAnonymous')){ return false; }
	
	$currentTime = time();	
	$nextSchedule = getOption('anonymousDataNextSchedule');
	
	if($currentTime > $nextSchedule){		
		//execute
		$fromTime = getOption('anonymousDataLastSent');
		$isSent = anonymousDataSend($fromTime, $currentTime);
		if(!$isSent){
			return false;	
		}
		//if sent execute below code
		updateOption('anonymousDataLastSent', $currentTime);
		
		$installedTime = getOption('installedTime');
		
		$weekDay = @date('w', $installedTime);
		$currWeekDay = @date('w', $currentTime);
	    $nextNoOfDays = 7 - $currWeekDay + $weekDay;		
		$nextSchedule = mktime(@date('H', $installedTime), @date('i', $installedTime), @date('s', $installedTime), @date('m', $currentTime), @date('d', $currentTime)+$nextNoOfDays, @date('Y', $currentTime));
		updateOption('anonymousDataNextSchedule', $nextSchedule);
		
	}
}

function anonymousDataSend($fromTime, $toTime){

	$fromTime = (int)$fromTime;
	
	$anonymousData = array();
	$addons = DB::getFields("?:addons", "slug", "1", 'slug');	
	if(!empty($addons)){
		foreach($addons as $slug => $v){
			$addons[$slug] = getAddonVersion($slug);
		}
	}	
	$anonymousData['addonsBought'] = $addons;
	$anonymousData['sites'] 			= DB::getField("?:sites", "count(siteID)", "type = 'normal'");
	$anonymousData['stagingSites'] 			= DB::getField("?:sites", "count(siteID)", "type = 'staging'");
	$anonymousData['groups']			= DB::getField("?:groups", "count(groupID)", "1");
	$anonymousData['groupMaxSites']		= DB::getField("?:groups_sites", "count(siteID) as maxSiteCount", "1 GROUP BY groupID ORDER BY maxSiteCount DESC LIMIT 1", "maxSiteCount");
	$anonymousData['hiddenCount']		= DB::getField("?:hide_list", "count(ID)", "1");
	$anonymousData['favourites']		= DB::getField("?:favourites", "count(ID)", "1");
	$anonymousData['settings']			= DB::getArray("?:settings", "*", "1");
	$anonymousData['users']				= DB::getField("?:users", "count(userID)", "1");
	$anonymousData['allowedLoginIps']	= DB::getField("?:allowed_login_ips", "count(IP)", "1");
		
	$anonymousData['siteNameMaxLength']	= DB::getField("?:sites", "length(name) as siteNameLength", "1 ORDER BY siteNameLength DESC LIMIT 1");	
	$anonymousData['groupNameMaxLength']= DB::getField("?:groups", "length(name) as groupNameLength", "1 ORDER BY groupNameLength DESC LIMIT 1");
	
	//$anonymousData['appVersion'] 				= APP_VERSION;
	$anonymousData['appInstalledTime'] 			= getOption('installedTime');
	$anonymousData['lastHistoryActivityTime'] 	= DB::getField("?:history", "microtimeAdded", "1 ORDER BY historyID DESC");	
	$anonymousData['updatesNotificationMailLastSent'] = getOption('updatesNotificationMailLastSent');
	
	$anonymousData['DBInfo'] = getAnonymousDBInfo();
	//to find hostType
	$anonymousData['hostType'] = 'unknown';
	
	if(!empty($_SERVER['SERVER_ADDR'])){
		$SERVER_ADDR = $_SERVER['SERVER_ADDR'];
	}
	else{
		$SERVER_ADDR = gethostbyname($_SERVER['HTTP_HOST']);
	}
	
	if(!empty($SERVER_ADDR)){
		if(IPInRange($SERVER_ADDR, '127.0.0.0-127.255.255.255')){
			$anonymousData['hostType'] = 'local';
		}
		elseif(IPInRange($SERVER_ADDR, '10.0.0.0-10.255.255.255') || IPInRange($SERVER_ADDR, '172.16.0.0-172.31.255.255') || IPInRange($SERVER_ADDR, '192.168.0.0-192.168.255.255')){
			$anonymousData['hostType'] = 'private';
		}
		else{
			$anonymousData['hostType'] = 'public';
		}
	}
	
	//history stats
	$where = array(
			      		'query' =>  "microtimeAdded > ':fromTime' AND microtimeAdded <= ':toTime' GROUP BY status",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);
	$anonymousData['historyStatusStats']= DB::getFields("?:history", "count(status) as statusCount, status", $where, "status");
	$where = array(
			      		'query' =>  "microtimeAdded > ':fromTime' AND microtimeAdded <= ':toTime'",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);
	$tempHistoryData					= DB::getRow("?:history", "count(historyID) as historyCount, count(DISTINCT actionID) as historyActions", $where);
	$anonymousData['historyCount']		= $tempHistoryData['historyCount'];
	$anonymousData['historyActions']	= $tempHistoryData['historyActions'];
	$where = array(
			      		'query' =>  "H.historyID = HAD.historyID AND H.microtimeAdded > ':fromTime' AND H.microtimeAdded <= ':toTime' GROUP BY HAD.status",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);
	$anonymousData['historyAdditionalStatusStats']	= DB::getFields("?:history H, ?:history_additional_data HAD", "count(HAD.status) as statusCount, HAD.status",$where, "status");
	$where = array(
			      		'query' =>  "H.historyID = HAD.historyID AND H.microtimeAdded > ':fromTime' AND H.microtimeAdded <= ':toTime'",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);
	$anonymousData['historyAdditionalCount']		= DB::getField("?:history H, ?:history_additional_data HAD", "count(HAD.historyID) as historyCount", $where);
	$where = array(
			      		'query' =>  "H.historyID = HAD.historyID AND H.microtimeAdded > ':fromTime' AND H.microtimeAdded <= ':toTime' GROUP BY H.type, H.action, HAD.detailedAction, HAD.status ORDER BY H.type, H.action, HAD.detailedAction, HAD.status",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);	
	$historyEventStatusStatsArray	= DB::getArray("?:history H, ?:history_additional_data HAD", "H.type, H.action, HAD.detailedAction, HAD.status, COUNT(H.historyID) as events", $where);
	$where = array(
			      		'query' =>  "H.historyID = HAD.historyID AND H.microtimeAdded > ':fromTime' AND H.microtimeAdded <= ':toTime' AND HAD.status IN ('error', 'netError')",
			      		'params' => array(
			               ':fromTime'=>$fromTime,
			               ':toTime'=>$toTime

           				)
        			);
	$historyEventErrorCodeStatsArray	= DB::getArray("?:history H, ?:history_additional_data HAD", "H.type, H.action, HAD.detailedAction, HAD.status, HAD.error", $where);
		
	if(!empty($historyEventErrorCodeStatsArray)){
		foreach($historyEventErrorCodeStatsArray as $v){
			if(!empty($v['error'])){
				$errorCodes[$v['type']][$v['action']][$v['detailedAction']][$v['status']][] = $v['error'];
			}
		}
	}
		
	$historyEventStatusStats= array();
	if(!empty($historyEventStatusStatsArray)){
		foreach($historyEventStatusStatsArray as $v){
			
			if(!isset($historyEventStatusStats[$v['type']][$v['action']][$v['detailedAction']]['total'])){
				$historyEventStatusStats[$v['type']][$v['action']][$v['detailedAction']]['total'] = 0;
			}
			$historyEventStatusStats[$v['type']][$v['action']][$v['detailedAction']][$v['status']] = $v['events'];			
			$historyEventStatusStats[$v['type']][$v['action']][$v['detailedAction']]['total'] += $v['events'];
			
			if(is_array($errorCodes[$v['type']][$v['action']][$v['detailedAction']]))
			foreach($errorCodes[$v['type']][$v['action']][$v['detailedAction']] as $key => $value){
				if($key == $v['status']){
					$historyEventStatusStats[$v['type']][$v['action']][$v['detailedAction']]['errorStats'][$v['status']] = array_count_values($value);
				}				
			}
		}
	}	
	
	$anonymousData['historyEventStatusStats'] = $historyEventStatusStats;
		
	$tempSiteStats				= DB::getArray("?:sites", "WPVersion, pluginVersion, isOpenSSLActive, callOpt, network, parent", "1");
	
	//To get contentType for sites.
	foreach($tempSiteStats as $key => $siteStats){

		if(!isset($anonymousData['siteStats']['WPVersion'][$siteStats['WPVersion']]))	{
			$anonymousData['siteStats']['WPVersion'][$siteStats['WPVersion']] = 1;
		}else{
			$anonymousData['siteStats']['WPVersion'][$siteStats['WPVersion']] += 1;
		}

		if(!isset($anonymousData['siteStats']['pluginVersion'][$siteStats['pluginVersion']]))	{
			$anonymousData['siteStats']['pluginVersion'][$siteStats['pluginVersion']] = 1;
		}else{
			$anonymousData['siteStats']['pluginVersion'][$siteStats['pluginVersion']] += 1;
		}

		if(!isset($anonymousData['siteStats']['WPAndClientVersion'][$siteStats['WPVersion'].'-'.$siteStats['pluginVersion']]))	{
			$anonymousData['siteStats']['WPAndClientVersion'][$siteStats['WPVersion'].'-'.$siteStats['pluginVersion']] = 1;
		}else{
			$anonymousData['siteStats']['WPAndClientVersion'][$siteStats['WPVersion'].'-'.$siteStats['pluginVersion']] += 1;
		}

		if(!isset($anonymousData['siteStats']['isOpenSSLActive'][$siteStats['isOpenSSLActive']]))	{
			$anonymousData['siteStats']['isOpenSSLActive'][$siteStats['isOpenSSLActive']] = 1;
		}else{
			$anonymousData['siteStats']['isOpenSSLActive'][$siteStats['isOpenSSLActive']] += 1;
		}

		if(!isset($anonymousData['siteStats']['network'][$siteStats['network']]))	{
			$anonymousData['siteStats']['network'][$siteStats['network']] = 1;
		}else{
			$anonymousData['siteStats']['network'][$siteStats['network']] += 1;
		}

		if(!isset($anonymousData['siteStats']['parent'][$siteStats['parent']]))	{
			$anonymousData['siteStats']['parent'][$siteStats['parent']] = 1;
		}else{
			$anonymousData['siteStats']['parent'][$siteStats['parent']] += 1;
		}
		
		$siteStatsCallOpt = unserialize($siteStats['callOpt']);
		if(!isset($anonymousData['siteStats']['contentType'][$siteStatsCallOpt['contentType']]))	{
			$anonymousData['siteStats']['contentType'][$siteStatsCallOpt['contentType']] = 1;
		}else{
			$anonymousData['siteStats']['contentType'][$siteStatsCallOpt['contentType']] += 1;
		}
	}
	//To get installed plugins
	$sitePlugins = array();
	$tempSitePlugins	= panelRequestManager::getRecentPluginsStatus();
	foreach ($tempSitePlugins as $siteID => $sitePluginData) {

		foreach ($sitePluginData as $slug => $pluginData) {
			$sitePlugins[$slug] = array('isInstalled'=>0,'isActivated'=>0,'name'=>$pluginData['name'],'title'=>$pluginData['title'],'version'=>array(),'isnetworkActivated'=>0);
		}
		}

	foreach ($tempSitePlugins as $siteID => $sitePluginData) {
		foreach ($sitePluginData as $slug => $pluginData) {
			if($pluginData['isInstalled'])	$sitePlugins[$slug]['isInstalled'] += 1;
			if($pluginData['isActivated'])	$sitePlugins[$slug]['isActivated'] += 1;
			if($pluginData['network'])		$sitePlugins[$slug]['isnetworkActivated'] += 1;
			if(!isset($sitePlugins[$slug]['version'][$pluginData['version']]))	{
				$sitePlugins[$slug]['version'][$pluginData['version']] = 1;
			}else{
				$sitePlugins[$slug]['version'][$pluginData['version']] += 1;
			}
	}

	}
	unset($tempSitePlugins);
	$anonymousData['sitePlugins']	= $sitePlugins;
	//To get installed themes
	$siteThemes = array();
	$tempSiteThemes	= panelRequestManager::getRecentThemesStatus();
	foreach ($tempSiteThemes as $siteID => $siteThemeData) {
		if(isset($siteThemeData['inactive'])){
			foreach ($siteThemeData['inactive'] as $themeData) {
				$siteThemes[$themeData['path']] = array('name'=>$themeData['name'],'version'=>array(),'stylesheet'=>$themeData['stylesheet'],'isActive'=>0,'isInstalled'=>0);
			}
		}
		if(isset($siteThemeData['active'])){
			$siteThemes[$siteThemeData['active'][0]['path']] = array('name'=>$siteThemeData['active'][0]['name'],'version'=>array(),'stylesheet'=>$siteThemeData['active'][0]['stylesheet'],'isActive'=>0,'isInstalled'=>0);
		}

		}

	foreach ($tempSiteThemes as $siteID => $siteThemeData) {
		if(isset($siteThemeData['inactive'])){
			foreach ($siteThemeData['inactive'] as $themeData) {
				$siteThemes[$themeData['path']]['isInstalled'] += 1;
				if(!isset($siteThemes[$themeData['path']]['version'][$themeData['version']]))	{
					$siteThemes[$themeData['path']]['version'][$themeData['version']] = 1;
				}else{
					$siteThemes[$themeData['path']]['version'][$themeData['version']] += 1;
				}
			}
		}
		if(isset($siteThemeData['active'])){
			$siteThemes[$siteThemeData['active'][0]['path']]['isInstalled'] += 1;
			$siteThemes[$siteThemeData['active'][0]['path']]['isActive'] += 1;

			if(!isset($siteThemes[$siteThemeData['active'][0]['path']]['version'][$siteThemeData['active'][0]['version']]))	{
				$siteThemes[$siteThemeData['active'][0]['path']]['version'][$siteThemeData['active'][0]['version']] = 1;
			}else{
				$siteThemes[$siteThemeData['active'][0]['path']]['version'][$siteThemeData['active'][0]['version']] += 1;
		}
		}
	}
	unset($tempSiteThemes);
	$anonymousData['siteThemes']	= $siteThemes;
	
	$anonymousData['server']['PHP_VERSION'] 	= phpversion();
	$anonymousData['server']['PHP_CURL_VERSION']= curl_version();
	$anonymousData['server']['MYSQL_VERSION'] 	= DB::getField("select version() as V");
	$anonymousData['server']['OS'] =  php_uname('s');
	$anonymousData['server']['OSVersion'] =  php_uname('v');
	$anonymousData['server']['Machine'] =  php_uname('m');


	$anonymousData['server']['webServerSoftware'] = $_SERVER['SERVER_SOFTWARE'];

	//To get server interface. (ex: apache, apache2filter, apache2handler, caudium, cgi, ... more)	
	$anonymousData['server']['PHP_SAPI'] = php_sapi_name(); 
	
	
	$anonymousData['server']['PHPDisabledFunctions'] = explode(',', ini_get('disable_functions'));	
	array_walk($anonymousData['server']['PHPDisabledFunctions'], 'trimValue');
	
	$anonymousData['server']['PHPDisabledClasses'] = explode(',', ini_get('disable_classes'));	
	array_walk($anonymousData['server']['PHPDisabledClasses'], 'trimValue');
	
	$anonymousData['browser'] = $_SERVER['HTTP_USER_AGENT'];
	
	$requestData = array('anonymousData' => serialize($anonymousData), 'appInstallHash' => APP_INSTALL_HASH, 'appVersion' => APP_VERSION);
	list($result) = doCall(getOption('serviceURL').'anonymous.php', $requestData, $timeout=30);
	
	$result = getServiceResponseToArray($result);
	
	if($result['status'] == 'true'){
		return true;	
	}
	return false;
	
}

function getAnonymousDBInfo(){

	$tables = DB::getArray("SHOW TABLE STATUS");
 	foreach ($tables as $table) {
		if(strpos($table['Name'], Reg::get('config.SQL_TABLE_NAME_PREFIX')) === false ) { continue;} //get only iwp related tables
		$table['Name'] = str_replace(Reg::get('config.SQL_TABLE_NAME_PREFIX'),'',$table['Name']);  //removing perfix from table name
		$DBInfo['tablesInfo'][$table['Name']] =  $table;
 	}
	$status = DB::getExists("SHOW TABLE STATUS FROM information_schema");
	if ($status) {
		$DBInfo['DBAccess'] = array('information_schema' => array('access' => 'yes'));
	} else {
		$DBInfo['DBAccess'] = array('information_schema' => array('access' => 'no'));
	}
	return $DBInfo;
}
function getReportIssueData($actionID, $reportType='historyIssue'){
	
	$reportIssue = array();
	
	//collecting data about the action
	
	$addons = DB::getFields("?:addons", "slug", "1", 'slug');
	
	if(!empty($addons)){
		foreach($addons as $slug => $v){
			$addons[$slug] = getAddonVersion($slug);
		}
	}	
	
	$reportIssue['addonsBought'] = $addons;
	
	if(!empty($actionID) && $reportType='historyIssue'){
		$where = array(
			      		'query' =>  "H.actionID =':actionID'",
			      		'params' => array(
			               ':actionID'=>$actionID
           				)
        			);
		$reportIssue['history'] = DB::getArray("?:history H", "*", $where);		
		$siteIDs = DB::getFields("?:history H", "H.siteID, H.actionID", $where);					
		if(empty($reportIssue['history'])){
			return false;
		}
		
		foreach($reportIssue['history'] as $key => $data){
			
			if(($data['type'] == 'backup' && $data['action'] == 'multiCallNow') || ($data['type'] == 'scheduleBackup' && $data['action'] == 'multiCallRunTask')){
				$where = array(
			      		'query' =>  "parentHistoryID =':parentHistoryID' GROUP BY status",
			      		'params' => array(
			               ':parentHistoryID'=>$data['historyID']
           				)
        			);
				$reportIssue['backupTriggerHistoryStatusCount'][$data['historyID']] = DB::getFields("?:history", "count(status) as statusCount, status", $where, "status");
				$reportIssue['backupTriggerHistoryStatusCount'][$data['historyID']]['total'] = array_sum($reportIssue['backupTriggerHistoryStatusCount'][$data['historyID']]);
				$where = array(
			      		'query' =>  "parentHistoryID =':parentHistoryID' ORDER BY historyID DESC LIMIT 6",
			      		'params' => array(
			               ':parentHistoryID'=>$data['historyID']
           				)
        			);
				$reportIssue['backupTriggerHistory'][$data['historyID']]= DB::getArray("?:history", "*", $where);	//edited for report issue multi tasks			
								
				if(!empty($reportIssue['backupTriggerHistory'])){
					foreach($reportIssue['backupTriggerHistory'] as $keys => $value){
						$where = array(
				      		'query' =>  "historyID = ':historyID'",
				      		'params' => array(
				               ':historyID'=>$value[0]['historyID']
	           				)
        				);
						$reportIssue['backupTriggerHistoryAdditional'][$data['historyID']][] = DB::getArray("?:history_additional_data", "*", $where); //edited for report issue multi tasks	
						$reportIssue['backupTriggerHistoryRaw'][$data['historyID']][] = DB::getArray("?:history_raw_details", "*", $where); //edited for report issue multi tasks	
					}
				}
			}
		}
		$where = array(
			      		'query' =>  "H.actionID = ':actionID' AND HAD.historyID = H.historyID",
			      		'params' => array(
			               ':actionID'=>$actionID,
           				)
        			);		
		$reportIssue['historyAdditional'] = DB::getArray("?:history_additional_data HAD, ?:history H", "HAD.*", $where);
                $where = array(
			      		'query' =>  "H.actionID = ':actionID' AND HRD.historyID = H.historyID",
			      		'params' => array(
			               ':actionID'=>$actionID,
           				)
        			);	
		$reportIssue['historyRaw']        = DB::getArray("?:history_raw_details HRD, ?:history H", "HRD.*", $where);	
		$reportIssue['siteDetails'] 	  = DB::getArray("?:sites", "siteID, URL, WPVersion, pluginVersion, network, parent, IP, siteTechinicalInfo", "siteID IN (".implode(',',DB::esc($siteIDs)).")", "siteID");	
	}
	
	$reportIssue['settings'] = DB::getRow("?:settings", "general", "1");
	$reportIssue['settings']['general'] = unserialize($reportIssue['settings']['general']);
	
	$reportIssue['fsockSameURLConnectCheck'] = fsockSameURLConnectCheck(APP_FULL_URL.'execute.php');
	//$siteID = DB::getArray("?:");
		
	$reportIssue['server']['PHP_VERSION'] 	= phpversion();
	$reportIssue['server']['PHP_CURL_VERSION']= curl_version();
	$reportIssue['server']['PHP_WITH_OPEN_SSL'] = function_exists('openssl_verify');
	$reportIssue['server']['PHP_MAX_EXECUTION_TIME'] =  ini_get('max_execution_time');
	$reportIssue['server']['MYSQL_VERSION'] 	= DB::getField("select version() as V");
	$reportIssue['server']['OS'] =  php_uname('s');
	$reportIssue['server']['OSVersion'] =  php_uname('v');
	$reportIssue['server']['Machine'] =  php_uname('m');
	
	$reportIssue['server']['PHPDisabledFunctions'] = explode(',', ini_get('disable_functions'));	
	array_walk($reportIssue['server']['PHPDisabledFunctions'], 'trimValue');
	
	$reportIssue['server']['PHPDisabledClasses'] = explode(',', ini_get('disable_classes'));	
	array_walk($reportIssue['server']['PHPDisabledClasses'], 'trimValue');
	
	$reportIssue['browser'] = $_SERVER['HTTP_USER_AGENT'];
	$reportIssue['reportTime'] = time();


	removeSecureContentFromReportIssue($reportIssue['backupTriggerHistoryRaw'] , true);
	removeSecureContentFromReportIssue($reportIssue['historyRaw'] , false );
		

	
	//to find hostType
	$reportIssue['hostType'] = 'unknown';
	
	if(!empty($_SERVER['SERVER_ADDR'])){
		$SERVER_ADDR = $_SERVER['SERVER_ADDR'];
	}
	else{
		$SERVER_ADDR = gethostbyname($_SERVER['HTTP_HOST']);
	}
	
	$reportIssue['serverIP'] = $SERVER_ADDR;
	
	if(!empty($SERVER_ADDR)){
		if(IPInRange($SERVER_ADDR, '127.0.0.0-127.255.255.255')){
			$reportIssue['hostType'] = 'local';
		}
		elseif(IPInRange($SERVER_ADDR, '10.0.0.0-10.255.255.255') || IPInRange($SERVER_ADDR, '172.16.0.0-172.31.255.255') || IPInRange($SERVER_ADDR, '192.168.0.0-192.168.255.255')){
			$reportIssue['hostType'] = 'private';
		}
		else{
			$reportIssue['hostType'] = 'public';
		}
	}
	//to find hostType - Ends
	
	if(!empty($actionID) && $reportType='historyIssue'){
		$reportIssueTemp = array();
		$reportIssueTemp[$actionID] = $reportIssue;
        updateOption('reportIssueTemp',  serialize($reportIssueTemp));
	}	
	
	return array('actionID' =>$actionID, 'report' => $reportIssue);
}

function removeSecureContentFromReportIssue(&$historyRaws , $isBackupTriggerHistoryRaw){
	
	if ($isBackupTriggerHistoryRaw && !empty($historyRaws) && is_array($historyRaws)) {
		foreach ($historyRaws as $key1 => $historyRaw) {
			foreach ($historyRaw as $key2 => $siteRaws) {
				foreach ($siteRaws as $key3 => $siteRaw) {
					$decodedHistoryRawRequest = unserialize(base64_decode($siteRaw['request']));
					unset($decodedHistoryRawRequest['signature'],
					$decodedHistoryRawRequest['params']['secure']);
					$historyRaws[$key1][$key2][$key3]['request'] = base64_encode(serialize($decodedHistoryRawRequest));
				}
			}
		}
	}else {
		if(!empty($historyRaws) && is_array($historyRaws)){
			foreach($historyRaws as $key => $value){
				$decodedHistoryRawRequest = unserialize(base64_decode($value['request']));
				unset($decodedHistoryRawRequest['signature'],
				$decodedHistoryRawRequest['params']['signature'],
				$decodedHistoryRawRequest['params']['secure']);
				if ($decodedHistoryRawRequest['ftpHost']) {
					unset($decodedHistoryRawRequest['ftpHost'],
					$decodedHistoryRawRequest['ftpPort'],
					$decodedHistoryRawRequest['ftpUser'],
					$decodedHistoryRawRequest['ftpPass'],
					$decodedHistoryRawRequest['ftpBase'],
					$decodedHistoryRawRequest['dbHost'],
					$decodedHistoryRawRequest['dbUser'],
					$decodedHistoryRawRequest['dbPassword'],
					$decodedHistoryRawRequest['dbName']);
				}
				$historyRaws[$key]['request'] = base64_encode(serialize($decodedHistoryRawRequest));
			}
		}
	}

}	


function sendReportIssue($params){
	if(!empty($params)){
		
		
		if($params['type'] == 'historyIssue' && !empty($params['report'])){
			$actionID = $params['actionID'];
            $reportIssueTemp = unserialize(getOption('reportIssueTemp'));
            if((!isset($reportIssueTemp[$actionID])) || (empty($reportIssueTemp[$actionID]))) {
                return false;
            }
			$params['reportBase64'] = base64_encode(serialize($reportIssueTemp[$actionID]));
			unset($params['report']);
            updateOption('reportIssueTemp','');
		}
		elseif($params['type'] == 'userIssue'){//user Issue
			$temp = getReportIssueData('', 'userIssue');
			$params['reportBase64'] = base64_encode(serialize($temp['report']));
			unset($temp);
		}
		
		$data = array('reportData' => $params);
		if(function_exists('gzcompress')){
			$data['reportDataCompressed'] = gzcompress(serialize($data['reportData']));
			unset($data['reportData']);
		}
		$data['skipJsonCommunication']=1;
		$temp = doCall(getOption('serviceURL').'report.php', $data, $timeout=60);
		list($result) = $temp;
		
		$result = getServiceResponseToArray($result);
		
		if($result['status'] == 'true'){
			return true;
		}
	}
	return false;
}

function addOption($optionName, $optionValue){
	return DB::insert("?:options", array('optionName' => $optionName, 'optionValue' => $optionValue));
}

function updateOption($optionName, $optionValue){
	$where = array(
          'query' => "optionName = ':optionName'",
          'params' => array(
               ':optionName'=>$optionName
           )
        );
	
	if(isExistOption($optionName)){
		return DB::update("?:options", array('optionName' => $optionName, 'optionValue' => $optionValue), $where);
	}
	else{
		return addOption($optionName, $optionValue);
	}
	
}

function getOption($optionName){
	$where = array(
          'query' => "optionName = ':optionName'",
          'params' => array(
               ':optionName'=>$optionName
           )
        );
	return DB::getField("?:options", "optionValue", $where);
}

function deleteOption($optionName){
	$where = array(
          'query' => "optionName = ':optionName'",
          'params' => array(
               ':optionName'=>$optionName
           )
        );
	return DB::delete("?:options", $where);
}

function isExistOption($optionName){
	$where = array(
			      		'query' =>  "optionName = ':optionName'",
			      		'params' => array(
			               ':optionName'=>$optionName
           				)
        			);
	return DB::getExists("?:options", "optionID", $where);
}

/* Manipulating "Options" */ 

function manipulateOption($optionName, $optionValue){
	$where = array(
			      		'query' =>  "optionName = ':optionName'",
			      		'params' => array(
			               ':optionName'=>$optionName
           				)
        			);
	$optionVal = DB::getField("?:options", "optionValue", $where);
	$arrayVal = unserialize($optionVal);
	
	if(is_array($arrayVal) && !empty($arrayVal))
	{
		$slug = $optionValue['slug'];
		if(!array_key_exists($slug, $arrayVal))
		{
			$arrayVal[$slug] = array();
		}
		elseif(array_key_exists($slug, $arrayVal))
		{
			$arrayEnd = end($arrayVal[$slug]);
			$optionValue['prevVer'] = $arrayEnd['newVer'];
			reset($arrayVal);
		}
		
	}
	elseif(!is_array($arrayVal) || empty($arrayVal))
	{
		$arrayVal = array();
		$slug = $optionValue['slug'];
		$arrayVal[$slug] = array();
	}
	
	array_push($arrayVal[$slug], $optionValue);
	$serVer = serialize($arrayVal);	 
	updateOption($optionName, $serVer);
}

/* Manipulating "Options" */ 

function sendAppMail($params = array(), $contentTPL = '', $options=array()){
	$TPLOptions = array('isMailFormattingReqd' => true);
	$content = TPL::get($contentTPL, $params, $TPLOptions);
	$content = explode("+-+-+-+-+-+-+-+-+-+-+-+-+-mailTemplates+-+-+-+-+-+-+-+-+-+-+-", $content);
	$subject = $content[0];
	$message = $content[1];
	$where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=>$params['userID']
           				)
        			);
	$user = DB::getRow("?:users", "email, name", $where);
	$to = $user['email'];
	$toName = $user['name'];
	$emailDetails = getFromMail($options);
	$from = $emailDetails['fromEmail'];
	$fromName = $emailDetails['fromName'];
	if(isset($options['isTest']) && !empty($options['isTest'])){
		$emailSettings = getOption("emailTempSettings");		//for sending test email use temporary value.
	}
	else{
		$emailSettings = getOption("emailSettings");
	}
	if($emailSettings){
		$emailSettings = unserialize($emailSettings);
	}
	$options['emailSettings'] = $emailSettings;
	
	return sendMail($from, $fromName, $to, $toName, $subject, $message, $options);	
	
}

function getNoReplyEmailIDByHost(){
	$URL_Info = parse_url(APP_URL);
	
	$host = preg_replace('#^www\.(.+\.)#i', '$1', $URL_Info['host']);

	if(function_exists('checkdnsrr') && checkdnsrr($host)){
		$noReplayMailID = 'noreply-iwp@' . $host;
		return $noReplayMailID;
	}
	else{
		return false;
	}
}

function getDefaultFromEmail(){
	$where = array(
			      		'query' =>  "accessLevel=':accessLevel' ORDER BY userID LIMIT ". 1,
			      		'params' => array(
			               ':accessLevel'=>'admin'
           				)
        			);
	$user = DB::getField("?:users", "email",$where);
	$noReplayMailID = getNoReplyEmailIDByHost();
	if($noReplayMailID){
		return $noReplayMailID;
	}
	else{
		return $user;
	}
	
}

function getFromMail($options=array()){	
	$emailDetails = array();
	if(isset($options['isTest']) && !empty($options['isTest'])){
		$emailSettings = getOption("emailTempSettings");		//for sending test email use temporary value.
	}
	else{
		$emailSettings = getOption("emailSettings");
	}
	$emailSettings = unserialize($emailSettings);
	$fromEmail = $emailSettings['fromEmail'];
	$fromName = $emailSettings['fromName'];
	if($fromName){
		$emailDetails['fromName'] = $fromName;
	}
	else{
		$emailDetails['fromName'] = 'InfiniteWP';
	}
	if($fromEmail){
		$emailDetails['fromEmail'] = $fromEmail;
	}
	else{
		$emailDetails['fromEmail'] = getDefaultFromEmail();
	}

	return $emailDetails;
}

/*
* Log recent 10 cron initiated time. only for system crons.
*/
function systemCronRunLog($time){
	
	$recentLogs = array();
	
	if (defined('APP_V3')) {
		$getRecentCronLog = getOption('cronRecentRunLogV3');
	}else{
		$getRecentCronLog = getOption('cronRecentRunLog');
	}
	
	if(!empty($getRecentCronLog)){
		$recentLogs = unserialize($getRecentCronLog);
	}
	
	if(count($recentLogs) >= 10){
		array_shift($recentLogs);
	}
	
	array_push($recentLogs, $time);
	if (defined('APP_V3')) {
		updateOption('cronRecentRunLogV3', serialize($recentLogs));
	}else{
		updateOption('cronRecentRunLog', serialize($recentLogs));
	}
}

function easyCronTaskRunLog($time){
	$today = date('d-m-Y',$time);
	$log = array('date' => $today , 'count' => 1,'cronLastRun'=>$time,'cronRecentRunLogs'=>array($time));
	$getRecentCronLog = getOption('taskCronRecentRunLog');
	if(empty($getRecentCronLog)){
		$getRecentCronLog = array();
	}
	if(!empty($getRecentCronLog)){
		$getRecentCronLog = unserialize($getRecentCronLog);
		$max_no_days = 10;
		if(defined('IWP_MAINTAIN_TASKCRON_LOGS') && IWP_MAINTAIN_TASKCRON_LOGS){
			if(IWP_MAINTAIN_TASKCRON_LOGS > $max_no_days ){
				$max_no_days = IWP_MAINTAIN_TASKCRON_LOGS;
			}
		}
		if(count($getRecentCronLog) >= $max_no_days){
			array_pop($getRecentCronLog);
		}
		if($getRecentCronLog[0]['date'] == $today){
			$getRecentCronLog[0]['count'] = $getRecentCronLog[0]['count'] + 1;
			$getRecentCronLog[0]['cronLastRun'] = $time;
			array_push($getRecentCronLog[0]['cronRecentRunLogs'],$time);
		}else{
			array_unshift($getRecentCronLog,$log);
		}
	}else{
		array_push($getRecentCronLog,$log);
	}
	updateOption('taskCronRecentRunLog',serialize($getRecentCronLog));
}

function cronRun(){
	
	ob_start();
	
	ignore_user_abort(true);
	set_time_limit(0);
	//$userID = DB::getField("?:users", "userID", "1 ORDER BY userID ASC LIMIT 1");
	$where = array(
			      		'query' =>  "accessLevel=':accessLevel' ORDER BY userID LIMIT 1",
			      		'params' => array(
			               ':accessLevel'=>'admin'
           				)
        			);
	$userID = DB::getField("?:users", "userID", $where);
	
	if(empty($userID)){
		return false;
	}
	$GLOBALS['userID'] = $userID;
	$GLOBALS['offline'] = true;

	$time = time();
	$previousRun = getOption('cronLastRun');
	if (($time-$previousRun) < 60) {
		return false;
	}
	updateOption('cronLastRun', $time); //sometime cron may take long time to complete, so updating first last cron run

	
	if(CRON_MODE == 'systemCronShortTime' || CRON_MODE == 'systemCronDefault'){
		systemCronRunLog($time);
	}
	if(CRON_MODE == 'easyCronTask'){
		easyCronTaskRunLog($time);
	}
	
	updatesNotificationMailRunCheck();
	
	$temp = array();
	setHook('cronRun', $temp);
	
	$settings = Reg::get('settings');
	//if($settings['executeUsingBrowser'] == 1){//this condition is commented to fix #0000221
		do{
			$status = executeJobs();
		}
		while($status['requestInitiated'] > 0 && $status['requestPending'] > 0 && ($GLOBALS['cronStartTime'] + CRON_TIMEOUT) > time());
	//}
	include_once(APP_ROOT."/includes/favicon.php");
	Favicon::getFaviconsCronJob($GLOBALS['cronStartTime']);
	
	//before ending
	if(CRON_MODE == 'easyCronTask'){
		//if no more new task(jobs) self disable task cron of easy cron
		if(!isAnyActiveOrPendingJobs()){
			$getNextTaskScheduleTime = getNextTaskScheduleTime();
			if( !(!empty($getNextTaskScheduleTime) && $getNextTaskScheduleTime < (time() + 30*60)) ){//no new task for next 30 mins
				//disable here
				$minimumScheduleTime = getMinimumScheduledTaskTime();
				if(!empty($minimumScheduleTime) && $minimumScheduleTime > 1 && manageEasyCron::isTaskCronScheduledTimeExpired()){
					/*
					After rescheduling task cron it EasyCron will trigger old previous queue on one time 
					Example if task cron timing change 1min to 5min after successful reschedule again 1min task cron will execute once 
					*/
					if(manageEasyCron::editTaskCron($minimumScheduleTime)){
						manageEasyCron::updateTaskCronRunningFrequency($minimumScheduleTime);
						$nextSchedule = time() + ($minimumScheduleTime * 60); // 5*60 = 300 (5min)
						manageEasyCron::updateTaskCronNextSchedule($nextSchedule);
					}
				}elseif($minimumScheduleTime === false){
					manageEasyCron::taskCronDisable();
				}
			}
		}else{
			// Task cron running state
			// Validate cron running frequency. if cron frequency graterthan 1 set task cron to 1
			$taskCronRunningFrequency = manageEasyCron::getTaskCronRunningFrequency();
			if(!empty($taskCronRunningFrequency) && $taskCronRunningFrequency > 1){
				$frequency = 1;
				if(manageEasyCron::editTaskCron($frequency)){
					manageEasyCron::deleteTaskCronRunningFrequency();
				}
			}
		}
	}
	if( !isAnyActiveOrPendingJobs() ){
		panelRequestManager::autoCheckAndDeleteLog(array());
	}
	ob_end_clean();

	if(CRON_MODE == 'IWP_Cron'){
		$response = array('pingBack' => true);
		$noNewTaskScheduled = !isAnyActiveOrPendingJobs();
		if($noNewTaskScheduled){
			$getNextTaskScheduleTime = getNextTaskScheduleTime();
			$minutes = 30;
			$isAtleast30MinutesAway = !timeUtils::isLessThanNowInMinutes($minutes, $getNextTaskScheduleTime);
			if($isAtleast30MinutesAway){
				$response['pingBack'] = false;
			}
		}
		header('Content-Type: application/json');
		echo json_encode($response);
	}

}


function updatesNotificationMailRunCheck($getNextScheduleTime = false){
	
	/*$settings = panelRequestManager::getSettings();
	$updatesNotificationMail = $settings['notifications']['updatesNotificationMail'];*/

	$isAtleastOneSiteAdded = DB::getExists("?:sites", "siteID", "type = 'normal' LIMIT 1");
	if(!$isAtleastOneSiteAdded){
		return false;//if no sites are there, then don't send update notification mail
	}

	$getAllNotifications = DB::getArray("?:users", "userID, accessLevel, permissions, notifications, updatesNotificationMailLastSent, status", 1, "userID");
	if(!empty($getAllNotifications))
	foreach($getAllNotifications as $userID => $userData){

		if ($userData['status'] == '0') {
			$where = array(
		      		'query' =>  "userID = ':userID'",
		      		'params' => array(
		               ':userID'=>$userID
       				)
    			);
			DB::update("?:users", array('updatesNotificationMailLastSent' => time()), $where);
			continue;
		}
		
		if(empty($userData['notifications'])){ continue; }
		if($userData['accessLevel'] == 'manager'){
			$permissions = unserialize($userData['permissions']);
			if(empty($permissions['access']) || (!empty($permissions['access']) && !in_array('updates', $permissions['access']))){
				continue;
			}
		}
		
		$updatesNotificationMail = unserialize($userData['notifications']);
		$updatesNotificationMail = $updatesNotificationMail['updatesNotificationMail'];
		//check setting
		if($updatesNotificationMail['frequency'] == 'never' || (empty($updatesNotificationMail['coreUpdates']) && empty($updatesNotificationMail['pluginUpdates']) && empty($updatesNotificationMail['themeUpdates']) && empty($updatesNotificationMail['IWPPanelUpdates'])) ){
			continue;//	updatesNotificationMail is disabled in the settings
		}
		//get updates Notification Mail Last Sent
		$updatesNotificationMailLastSent = !empty($userData['updatesNotificationMailLastSent'])?$userData['updatesNotificationMailLastSent']:0;
		
		//check last run falls within the frequency
		$customNotification = '';
		if (defined('CUSTOM_EMAIL_UPDATE_NOTIFICATION_TIME')) {
			$customNotification = CUSTOM_EMAIL_UPDATE_NOTIFICATION_TIME;
		}
		if( is_null($updatesNotificationMailLastSent) || $updatesNotificationMailLastSent > 0){
			if($updatesNotificationMail['frequency'] == 'daily'){
				if (!empty($customNotification)) {
					$frequencyStartTime = strtotime(@date("d F Y ".$customNotification,time())); // changed to send at 10:00 am localtime
				}else{
					$frequencyStartTime = strtotime(@date("d F Y 10:00:00",time())); // changed to send at 10:00 am localtime
				}
			}
			elseif($updatesNotificationMail['frequency'] == 'weekly'){//mon to sun week
				$day = @date('w', time());
				// $frequencyStartTime = mktime(0, 0, 1, @date('m'), @date('d') - ($day > 0 ? $day: 7) + 1, @date('Y'));
				if (!empty($customNotification)) {
					$frequencyStartTime = strtotime((@date('d',time()) - $day+1)." ".@date("F Y ".$customNotification,time()));	// changed to send on monday,10:00 am localtime
				}else{
					$frequencyStartTime = strtotime((@date('d',time()) - $day+1)." ".@date("F Y 10:00:00",time()));	// changed to send on monday,10:00 am localtime
				}
			}
			else{
				continue;//user not subscribed to update notification mail
			}
			if($updatesNotificationMailLastSent < $frequencyStartTime  && $frequencyStartTime <= time()){
				$sendMailUserID = $userID;
				//send mail
			}
			else{
				//stop mail 0 => '1409655692',  1 => 1409670000,  2 => 1409656008	
				continue;//already sent or time less than 10:00 according to local time
			}
		

		}
		//To get the time schedued to send the update mail Notification.
		if($getNextScheduleTime){
			if(isset($frequencyStartTime)){
				$time = $frequencyStartTime;
			}else{
				$time = time();
			}
			return $time;
		}
		 updatesNotificationMailSend($force=false,$userID = $sendMailUserID);
	
	}
	
}

function updatesNotificationMailSend($force=false,$userID = false){
	$onlyVulnsUpdate = false;
	if($force == false){
		$where = array(
			      		'query' =>  "userID = ':userID' AND status = '1'",
			      		'params' => array(
			               ':userID'=>$userID
           				)
        			);
		$getAllNotifications = DB::getArray("?:users", "userID, accessLevel, permissions, notifications, updatesNotificationMailLastSent",$where, "userID");
	}
	else{
		$where = array(
			      		'query' =>  "userID = ':userID' AND status = '1'",
			      		'params' => array(
			               ':userID'=>$GLOBALS['userID']
           				)
        			);
		$getAllNotifications = DB::getArray("?:users", "userID, accessLevel, permissions, notifications, updatesNotificationMailLastSent", $where, "userID");
	}
		
	$run = 1;
	if(!empty($getAllNotifications))
	foreach($getAllNotifications as $userID => $userData){

		if ($userData['status'] == '0') {
			$where = array(
		      		'query' =>  "userID = ':userID'",
		      		'params' => array(
		               ':userID'=>$userID
       				)
    			);
			DB::update("?:users", array('updatesNotificationMailLastSent' => time()), $where);
			continue;
		}
		
		if(empty($userData['notifications'])){
			continue;
		}

		if($userData['accessLevel'] == 'manager'){
			$permissions = unserialize($userData['permissions']);
			if(empty($permissions['access']) || (!empty($permissions['access']) && !in_array('updates', $permissions['access']))){
				continue;
			}
			
		}
		$UID = $userID;
		
		$updatesNotificationMail = unserialize($userData['notifications']);
        $updatesNotificationMail = $updatesNotificationMail['updatesNotificationMail'];
		//check setting
		if($force == false){
			if($updatesNotificationMail['frequency'] == 'never' || (empty($updatesNotificationMail['coreUpdates']) && empty($updatesNotificationMail['pluginUpdates']) && empty($updatesNotificationMail['themeUpdates'])) ){
				continue; //updatesNotificationMail is disabled in the settings
			}
		}
		if($force == false && $run == 1){ //for test mail(i.e $force == true) dont need to get new data
			
			Reg::set('currentRequest.actionID', uniqid('', true));
			$lastNHours = time() - (60*60*2);//2 hours

			$getRemainingSiteIDsQuery = "SELECT S.siteID FROM ?:sites S LEFT OUTER JOIN ?:history H on S.siteID = H.siteID and H.type = 'stats' and H.action = 'getStats' and H.microtimeInitiated >= ".DB::esc($lastNHours)." and H.status IN('completed', 'error', 'netError') where H.siteID is null";
			$remainingSiteIDs = DB::getFields($getRemainingSiteIDsQuery);//Assuming for all the sites reload data can happen in 2 hours.

			if(!empty($remainingSiteIDs) && is_array($remainingSiteIDs)){
				foreach($remainingSiteIDs as $siteID) {
					$where = array(
			      		'query' =>  "H.siteID = :siteID AND H.type = ':type' AND H.action = ':action'and H.microtimeInitiated >= ':microtimeInitiated' AND showUser = 'N'",
			      		'params' => array(
			               ':siteID'=>$siteID,
			               ':type'=>'stats',
			               ':action'=>'getStats',
			               ':microtimeInitiated'=>$lastNHours
           				)
        			);
					$isAlreadyAdded = DB::getExists("?:history H", "H.historyID", $where);
					if($isAlreadyAdded){
						continue;//no need to trigger new one, has one is already in place.
					}
					
					$extras = array('directExecute' => true, 'sendAfterAllLoad' => false, 'doNotShowUser' => true);//'directExecute' => true reload data calls will be executed directly blocking mode
					manageClientsFetch::getStatsProcessor(array($siteID), array(), $extras);
					$run = 0;	

					if(($GLOBALS['cronStartTime'] + CRON_TIMEOUT) < time()){ break;}
				}
			}

			$remainingSiteIDs = DB::getFields($getRemainingSiteIDsQuery);
			if(!empty($remainingSiteIDs)){ return false; }//If all sites reload data not completed as per above criteria, then go out of this function. In the next cron call it will continue from where it left. As the above while function this case will come from CRON_TIMEOUT meets.
		}



		//getting updateInformation
		$sitesUpdates = panelRequestManager::getSitesUpdates($UID, false);
		$hiddenUpdates = panelRequestManager::getHide();
		$panelUpdates = array();
		$changeLogLink = 'http://infinitewp.com/change-log';
		if(!empty($updatesNotificationMail['IWPPanelUpdates'])){
			if (defined('APP_V3')) {
				$V2UpdateDetails = getCachedUpdateDetails();
			}else{
				$V2UpdateDetails = checkUpdate();
			}
			if(!empty($V2UpdateDetails) && !empty($V2UpdateDetails['newVersion'])){
				 $changeLogLink = $V2UpdateDetails['updateDetails'][$V2UpdateDetails['newVersion']]['changeLogLink'];
				 $v2PanelData = array('new_version'=>$V2UpdateDetails['newVersion'],'change_log_link'=>$changeLogLink);
				$panelUpdates['V2'] = $v2PanelData;
			}
			if (defined('APP_V3')) {
				$V2UpdateDetails = checkUpdateV3();
			}else{
				$V2UpdateDetails = fetchV3UpdateDetails();
			}
			$V3UpdateDetails = fetchV3UpdateDetails();

			if(!empty($V3UpdateDetails) && !empty($V3UpdateDetails['newVersion'])){
				 $changeLogLink = $V3UpdateDetails['updateDetails'][$V3UpdateDetails['newVersion']]['changeLogLink'];
				 $v3PanelData = array('new_version'=>$V3UpdateDetails['newVersion'],'change_log_link'=>$changeLogLink);
				$panelUpdates['V3'] = $v3PanelData;
			}
		}
		
		foreach($hiddenUpdates as $siteID => $value){
			foreach($value as $d){
				unset($sitesUpdates['siteView'][$siteID][$d['type']][$d['URL']]);
				
				//this will fix the site name shows even all update items are hidden
				if(empty($sitesUpdates['siteView'][$siteID][$d['type']])){
					unset($sitesUpdates['siteView'][$siteID][$d['type']]);
				}
				if(empty($sitesUpdates['siteView'][$siteID])){
					unset($sitesUpdates['siteView'][$siteID]);
				}
			}
		}
		if(!empty($sitesUpdates['siteView']) && ( empty($updatesNotificationMail['coreUpdates']) ||  empty($updatesNotificationMail['pluginUpdates']) || empty($updatesNotificationMail['themeUpdates']) || empty($updatesNotificationMail['translationUpdates']) )){//this will fix  when the "plugin" not selected in settings. Site name shows with empty list when plugin update is available
			foreach($sitesUpdates['siteView'] as $siteID => $value){
				if(empty($updatesNotificationMail['coreUpdates'])){
					unset($sitesUpdates['siteView'][$siteID]['core']);
				}
				if(empty($updatesNotificationMail['pluginUpdates'])){
					unset($sitesUpdates['siteView'][$siteID]['plugins']);				
				}
				if(empty($updatesNotificationMail['themeUpdates'])){
					unset($sitesUpdates['siteView'][$siteID]['themes']);
				}
				if(empty($updatesNotificationMail['translationUpdates'])){
					unset($sitesUpdates['siteView'][$siteID]['translations']);
				}
				if(empty($sitesUpdates['siteView'][$siteID])){
					unset($sitesUpdates['siteView'][$siteID]);
				}
			}
		}
		if (!empty($updatesNotificationMail['WPVulnsUpdates'])) {
			if (empty($sitesUpdates['siteView'])) {
				$onlyVulnsUpdate = true;
			}
			setHook('updateNotificationViews', $sitesUpdates, $UID);
		}
		$params = array('userID' => $userID, 'sitesUpdates' => $sitesUpdates,  'updatesNotificationMail' => $updatesNotificationMail, 'updateNotificationDynamicContent' => getOption('updateNotificationDynamicContent'), 'onlyVulnsUpdate' => $onlyVulnsUpdate,'panelUpdates'=>$panelUpdates);
		$isSent = sendAppMail($params, '/templates/email/updatesNotification.tpl.php');
		$where = array(
		      		'query' =>  "userID = ':userID'",
		      		'params' => array(
		               ':userID'=>$userID
       				)
    			);
		if($isSent){
			if(!$force){
				DB::update("?:users", array('updatesNotificationMailLastSent' => time()), $where);
			}else{
				addNotification($type='N', $title='Test Update Mail', $message='E-Mail Sent Successfully.', $state='U', $callbackOnClose='', $callbackReference='');
			}
		}
		else{
			if(!$force){
				DB::update("?:users", array('updatesNotificationMailLastSent' => time()),$where);//even mail sending failed mark as sent this will avoid re-trying, customer will be notified if mail not sent using offline notification
			}
		}
	}
	return true;
}


function cronReloadCompCheck($statsInitiateTime){
		
	$limit = DB::getField("?:sites", "count(*)", 1);
	$where = array(
			      		'query' =>  "HAD.historyID = :historyID AND H.action = ':action' AND H.type = ':type' ORDER BY H.historyID DESC LIMIT ".DB::esc($limit),
			      		'params' => array(
			               ':historyID'=>'H.historyID',
			               ':action'=>'getStats',
			               ':type'=>'stats'
           				)
        			);
	$siteIds = DB::getArray("?:sites S LEFT JOIN ?:site_stats SS ON S.siteID = SS.siteID LEFT JOIN ?:history H ON S.siteID = H.siteID, ?:history_additional_data HAD", "HAD.errorMsg, S.siteID, SS.lastUpdatedTime, H.status", $where);
	
	$statsVal = array();
	$statsVal['statsInitiateTime'] = $statsInitiateTime;
	
	foreach($siteIds as $key => $value){
		if($value['lastUpdatedTime'] > $statsInitiateTime && $value['lastUpdatedTime'] < $statsInitiateTime+60*60 && $value['status'] == 'completed'){
			$statsVal['completed'][] = $value;
		}
		elseif($value['status'] == 'netError' || $value['status'] == 'error' || ($value['status'] == 'completed' && !empty($value['errorMsg']))){
			$statsVal['ignore'][] = $value;
		}
		else{
			$statsVal['retry'][] = $value;
		}
	}
	
	updateOption("cronReloadCompCheck", serialize($statsVal));
	return $statsVal;
}

function getAllSitesStatsWithError(){
	//reloading stats from all the sites
	
	//option 1 - While doing cron - latest
	$statsInitiateTime = time(); $siteIDs = '';
	
	//option 1 - While doing cron - latest
	$proceed = cronReloadCompCheck($statsInitiateTime);
	if(!empty($proceed) && isset($proceed['retry']) && !empty($proceed['retry'])){
		return false;
	}
}

function getCachedUpdateDetails(){
	$updateAvailable = getOption('updateAvailable');
	if(!empty($updateAvailable)){
		$updateAvailable = @unserialize($updateAvailable);
		if($updateAvailable == 'noUpdate'){
			return false;
		}
		return $updateAvailable;
	}
	return false;
}

function checkUpdate($force=false, $checkForUpdate=true){
	if (defined('APP_V3')) {
		return false;
	}
	$currentTime = time();
	$updateLastChecked = getOption('updateLastCheck');
	if(!$force){
		$updateCheckInterval = 86400;//86400 => 1 day in seconds
	
		if(stripos(APP_VERSION, 'beta') !== false) $updateCheckInterval = (60 * 60 * 4);//60 * 60 * 4 every 4 hrs. betaClientPlugin update notification comes via checkUpdate

		if( ($currentTime - $updateLastChecked) < $updateCheckInterval ){
			return getCachedUpdateDetails();
		}
	}
	
	if(!$checkForUpdate){
		return false;
	}
	
	$updateLastTried = getOption('updateLastTry');
	if(!$force && $updateLastTried > 0 && $updateLastChecked > 0 && ($currentTime - $updateLastTried) < 600){//auto checkUpdate after 600 secs
		return false;
	}
	if(!$force && $updateLastTried > 0 && ($currentTime - $updateLastTried) <= 10){//no new checkUpdate within 10 secs of last try
		return getCachedUpdateDetails();
	}
	updateOption('updateLastTry', $currentTime);

	$URL = getOption('serviceURL').'checkUpdate.php';
	$URL .= '?appVersion='.APP_VERSION.'&appInstallHash='.APP_INSTALL_HASH.'&installedHash='.getInstalledHash();
	
	$installedEmail = getOption('installedEmail');
	if(!empty($installedEmail)){
		$URL .= '&installedEmail='.urlencode($installedEmail);
	}
	
	$partnerHost = getOption('partnerHost');
	if(!empty($partnerHost)){
		$URL .= '&partnerHost='.urlencode($partnerHost);
	}
	
	//$installedAddons = getInstalledAddons();
	$addonDetails = Reg::get('addonDetails');
	if(!empty($addonDetails)){
		foreach($addonDetails as $addonSlug => $addon){
			$URL .=  '&checkAddonsUpdate['.$addonSlug.']='.$addon['version'];		
		}
	}
	$currentGeneralSettings = Reg::get('settings');
	if($currentGeneralSettings['participateBeta'] == 1){
		$URL .= '&participateBeta=1';
	}	
	if($force){
		$URL .= '&force=1';
	}
    if(defined('DEV_UPDATE')) {
		$URL .= '&devUpdate='.DEV_UPDATE;
    }
    if(defined('IWP_TRIAL_PANEL')) {
		$URL .= '&trailPanel='.IWP_TRIAL_PANEL;
    }
    $installedTime = getOption('installedTime');
    if(!empty($installedTime)) {
		$URL .= '&installedTime='.$installedTime;
    }
    $isV3Installed = getOption('V3Installed');
    if (!empty($isV3Installed)) {
    	$URL .='&V3Installed=1';
    }
	
	$suiteDetails = unserialize(getOption('suiteDetails'));
	if(empty($suiteDetails) and !is_array($suiteDetails)) {
		$cancelMessageFlag='';
		$addonSuiteMiniActivity='';
	} else {
		$cancelMessageFlag=$suiteDetails['cancelMessageFlag'];
		$addonSuiteMiniActivity=(isset($suiteDetails['addonSuiteMiniActivity']) && $suiteDetails['addonSuiteMiniActivity']!='')?$suiteDetails['addonSuiteMiniActivity']:'';
	}
	$URL .= '&cancelMessageFlag='.$cancelMessageFlag.'&addonSuiteMiniActivity='.$addonSuiteMiniActivity;
	
	$temp = doCall($URL, '', $timeout=30);
	list($result, , , $curlInfo) = $temp;
	$result = getServiceResponseToArray($result);//from 2.0.8 follows <IWPHEADER><IWPHEADEREND> wrap in return value	
	$curlErrors = new curlErrors($curlInfo);
	if(!$curlErrors->isOk()){
		return $curlErrors->getErrorDetails();
	}
	
	if(empty($result)){
		//response error
		return false;
	}
	setHook('updateCheck', $result);
	if (!empty($result['addonsHTML'])) {
		updateOption('addonsHTML', $result['addonsHTML']);
	}
	if (!empty($result['illegalHTML'])) {
		updateOption('addonsIllegalHTML', $result['illegalHTML']);
	}
	if (!empty($result['limitAddSiteHTML'])) {
		updateOption('addSiteHTML', $result['limitAddSiteHTML']);
	}
	if (!empty($result['pricePlanDetails'])) {
		updateOption('pricingPlanTypes', serialize($result['pricePlanDetails']));
	}
	if (!empty($result['notifyV3Update'])) {
		updateOption('notifyV3Update', 1);
	}
	if(!empty($result['updateNotificationDynamicContent'])){
		updateOption('updateNotificationDynamicContent', $result['updateNotificationDynamicContent']);
	}
	if (!empty($result['supportDocs'])) {
		updateOption("supportDocs", $result['supportDocs']);
		updateOption("isShowSupportDocs", $result['isShowSupportDocs']);
		updateOption("isShowSupportSearch", $result['isShowSupportSearch']);
	}
	updateOption('updateLastCheck', $currentTime);
	if (!empty($result['multicallRetryErrorCode'])) {
		updateOption('multicallRetryErrorCode', $result['multicallRetryErrorCode']);
	}
	if(!empty($result['commonRetryErrorCode'])){
		updateOption('commonRetryErrorCode', $result['commonRetryErrorCode']);
	}
	if(isset($result['registerd'])){
		updateAppRegistered($result['registerd']);
	}
	
	if(isset($result['addons'])){
		processCheckAddonsUpdate($result['addons']);
	}
	
	if(isset($result['promos'])){
		updateOption('promos', serialize($result['promos']));
	}
	
	if(isset($result['clientPluginBetaUpdate'])){
		updateOption('clientPluginBetaUpdate', serialize($result['clientPluginBetaUpdate']));
	}
        if(isset($result['checkClientUpdate'])){
		updateOption('clientPluginUpdate', serialize($result['checkClientUpdate']));
	}

	if(isset($result['iwpCronInvited'])){
            $isInvitedEarlier = getOption('iwpCronInvited');
            if(!$isInvitedEarlier){
                updateOption('iwpCrontInvitedNotificationReq', true);
            }
            $iwpCronInvited = $result['iwpCronInvited'];
            updateOption('iwpCronInvited', $iwpCronInvited);
	}

	if(isset($result['mark'])){ //codeSprint
		dispatchMark($result['mark']);
	}
	if(empty($result['checkUpdateV3']) || $result['checkUpdateV3'] == 'noUpdate'){
		updateOption('updateAvailableV3', '');
	}
	else{
		updateOption('updateAvailableV3', serialize($result['checkUpdateV3']));
	}
	if (!empty($result['servicePopupNotification'])) {
		processServicePopupNotification($result['servicePopupNotification']);
	}
	
	if (!empty($result['truncateServicePopup'])) {
		DB::doQuery('TRUNCATE TABLE ?:popup_notification');
	}

	if($result['checkUpdate'] == 'noUpdate'){
		updateOption('updateAvailable', '');
		return false;
	}
	else{
		updateOption('updateAvailable', serialize($result['checkUpdate']));
		return $result['checkUpdate'];
	}

	
}

function processAppUpdate(){//download and install update
	$updateAvailable = checkUpdate(false, false);
	if(empty($updateAvailable)){
		return false;	
	}
	
	$newVersion = $updateAvailable['newVersion'];
	
	$optionVer['action'] = 'updated';
	$optionVer['actionTime'] = time();
	$optionVer['prevVer'] = APP_VERSION;
	$optionVer['newVer'] = $newVersion;
	$optionVer['slug'] = 'IWPAdminPanel';
	
	if(version_compare(APP_VERSION, $newVersion) !== -1){
		return false;
	}
	
	$updateDetails = $updateAvailable['updateDetails'][$newVersion];
	
	if(!empty($updateDetails['downloadLink']) && !empty($updateDetails['fileMD5'])){
		
		$updateZip = getTempName('appUpdate.zip');
	
		appUpdateMsg('Downloading package..');
		
		$isDone = downloadURL($updateDetails['downloadLink'], $updateZip);		
		
		if(!$isDone){ //download failed
			appUpdateMsg('Download Failed.', true);
			appUpdateMsg("Install this constant in IWP config.php file and try again <br> define('PANEL_UPDATE_SSL_VERIFY', true);", true);
			return false;
		}
				
		if(md5_file($updateZip) != $updateDetails['fileMD5']){
			appUpdateMsg('File MD5 mismatch(damaged package).', true);
			return false;	
		}
		
		if(!initFileSystem()){
			appUpdateMsg('Unable to initiate file system.', true);
			return false;
		}
		
		$unPackResult = unPackToWorkingDir($updateZip);
		if(!empty($unPackResult) && is_array($unPackResult)){
			$source = $unPackResult['source'];
			$remoteSource = $unPackResult['remoteSource'];
		}
		else{
			return false;	
		}
		
		$destination = APP_ROOT;
		if(!copyToRequiredDir($source, $remoteSource, $destination)){
			return false;	
		}
		
		appUpdateMsg('Finalizing update..');	
		if(file_exists(APP_ROOT.'/updateFinalize_v'.$newVersion.'.php')){
			//$updateAvailable variable should be live inside the following file
			include(APP_ROOT.'/updateFinalize_v'.$newVersion.'.php');//run the update file
			
			if($GLOBALS['updateFinalizeStatus'] === true || $updateFinalizeStatus === true){
				
				if(file_exists($updateZip)){ // because file already deleted in unPackToWorkingDir
					@unlink($updateZip);
				}
				updateOption('updateAvailable', '');
				
				appUpdateMsg('Updated successfully.', false);
				manipulateOption('versionLogs', $optionVer);
				updateOption('lastPanelUpdated', time());
				return true;
			}
			else{
				appUpdateMsg('Update failed.', true);
			}
		}
		else{
			//updateFinalize file not found	
			appUpdateMsg('Update finalizing file missing.', true);
		}
		@unlink($updateZip);
		return false;	
	}	
	
	
}

function processAppUpdateV3(){//download and install update
	$updateAvailable = getCachedV3UpdateDetails(false, false);
	if(empty($updateAvailable)){
		return false;	
	}
	
	$newVersion = $updateAvailable['newVersion'];
	
	$optionVer['action'] = 'updated';
	$optionVer['actionTime'] = time();
	$optionVer['prevVer'] = APP_VERSION;
	$optionVer['newVer'] = $newVersion;
	$optionVer['slug'] = 'IWPAdminPanel';
	
	if(version_compare(APP_VERSION, $newVersion) !== -1){
		return false;
	}
	
	$updateDetails = $updateAvailable['updateDetails'][$newVersion];
	
	if(!empty($updateDetails['downloadLink']) && !empty($updateDetails['fileMD5'])){
		
		$updateZip = getTempName('appUpdate.zip');
	
		appUpdateMsg('Downloading package..');
		
		$isDone = downloadURL($updateDetails['downloadLink'], $updateZip);		
		
		if(!$isDone){ //download failed
			appUpdateMsg('Download Failed.', true);
			appUpdateMsg("Install this constant in IWP config.php file and try again <br> define('PANEL_UPDATE_SSL_VERIFY', true);", true);
			return false;
		}
				
		if(md5_file($updateZip) != $updateDetails['fileMD5']){
			appUpdateMsg('File MD5 mismatch(damaged package).', true);
			return false;	
		}
		
		if(!initFileSystem()){
			appUpdateMsg('Unable to initiate file system.', true);
			return false;
		}
		
		$unPackResult = unPackToWorkingDir($updateZip);
		if(!empty($unPackResult) && is_array($unPackResult)){
			$source = $unPackResult['source'];
			$remoteSource = $unPackResult['remoteSource'];
		}
		else{
			return false;	
		}
		
		$destination = APP_ROOT;
		if(!copyToRequiredDir($source, $remoteSource, $destination)){
			return false;	
		}
		
		appUpdateMsg('Finalizing update..');	
		if(file_exists(APP_ROOT.'/updateFinalize_v'.$newVersion.'.php')){
			//$updateAvailable variable should be live inside the following file
			include(APP_ROOT.'/updateFinalize_v'.$newVersion.'.php');//run the update file
			
			if($GLOBALS['updateFinalizeStatus'] === true || $updateFinalizeStatus === true){
				
				if(file_exists($updateZip)){ // because file already deleted in unPackToWorkingDir
					@unlink($updateZip);
				}
				updateOption('updateAvailable', '');
				
				appUpdateMsg('Updated successfully.', false);
				manipulateOption('versionLogs', $optionVer);
				return true;
			}
			else{
				appUpdateMsg('Update failed.', true);
			}
		}
		else{
			//updateFinalize file not found	
			appUpdateMsg('Update finalizing file missing.', true);
		}
		@unlink($updateZip);
		return false;	
	}	
	
	
}

function unPackToWorkingDir($updateZip){
	
	if(empty($updateZip)) return false;
	
	$workingDir = APP_ROOT.'/updates';
	
	$updatesFolder = $GLOBALS['FileSystemObj']->findFolder($workingDir);
		
	//Clean up contents of upgrade directory beforehand.
	$updatesFolderFiles = $GLOBALS['FileSystemObj']->dirList($updatesFolder);
	if ( !empty($updatesFolderFiles) ) {
		$temp = basename($updateZip);
		foreach ( $updatesFolderFiles as $file ){
			if($temp != $file['name'])
			$GLOBALS['FileSystemObj']->delete($updatesFolder . $file['name'], true);
		}
	}

	//We need a working directory
	//removing the extention
	$updateZipParts = explode('.', basename($updateZip));
	if(count($updateZipParts) > 1) array_pop($updateZipParts);
	$tempFolderName = implode('.', $updateZipParts);
	if(empty($tempFolderName)) return false;
	
	$remoteWorkingDir = $updatesFolder . $tempFolderName;
	$workingDir = addTrailingSlash($workingDir). $tempFolderName;

	// Clean up working directory
	if ( $GLOBALS['FileSystemObj']->isDir($remoteWorkingDir) )
		$GLOBALS['FileSystemObj']->delete($remoteWorkingDir, true);

	// Unzip package to working directory
	$result = $GLOBALS['FileSystemObj']->unZipFile($updateZip, $remoteWorkingDir); //TODO optimizations, Copy when Move/Rename would suffice?

	// Once extracted, delete the package.
	@unlink($updateZip);
	
	if ( $result == false ) {
		$GLOBALS['FileSystemObj']->delete($remoteWorkingDir, true);
		return false;
	}
	
	return array('source' => $workingDir, 'remoteSource' => $remoteWorkingDir);
}

function copyToRequiredDir($source, $remoteSource, $destination){
	
	$remoteSourceFiles = array_keys( $GLOBALS['FileSystemObj']->dirList($remoteSource) );
	if(empty($remoteSourceFiles)){
		appUpdateMsg('Unable to retrieve the directory list('.$remoteSource.').'.(($GLOBALS['FileSystemObj']->getMethod() == 'FTPExt') ? ' Please check APP_FTP_BASE folder path in config.php. It should point to the IWP root folder.' : ''), true);
		return false;
	}
	
	
	@set_time_limit( 300 );
	//$destination = APP_ROOT;
	$remoteDestination = $GLOBALS['FileSystemObj']->findFolder($destination);

	//Create destination if needed
	if ( !$GLOBALS['FileSystemObj']->exists($remoteDestination) )
		if ( !$GLOBALS['FileSystemObj']->mkDir($remoteDestination, FS_CHMOD_DIR) ){
			//return new WP_Error('mkdir_failed', $this->strings['mkdir_failed'], $remoteDestination);
			appUpdateMsg('Unable to create directory '.$remoteDestination, true);
			return false;
		}

	// Copy new version of item into place.
	$result = $GLOBALS['FileSystemObj']->copyDir($remoteSource, $remoteDestination);
	if ( !$result ) {
		$GLOBALS['FileSystemObj']->delete($remoteSource, true);
		return $result;
	}

	//Clear the Working folder?
	$GLOBALS['FileSystemObj']->delete($remoteSource, true);	
	
	return true;
}

function appUpdateMsg($msg, $isError=0){
	if (isV3Panel()) {
		$GLOBALS['updateMsg'] = $msg;
		return;
	}
	if (defined('FILE_TREE_EXIT')) {
		die($msg);
	}
	echo '<br>'.$msg;
	if($isError === true){
		?>
        <br />Try again by refreshing the panel or contact <a href="mailto:help@infinitewp.com">help@infinitewp.com</a>
         <script>
		window.parent.$("#updates_centre_cont .btn_loadingDiv").remove();
		</script>
		<?php
	}
	elseif($isError === false){
		?>
        <script>
		window.parent.$("#updates_centre_cont .btn_loadingDiv").remove();
		window.parent.$(".updateActionBtn").attr({'btnaction':'reload','target':'_parent', 'href':'<?php echo APP_URL; ?>'}).text('Reload App').removeClass('disabled');
		window.parent.$("#updates_centre_cont_V3 .btn_loadingDiv").remove();
		window.parent.$(".updateActionBtnV3").attr({'btnaction':'reload','target':'_parent', 'href':'<?php echo trim(APP_URL, "/")."/v3"; ?>'}).text('Reload App').removeClass('disabled');
		</script>
		<?php
	}
	?>
	<script>
	window.scrollTo(0, document.body.scrollHeight);
	</script>
    <?php
	ob_flush();
	flush();
}

function runOffBrowserLoad(){
	$GLOBALS['offline'] = true;
	checkUpdate();
	anonymousDataRunCheck();
	checkRawHistoryAndDelete();
	autoSelectConnectionMethod();
	
	if(manageEasyCron::isActive()){
		manageEasyCron::manageCronEnable();
	}

	$temp = array();
	setHook('runOffBrowserLoad', $temp);
}

function runWhileBrowserIdle(){
	getFaviconsPanelIdle();
	processExpiredCacheFiles();
}

function processExpiredCacheFiles(){
	$lastCheck = getOption('lastExpiredCacheFilesCheck');
	$minInterval = 60 * 60 * 24; // once per day
	$nextCheck = $lastCheck + $minInterval;
	if ($nextCheck >= time()) {
		return false;
	}
	include_once(APP_ROOT."/includes/HTMLHeadCache.php");
	$cacheObj = new cacheCommon();
	$cacheObj->processExpiredCacheFiles();
	updateOption('lastExpiredCacheFilesCheck', time());
}

function getFaviconsPanelIdle(){
	include_once(APP_ROOT."/includes/favicon.php");
	return Favicon::getFaviconsPanelIdle();
}

function getResponseMoreInfo($historyID){
	$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$historyID
           				)
        			);
	$rawData = DB::getRow("?:history_raw_details", "response, callInfo", $where);
	$rawResponseData = $rawData['response'];
	$rawResponseData = maybeUnCompress($rawResponseData);
	if (stripos($rawResponseData, '<IWPHEADER') === false) {
		$curlInfo = unserialize($rawData['callInfo']);
		stripHeaders($rawResponseData, $curlInfo);
	}else{
		removeResponseJunk($rawResponseData);
		return $rawResponseData;
	}
	
	$startStr = '<IWPHEADER>';
    $endStr = '<ENDIWPHEADER';

	$response_start = stripos($rawResponseData, $startStr);	
	if($response_start === false){
		return $rawResponseData;
	}
	$str = substr($rawResponseData, 0, $response_start);
	
	$response_End = stripos($rawResponseData, $endStr);
	$Estr = substr($rawResponseData, $response_End + strlen($endStr));
	$Estr = (substr($Estr, 0, 1) == '>') ? substr($Estr, 1) : $Estr;
	return $str.$Estr;
}

/*
$type = 'N' -> notice, 'W' -> Warning, 'E' -> Error
$state = 'T' -> Timer, 'U' -> user should close it
* $scheduleTime = Time stamp, When the Notification is triggered
*/
function addNotification($type, $title, $message, $state='T', $callbackOnClose='', $callbackReference='', $scheduleTime=''){


        $offlineNotifications = getOption('offlineNotifications');
        $offlineNotifications = (!empty($offlineNotifications)) ? @unserialize($offlineNotifications) : array();
        $notifications = &$offlineNotifications;
	
	$key =  md5($type.$title.$message);
	if(empty($notifications[$key])){
		$schedule = ($scheduleTime=='')?0:$scheduleTime;
		$notifications[$key] = array('key' => $key,
									 'type' => $type,
									 'title' => $title, 
									 'message' => $message, 
									 'state' => empty($callbackOnClose) ? $state : 'U', 
									 'callbackOnClose' => $callbackOnClose, 
									 'callbackReference' => $callbackReference, 
									 'counter' => 1,
									 'time' => time(),
									 'schedule' => $schedule,
									 'notified' => false);
	}
	else{
		$notifications[$key]['counter']++;
	}
	
	if(!empty($offlineNotifications)){
		//save in db
		updateOption('offlineNotifications', serialize($offlineNotifications));
	}
}

function getNotifications($reloaded=false){
	
	if(empty($GLOBALS['userID'])){ return false; }//No session, dont send any notifications

	$msg = $schedule = $notifications = $callBack = array();
	
	$offlineNotifications = getOption('offlineNotifications');
	
	if(!empty($offlineNotifications)){
		$offlineNotifications = @unserialize($offlineNotifications);
		/*
		 * Code change for schedule start here
		 */
		$offlineNotifications = (array)$offlineNotifications;
		foreach($offlineNotifications as $key => $messages) {
			if($messages['shcedule']<=time()) {
				$msg[$key] = $messages; 		
			} else {
				$schedule[$key] = $messages;
			}
		}
		$offlineNotifications = $msg;
		if(count($schedule)>0) {
			updateOption('offlineNotifications', serialize($schedule));
		} else {
			updateOption('offlineNotifications', NULL);
		}
		/*
		 * Code change for schedule End here
		 */
			
	}	
	
	if(!empty($offlineNotifications) && is_array($offlineNotifications))
	foreach($offlineNotifications as $key => $_notification){
                $notifications[] = $_notification;
		/*if(!empty($_notification['callbackOnClose'])){
			if($reloaded || !$_notification['notified']){
				$offlineNotifications[$key]['notified'] = true;
				$notifications[] = $_notification;
			}
		}
		else{
			unset($offlineNotifications[$key]);
			$notifications[] = $_notification;
		}*/		
	}

	
	return $notifications;	
}

function closeNotification($key){
	//only happens when user logged in
}

function installFolderAlert(){
	if (defined('IWP_TRIAL_PANEL')) {
		return false;
	}
	if(is_dir(APP_ROOT.'/install')){
		$lastNotify = getOption('lastRemoveInstallFolderNotified');
		$retryTime = 60 * 60 * 24 * 30; // send notification again after one month
		$lastNotify += $retryTime;
		if ($lastNotify >= time()) {
			return false;
		}
		addNotification($type='E', $title='Security Warning!', $message='Please remove or rename the "install" folder.', $state='U', $callbackOnClose='', $callbackReference='');
		updateOption('lastRemoveInstallFolderNotified', time());
	}
}

function userStatus($userID = false){
	if (!$userID) {
		$userID = $GLOBALS['userID'];
	}
	$where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=> $userID
           				)
        			);
	$status = DB::getField("?:users", "accessLevel", $where);
	return $status;
}

function setHook($hook, &$arg1 = NULL, &$arg2 = NULL, &$arg3 = NULL, &$arg4 = NULL, &$arg5 = NULL, &$arg6 = NULL, &$arg7 = NULL, &$arg8 = NULL, &$arg9 = NULL){
	
	$num = func_num_args();
	$args = array();
	for ($i = 1; $i < 10; $i++) {//$i = 1, skiping first arg which is always a hook name
		$argName = 'arg' . $i;
		if ($i < $num) {
			$args[$i] = &$$argName;
		}
		unset($$argName, $argName);
	}
	
	$hooks = Reg::get('hooks');
	if(empty($hooks[$hook])){
		return false;
	}
	foreach($hooks[$hook] as $func){
		if(function_exists($func)){
			call_user_func_array($func, $args);
		}
	}
}


function regHooks(){
	
	$args = func_get_args();
	
	$hooks = Reg::get('hooks');
	
	$backtrace = debug_backtrace();
	
	$addonSlug = basename(dirname($backtrace[0]['file']));
	
	foreach($args as $arg){
		$arg = trim($arg);
		if(empty($arg) || !is_string($arg)){
			continue;
		}
		if(!isset($hooks[$arg])){
			$hooks[$arg] = array();
		}
		
		$hooks[$arg][] = $addonSlug.ucfirst($arg);
		
		$hooks[$arg] = array_unique($hooks[$arg]);		
	}	
	Reg::set('hooks', $hooks);
}

function getInstalledAddons($withUpdates=false){
	$addons = DB::getArray("?:addons", "*", "1", 'slug');
        
        if(empty($addons)){
		return array();
	}
	foreach($addons as $slug => $addon){
		$addons[$slug]['version'] = getAddonVersion($slug);	
		unset($addons[$slug]['validityExpires']);//dont trust the data saved in app db so unsetting
	}
	
	if($withUpdates){
		$updateAddonsAvailable = @unserialize(getOption('updateAddonsAvailable'));
			
		if(!empty($updateAddonsAvailable)){
			foreach($updateAddonsAvailable as $slug => $updateAddon){
				if(!empty($addons[$slug])){
					if(!empty($updateAddon['updateAvailable'])){			
						$addons[$slug]['updateAvailable'] = $updateAddon['updateAvailable'];				
					}
					//$addons[$slug]['isValidityExpired'] = $updateAddon['isValidityExpired'];//calculate isValidityExpired instead of getting from IWP Service(why? it can show less accurate data, because 24hrs once app check for update and get these data
					$addons[$slug]['validityExpires'] = $updateAddon['validityExpires'];
					$addons[$slug]['datePurchased'] = $updateAddon['datePurchased'];
					
					
					$addons[$slug]['isValidityExpired'] = false;
					if($addons[$slug]['validityExpires'] < time()){
						$addons[$slug]['isValidityExpired'] = true;
					}
					
					//isLifetime is used in addon/view.tpl.php
					$addons[$slug]['isLifetime'] = false;
					if( ($addons[$slug]['validityExpires']-$addons[$slug]['datePurchased']) > (86400 * 365 * 20)){
						$addons[$slug]['isLifetime'] = true;
					}
				}
			}
		}
	}
	
	return $addons;
}

function regSetInstalledAddonsDetails($activeLoadedAddonsSlugs){
	if (isV3Panel()) {
		$installedAddons = getInstalledAddonsV3();
	}else{
		$installedAddons = getInstalledAddons();
	}
	foreach($installedAddons as $addonSlug => $addonDetails){
		if($activeLoadedAddonsSlugs[$addonSlug]){
			$installedAddons[$addonSlug]['isLoaded'] = true;
		}
		else{
			$installedAddons[$addonSlug]['isLoaded'] = false;
		}
	}
	Reg::set('addonDetails', $installedAddons);
}

function getAddonAlertCount(){

	//get addon updates count
	$i = 0;
	$addons = getInstalledAddons(true);	
	if(!empty($addons)){
		foreach($addons as $slug => $addon){
			if(!empty($addon['updateAvailable'])) $i++;
		}
	}
	$i;

	//get new addons(non installed) count
	$newAddons = getNewAddonsAvailable();
	if(!empty($newAddons)){
		$i += count($newAddons);
	}
	return $i;
}

function getAddonUpdateCount(){
	$i = 0;
	$addons = getInstalledAddons(true);	
	if(!empty($addons)){
		foreach($addons as $slug => $addon){
			if(!empty($addon['updateAvailable'])) $i++;
		}
	}
	return $i;
}
function getAddonVersion($slug){
	$matches = array();
	if(file_exists(getAppRoot().'/addons/'.$slug.'/addon.'.$slug.'.php')){
				
		$fp = fopen(getAppRoot().'/addons/'.$slug.'/addon.'.$slug.'.php', 'r');
		$fileData = fread($fp, 8192);
		fclose($fp);
		preg_match( '/^[ \t\/*#@]*' . preg_quote( 'version', '/' ) . ':(.*)$/mi', $fileData, $matches);
		return trim($matches[1]);
	}
	return false;
}

function getOldAddonVersion($slug){ //supported from 2.2.0 //this should be used after replacing old addon with new addon files and then to get old version
	$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$slug
           				)
        			);
	return DB::getField("?:addons", "updateCurrentVersion", $where);
}

function userAddonsAccess(&$activeAddons){
	
	$permissions = userAllowAccessTest();
	
	if(!empty($permissions) && is_array($permissions)){
		foreach($activeAddons as $activeAddonkey => $activeAddonsSlug){
			if(in_array($activeAddonsSlug['slug'], $permissions['restrict'])){
				unset($activeAddons[$activeAddonkey]);
			}
		}
	}
}


function userAllowAccessTest(){
	$where = array(
			      		'query' =>  "userID = ':userID'",
			      		'params' => array(
			               ':userID'=>$GLOBALS['userID']
           				)
        			);
	$getPermissions = DB::getField("?:users", "permissions", $where);

	if(!empty($getPermissions)){
		$permissions = unserialize($getPermissions);
		return $permissions;
	}
	return array();
}


function loadActiveAddons(){
	
	$suiteDetails = unserialize(getOption('suiteDetails'));
	
	if(empty($suiteDetails) and !is_array($suiteDetails)) $addonSuiteMiniActivity='';
	else $addonSuiteMiniActivity=$suiteDetails['addonSuiteMiniActivity'];
	if(panelRequestManager::checkIsAddonPlanLimitExceeded('addonSuiteLimitExceededIllegally') && panelRequestManager::getAddonSuitePlanActivity()=='installed') {
		Reg::set('addonSuiteLimitExceededIllegally', 1);
		Reg::set('addonSuiteLimitExceededAttempt', 1);
	} else {
		Reg::set('addonSuiteLimitExceededIllegally', 0);
		Reg::set('addonSuiteLimitExceededAttempt', 0);
	}
	
	$activeAddons = DB::getArray("?:addons", "slug, status, addon", "1");
        
        if(userStatus() != 'admin'){
		userAddonsAccess($activeAddons);
	}
	$installedAddons = @unserialize(getOption('updateAddonsAvailable'));
	$newAddons = getNewAddonsAvailable();
	$purchasedAddons = array();
        
	if(!empty($installedAddons)){ $purchasedAddons = array_merge($purchasedAddons, array_keys($installedAddons));  }
	if(!empty($newAddons)){ $purchasedAddons = array_merge($purchasedAddons, array_keys($newAddons));  }
	Reg::set('purchasedAddons', $purchasedAddons);
	$uninstallAddons = $uninstall = $activeLoadedAddonsSlugs = $allPurchasedAddonsNameAndSlug = array();
	foreach($activeAddons as $key => $addon){
		if(!in_array($addon['slug'], $purchasedAddons)){
			$uninstall[] = $addon['slug'];
			$uninstallAddons[]['slug'] = $addon['slug'];
		}
		if($addon['status'] == 'active'){
			
			$allPurchasedAddonsNameAndSlug[$addon['slug']] = $addon['addon'];
			
			if(Reg::get('addonSuiteLimitExceededIllegally') && Reg::get('addonSuiteLimitExceededAttempt')) {
				$activeLoadedAddonsSlugs[$addon['slug']] = array('slug' => $addon['slug']);
			} else {
				//if(file_exists(APP_ROOT.'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php')){
				@include_once(getAppRoot().'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php');
					
				if(method_exists('addon'.ucfirst($addon['slug']),'init')){
					call_user_func(array('addon'.ucfirst($addon['slug']),'init'));
					$activeLoadedAddonsSlugs[$addon['slug']] = array('slug' => $addon['slug']);
				} else{//file not found deactivate the addon
					unset($activeAddons[$key]);
					//DB::delete("?:addons", "slug='".$addon['slug']."'");
					//addNotification($type='E', $title='Addon file missing', $message='The "'.$addon['addon'].'" addon has been removed, since a file is missing.', $state='U', $callbackOnClose='', $callbackReference='');
				}				
			}
		}
	}
	if(!empty($uninstallAddons) && $addonSuiteMiniActivity!='cancelled'){
		addNotification($type='E', $title='Addon error', $message='Addon(s) are not legitimate.', $state='U', $callbackOnClose='', $callbackReference='');
		uninstallAddons($uninstallAddons);
	}
	regSetInstalledAddonsDetails($activeLoadedAddonsSlugs);
	Reg::set('allPurchasedAddonsNameAndSlug', $allPurchasedAddonsNameAndSlug);
	//Reg::set('activeAddons', $activeLoadedAddonsSlugs);
}


function downloadAndInstallAddons($addons){
	$installedHash = getInstalledHash();
	$currentGeneralSettings = Reg::get('settings');
	foreach($addons as $key => $addon){
		appUpdateMsg('Checking download for '.$addon['slug'].'...');
		$downloadCheckLink = getOption('serviceURL').'download.php?appInstallHash='.APP_INSTALL_HASH.'&installedHash='.$installedHash.'&appVersion='.APP_VERSION.'&type=addon&downloadType=install&download='.$addon['slug'].'&downloadVersion='.$addon['version'].'&downloadToken='.$GLOBALS['downloadToken'];		
		if($currentGeneralSettings['participateBeta'] == 1){
			$downloadCheckLink .= '&participateBeta=1';
		}
				
		$temp = doCall($downloadCheckLink, '', $timeout=30);
		list($result, , , $curlInfo) = $temp;
		
		//$result = base64_decode($result);
		//$result = @unserialize($result);
		$result = getServiceResponseToArray($result);
		
		$cURLErrors = new cURLErrors($curlInfo);
		if($cURLErrors->isOk()){
			if($result['status'] == 'success'){
				$addons[$key]['downloadLink'] = $result['downloadLink'];//$downloadCheckLink.'&checked=true';
			}
			elseif($result['status'] == 'error'){
				$addons[$key]['error'] = 1;
				// unset($addons[$key]);
				appUpdateMsg('Error while downloading addon '.$addon['slug'].': '.$result['errorMsg']);
			}
		}else{
			$addons[$key]['error'] = 1;
			// unset($addons[$key]);
			appUpdateMsg('Error while downloading addon '.$addon['slug'].': Unable to communicate with server(' . $cURLErrors->getErrorMsg() .').');
		}
			
		
		
	}
	downloadAndUnzipAddons($addons);
	installAddons($addons);
	retryFailedAddonsInstall($addons);
	updateOption('updateLastCheck', 0);//to trigger checkUpdate in next page load
	//$_SESSION['addonAlertCount'] = 0;
	//manageCookies::cookieSet('addonAlertCount',0,array('expire'=>0));
        updateOption('addonAlertCount',  '0');
}

function retryFailedAddonsInstall(&$addons){
	$flag = false;
	if (empty($addons)) {
		return;
	}
	foreach ($addons as $key => $addon) {
		if (!empty($addon['process']['unzipDone'])) {
			continue;
		}
		if (!empty($addon['error']) && (empty($addon['retryCount']) || $addon['retryCount'] < 3)) {
			$addons[$key]['retryCount']++;
			$flag = true;
		}
	}

	if ($flag == true) {
		appUpdateMsg('Retrying failed addons...');
		downloadAndInstallAddons($addons);
	}else{
		appUpdateMsg('<br>Please <a href="'.APP_URL.'" target="_top">click here</a> to reload the app.'); 
	}
}

function updateAddons($addons){
	$installedHash = getInstalledHash();
	$currentGeneralSettings = Reg::get('settings');
	foreach($addons as $key => $addon){
		appUpdateMsg('Checking download for '.$addon['slug'].'...');
		$downloadCheckLink = getOption('serviceURL').'download.php?appInstallHash='.APP_INSTALL_HASH.'&installedHash='.$installedHash.'&appVersion='.APP_VERSION.'&type=addon&downloadType=update&download='.$addon['slug'].'&downloadVersion='.$addon['version'];
		if($currentGeneralSettings['participateBeta'] == 1){
			$downloadCheckLink .= '&participateBeta=1';
		}
	    if(defined('IWP_TRIAL_PANEL')) {
			$downloadCheckLink .= '&trailPanel='.IWP_TRIAL_PANEL;
	    }
		$temp = doCall($downloadCheckLink, '', $timeout=30);
		list($result, , , $curlInfo) = $temp;
		//$result = base64_decode($result);
		//$result = @unserialize($result);
		$result = getServiceResponseToArray($result);

		$cURLErrors = new cURLErrors($curlInfo);
		if($cURLErrors->isOk()){
			if($result['status'] == 'success'){
				$addons[$key]['downloadLink'] = $result['downloadLink'];//$downloadCheckLink.'&checked=true';
			}
			elseif($result['status'] == 'error'){
				unset($addons[$addon['slug']]);
				appUpdateMsg('Error while downloading addon '.$addon['slug'].': '.$result['errorMsg']);
			}
		}
		else{
			unset($addons[$addon['slug']]);
			appUpdateMsg('Error while downloading addon '.$addon['slug'].': Unable to communicate with server(' . $cURLErrors->getErrorMsg() .').');
		}		
	}
	downloadAndUnzipAddons($addons);
	
	foreach($addons as $addon){
		if($addon['process']['unzipDone']){			
			//$addon['process']['updated'] = true;
			include(APP_ROOT.'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php');
			$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$addon['slug']
           				)
        			);
			$prevVer = DB::getField("?:addons", "updateCurrentVersion", $where);

			if(method_exists('addon'.ucfirst($addon['slug']),'update')){
				call_user_func(array('addon'.ucfirst($addon['slug']),'update'));
			}
			$newAddonVersion = getAddonVersion($addon['slug']);
			
			$optionVer['action'] = 'updated';
			$optionVer['actionTime'] = time();
			$optionVer['prevVer'] = $prevVer;
			$optionVer['newVer'] = $newAddonVersion;
			$optionVer['slug'] = $addon['slug'];
			manipulateOption('versionLogs', $optionVer);
			
			DB::update("?:addons", array('updateCurrentVersion' => $newAddonVersion), $where);//updating in database that addon is updated
			
			//remove updateAvailable for this addon so that it will stop false update notification in next browser app load
			$updateAddonsAvailable = @unserialize(getOption('updateAddonsAvailable'));
			if(isset($updateAddonsAvailable[ $addon['slug'] ]['updateAvailable']) && !empty($updateAddonsAvailable[ $addon['slug'] ]['updateAvailable'])){
				unset($updateAddonsAvailable[ $addon['slug'] ]['updateAvailable']);
				updateOption('updateAddonsAvailable', serialize($updateAddonsAvailable));
			}
			
			appUpdateMsg('Addon '.$addon['slug'].' successfully updated.');		
		}
	}
	appUpdateMsg('<br>Please <a href="'.APP_URL.'" target="_top">click here</a> to reload the app.');
	updateOption('updateLastCheck', 0);//to trigger checkUpdate in next page load 	
	//$_SESSION['addonAlertCount'] = 0;
	//manageCookies::cookieSet('addonAlertCount',0,array('expire'=>0));
        updateOption('addonAlertCount',  '0');
}

function downloadAndUnzipAddons(&$addons){
	foreach($addons as $key => $addon){
		if(!empty($addon['downloadLink'])/* && !empty($updateDetails['fileMD5'])*/){
		
			$downloadLink = $addon['downloadLink'];
			//$fileMD5 = $updateDetails['fileMD5'];
		
			$zip = getTempName('addon_'.$addon['slug'].'.zip');
			
			
			appUpdateMsg('Downloading '.$addon['slug'].' package...');
			$isDone = downloadURL($downloadLink, $zip);			
			
			if(!$isDone){ //download failed
				$addons[$key]['error'] = 1;
				appUpdateMsg($addon['slug'].' package download failed.', true);
				continue;
			}
			
			if(!initFileSystem()){
				appUpdateMsg('Unable to initiate file system.', true);
				return false;
			}
			
			$unPackResult = unPackToWorkingDir($zip);
			if(!empty($unPackResult) && is_array($unPackResult)){
				$source = $unPackResult['source'];
				$remoteSource = $unPackResult['remoteSource'];
			}
			else{
				$addons[$key]['error'] = 1;
				continue;
			}
			
			$destination = APP_ROOT;
			if(!copyToRequiredDir($source, $remoteSource, $destination)){
				return false;	
			}
			

			appUpdateMsg('Unzipped '.$addon['slug'].' package.');
			$addons[$key]['process']['unzipDone'] = true;

			@unlink($zip);
					
				
		}
	}
	//return $addons;
}

function installAddons($addons){//install and activate the addon

	foreach($addons as $addon){
		if(empty($addon['process']['unzipDone'])){
			continue;	
		}
		$ok=false;
		appUpdateMsg('Installing '.$addon['slug'].' addon...');
		$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$addon['slug']
           				)
        			);
		$isExist = DB::getField("?:addons", "slug", $where);
		if($isExist){
			appUpdateMsg('The '.$addon['slug'].' addon is already installed.');
			continue;
		}		
		
		if(file_exists(APP_ROOT.'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php')){
			//activating the addon
			$isDone = DB::insert("?:addons", array('slug' => $addon['slug'], 'addon' => $addon['addon'], 'status' => 'active', 'validityExpires' => $addon['validityExpires'], 'initialVersion' => $addon['version'], 'updateCurrentVersion' => $addon['version']));
			if($isDone){
				$ok=true;
				include_once(APP_ROOT.'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php');
				if(method_exists('addon'.ucfirst($addon['slug']), 'install')){

					$isSuccess = call_user_func(array('addon'.ucfirst($addon['slug']),'install'));
					if(!$isSuccess){
						$ok=false;
						$where = array(
				          'query' => "slug = ':slug'",
				          'params' => array(
				               ':slug'=>$addon['slug']
				           )
				        );
						DB::delete("?:addons", $where);
						appUpdateMsg('An error occurred while installing the '.$addon['slug'].' addon.');
					}
				}
				if($ok){
					appUpdateMsg($addon['slug'].' addon successfully installed.');
					
					//remove addon install available for this addon so that it will stop false notification in next browser app load
					//$newAddonsAvailableTemp = @unserialize(getOption('newAddonsAvailable'));
					//if(isset($newAddonsAvailableTemp[ $addon['slug'] ])){
					//	unset($newAddonsAvailableTemp[ $addon['slug'] ]);
					//	updateOption('newAddonsAvailable', serialize($newAddonsAvailableTemp));
					//}//commented because new installed getting deleted in next run
				}
			}
		}
		else{
			appUpdateMsg('A file was found missing while installing the '.$addon['slug'].' addon.');
		}
					
		$optionVer['action'] = 'installed';
		$optionVer['actionTime'] = time();
		$optionVer['prevVer'] = '0';
		$optionVer['newVer'] = $addon['version'];
		$optionVer['slug'] = $addon['slug'];
		manipulateOption('versionLogs', $optionVer);
		
		
	}
	//force update to make new addons to show as installed
	//checkUpdate(true, true);//commented because this deleting old addons

}

function activateAddons($addons){
	$success = array();
	foreach($addons as $key => &$addon){
		$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$addon['slug']
           				)
        			);
		$isExist = DB::getField("?:addons", "slug", $where);
		if(!$isExist){
			addNotification($type='E', $title='Addon activation failed', $message='The '.$addon['slug'].' addon does not exist in the database.', $state='U', $callbackOnClose='', $callbackReference='');
			$addons[$key]['activate'] = false;
			continue;
		}		
		
		if(file_exists(getAppRoot().'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php')){
			//activating the addon
			$isDone = DB::update("?:addons", array( 'status' => 'active'), $where);
			if($isDone){
				$addons[$key]['activate'] = true;
				$success[$addon['slug']] = DB::getField("?:addons", "addon", $where);
				include_once(getAppRoot().'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php');
				if(method_exists('addon'.ucfirst($addon['slug']),'activate')){
					call_user_func(array('addon'.ucfirst($addon['slug']),'activate'));
				}
			}
		}
		else{
			$addons[$key]['activate'] = false;
			addNotification($type='E', $title='Addon activation failed', $message='A file was found missing while activating the '.$addon['slug'].' addon.', $state='U', $callbackOnClose='', $callbackReference='');
		}
	}
	if(!empty($success)){
		addNotification($type='N', $title='Addon has been activated', $message=implode('<br>', $success), $state='U', $callbackOnClose='', $callbackReference='');
	}
	return $addons;
}

function deactivateAddons($addons){
	foreach($addons as $key => $addon){
		$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$addon['slug']
           				)
        			);
		$isExist = DB::getField("?:addons", "slug", $where);
		if(!$isExist){
			$addons[$key]['deactivate'] = false;
			addNotification($type='E', $title='Addon deactivation failed', $message='The '.$addon['slug'].' addon does not exist in the database.', $state='U', $callbackOnClose='', $callbackReference='');
			continue;
		}		
		
		if(file_exists(getAppRoot().'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php')){
			//activating the addon
			$isDone = DB::update("?:addons", array( 'status' => 'inactive'), $where);
			if($isDone){
				$addons[$key]['deactivate'] = true;
				$success[$addon['slug']] = DB::getField("?:addons", "addon", $where);
				include_once(getAppRoot().'/addons/'.$addon['slug'].'/addon.'.$addon['slug'].'.php');
				if(method_exists('addon'.ucfirst($addon['slug']),'deactivate')){
					call_user_func(array('addon'.ucfirst($addon['slug']),'deactivate'));
				}
			}
		}
		else{
			$addons[$key]['deactivate'] = false;
			addNotification($type='E', $title='Addon deactivation failed', $message='A file was found missing while deactivating the '.$addon['slug'].' addon.', $state='U', $callbackOnClose='', $callbackReference='');
		}
	}
	if(!empty($success)){
		addNotification($type='N', $title='Addon has been deactivated', $message=implode('<br>', $success), $state='U', $callbackOnClose='', $callbackReference='');
	}
	return $addons;
}

function uninstallAddons($addons){
	foreach($addons as $addon){
		
		if(is_object($GLOBALS['FileSystemObj']) || uninstallAddonsInitFileSystem()){
			$GLOBALS['FileSystemObj']->delete(APP_ROOT.'/addons/'.$addon['slug'], true);
		}
		$where = array(
			      		'query' =>  "slug = ':slug'",
			      		'params' => array(
			               ':slug'=>$addon['slug']
           				)
        			);		
		$isDone = DB::delete("?:addons", $where);
		addNotification($type='N', $title='Addon uninstalled', $message='The '.$addon['slug'].' addon has been uninstalled.', $state='U', $callbackOnClose='', $callbackReference='');	
	}
}

function uninstallAddonsInitFileSystem(){
	ob_start();
	$r = initFileSystem();
	ob_end_clean();
	return $r;
}

function getAddonsHTMLHead(){
	$createAddonCache = new createAddonCache();
	$head =  $createAddonCache->initiateCacheProcess();
	return $head;
}

function getInstalledHash(){
	return sha1(rtrim(APP_DOMAIN_PATH,"/")."/".'|--|'.APP_ROOT);
}


function updateAppRegistered($user){//$user => username or email registered with IWP Site

	if (!empty($user)) {
		deleteOption('infinitewpAccountCredentials');
	}
	updateOption('appRegisteredUser', $user);
}

function isAppRegistered(){
	$appRegisteredUser = getOption('appRegisteredUser');
	if(!empty($appRegisteredUser)){
		return true;
	}
	return false;
}

function processCheckAddonsUpdate($addonsUpdate){
	//get updates
	updateOption('updateAddonsAvailable', serialize($addonsUpdate['updateAddons']));
	updateOption('newAddonsAvailable', serialize($addonsUpdate['newAddons']));
	updateOption('promoAddons', serialize($addonsUpdate['promoAddons']));
	updateOption('suiteDetails', serialize($addonsUpdate['suiteDetails']));
	
	addRenewalAlertNotification($addonsUpdate);
}

function addRenewalAlertNotification($addonsUpdate){
	$userHelp = panelRequestManager::getUserHelp();
	$newUserHelp = $newUserHelpEtc = array();
	if(!empty($addonsUpdate['updateAddons'])){//25,6,1
		foreach($addonsUpdate['updateAddons'] as $addonSlug => $addonDetails){
			if( $addonDetails['validityExpires'] > 0 && ($addonDetails['validityExpires'] - (86400 * 30)) < time() ){//about to expire in less then 30 days or already expired
				if(!empty($addonDetails['isValidityExpired'])){
					if(empty($userHelp['renewal_alert_0d_'.$addonDetails['validityExpires']])){
						$newUserHelp['renewal_alert_0d_'.$addonDetails['validityExpires']] = true;
						$newUserHelpEtc['renewal_alert_0d_'.$addonDetails['validityExpires']]['names'][] = $addonDetails['addon'];
					}	
				}
				else if( ($addonDetails['validityExpires'] - (86400 * 1)) > time() && ($addonDetails['validityExpires'] - (86400 * 2)) < time() ){
					if(empty($userHelp['renewal_alert_1d_'.$addonDetails['validityExpires']])){
						$newUserHelp['renewal_alert_1d_'.$addonDetails['validityExpires']] = true;
						$newUserHelpEtc['renewal_alert_1d_'.$addonDetails['validityExpires']]['names'][] = $addonDetails['addon'];
					}				
				}
				else if( ($addonDetails['validityExpires'] - (86400 * 2)) > time() && ($addonDetails['validityExpires'] - (86400 * 6)) < time() ){
					if(empty($userHelp['renewal_alert_6d_'.$addonDetails['validityExpires']])){
						$newUserHelp['renewal_alert_6d_'.$addonDetails['validityExpires']] = true;
						$newUserHelpEtc['renewal_alert_6d_'.$addonDetails['validityExpires']]['names'][] = $addonDetails['addon'];
					}				
				}
				else if( ($addonDetails['validityExpires'] - (86400 * 10)) > time() && ($addonDetails['validityExpires'] - (86400 * 25)) < time() ){
					if(empty($userHelp['renewal_alert_25d_'.$addonDetails['validityExpires']])){
						$newUserHelp['renewal_alert_25d_'.$addonDetails['validityExpires']] = true;
						$newUserHelpEtc['renewal_alert_25d_'.$addonDetails['validityExpires']]['names'][] = $addonDetails['addon'];
					}				
				}				
				
			}
		}
		
		panelRequestManager::updateUserHelp($newUserHelp);
		if(0 && !empty($newUserHelp)){ //notification disabled because we implemented subscription
			foreach($newUserHelp as $key => $value){
				$isExpired = false;
				$thisSingPlurMsg = array('AN ADDON IS EXPIRING', 'The following addon is about to expire. Please renew it immediately.');
				if(strpos($key, "renewal_alert_0d_") !== false){
					$isExpired = true;
					$thisSingPlurMsg = array('AN ADDON HAS EXPIRED', 'The following addon has expired. Please renew it immediately to get continued updates and support.');
				}
				if(count($newUserHelpEtc[$key]['names']) > 1){
					$thisSingPlurMsg[0] = ($isExpired) ? 'A FEW ADDONS HAVE EXPIRED' : 'A FEW ADDONS ARE EXPIRING';
					$thisSingPlurMsg[1] = ($isExpired) ? 'The following addons have expired. Please renew them immediately to get continued updates and support.' : 'The following addons are about to expire. Please renew them immediately.';
				}
				addNotification($type='E', $title=$thisSingPlurMsg[0], $thisSingPlurMsg[1].'<br>'.implode('<br>', $newUserHelpEtc[$key]['names']).'<br><a style="display:none" class="closeRenewalNotification" notifingitem="'.$key.'">Dismiss</a> <a href="'.IWP_SITE_URL.'my-account/" target="_blank" >Renew Now</a>', $state='U');
			}
		}
		
	}
}

function getNewAddonsAvailable(){
	return @unserialize(getOption('newAddonsAvailable'));
}

function getPromoAddons(){
	return @unserialize(getOption('promoAddons'));
}


function initMenus(){
	
	$menus['manage'] 	= array();
	$menus['protect'] 	= array();
	$menus['monitor'] 	= array();
	$menus['maintain'] 	= array();
	$menus['tools'] 	= array();
	
	$menus['manage']['displayName'] 	= 'Manage';
	$menus['manage']['subMenus'][] 		= array('page' => 'updates', 'displayName' => '<span class="float-left">Updates</span><span class="update_count float-left droid700" id="totalUpdateCount">0</span><div class="clear-both"></div>');
	$menus['manage']['subMenus'][] 		= array('page' => 'items', 'displayName' => 'Plugins &amp; Themes');
	
	$menus['protect']['displayName'] 	= 'Protect';
	$menus['protect']['subMenus'][] 	= array('page' => 'backups', 'displayName' => 'Backups');
	
	$menus['monitor']['displayName'] 	= 'Monitor';	
	$menus['maintain']['displayName'] 	= 'Maintain';	
	$menus['tools']['displayName'] 		= 'Tools';
	
	setHook('addonMenus', $menus);
	
	$hooks = Reg::get('hooks');
	
	Reg::set('menus', $menus);
}

function printMenus(){
	$menus = Reg::get('menus');
	$tempAddons = array();
	$tempAddons['displayName']	= 'Addons';
	$tempAddons['subMenus']		= array();
	
	foreach($menus as $key => $group){	
		if(isset($menus[$key]) && !empty($menus[$key]['subMenus']) && is_array($menus[$key]['subMenus'])){	
			$groupName = $menus[$key]['displayName'];
			$singleGroupMenu = $menus[$key]['subMenus'];
			$HTML = TPL::get('/templates/menu/menu.tpl.php', array('groupName' => $groupName, 'singleGroupMenu' => $singleGroupMenu));
			echo $HTML;
		}
		/*elseif(isset($group['displayName'])){
			
		}*/
		elseif(is_string($group)){
			$tempAddons['subMenus'][] = $group;
		}
	}
	
	if(!empty($tempAddons['subMenus'])){
		
		$groupName = $tempAddons['displayName'];
		$singleGroupMenu = $tempAddons['subMenus'];
		$HTML = TPL::get('/templates/menu/menu.tpl.php', array('groupName' => $groupName, 'singleGroupMenu' => $singleGroupMenu));
		echo $HTML;
		
	}
}

function getAddonMenus(){
	$menus = array();
	return implode("\n", $menus);
}


function repositoryTestConnection($account_info){
	if(isset($account_info['iwp_ftp']) && !empty($account_info)) {
		$return = FTPTestConnection($account_info['iwp_ftp']);
	}
	  
	if(isset($account_info['iwp_amazon_s3']) && !empty($account_info['iwp_amazon_s3'])) {
		if(phpversion() >= '5.3.3'){
			require_once(APP_ROOT . '/lib/amazon/s3IWPTestConnection.php');
			$return = repositoryAmazons3($account_info['iwp_amazon_s3']);
		}
		else{
			$return = repositoryAmazons3BwdComp($account_info['iwp_amazon_s3']);
		}
	}
	  
	if (isset($account_info['iwp_dropbox']) && !empty($account_info['iwp_dropbox'])) {
	  $return = repositoryDropbox($account_info['iwp_dropbox']);
	}	
	  
	if (isset($account_info['iwp_gdrive']) && !empty($account_info['iwp_gdrive'])) {
	  $return = repositoryGDrive($account_info['iwp_gdrive']);
	}
	return $return;	
}
	
function FTPTestConnection($args){
	extract($args);	
	$ftp_hostname = $ftp_hostname ? $ftp_hostname : $hostName;
	$ftp_username = $ftp_username ? $ftp_username : $hostUserName;
	$ftp_password = $ftp_password ? $ftp_password : $hostPassword;
	$FTPBase = $ftp_remote_folder ? $ftp_remote_folder : $FTPBase;
	
	if(empty($ftp_hostname)){
		return array('status' => 'error',
			'errorMsg' => 'Inavlid FTP host',
			);	
	}

    if(isset($use_sftp) && $use_sftp == 1) {
    	return SFTPTestConnection($args);
    }
	else{
		return simpleFTPTestConnection($args);
	}

}
function simpleFTPTestConnection($args){
	extract($args);	
	$ftp_hostname = $ftp_hostname ? $ftp_hostname : $hostName;
	$ftp_username = $ftp_username ? $ftp_username : $hostUserName;
	$ftp_password = $ftp_password ? $ftp_password : $hostPassword;
	$FTPBase = $ftp_remote_folder ? $ftp_remote_folder : $FTPBase;
	$ftp_passive = $ftp_passive ? $ftp_passive : $use_pasv;
	$port = $ftp_port ? $ftp_port : 21; //default port is 21
	
	if ($ftp_ssl) {
		if (function_exists('ftp_ssl_connect')) {
			$conn_id = ftp_ssl_connect($ftp_hostname, $port);
			if ($conn_id === false) {
				return array('status' => 'error',
						'errorMsg' => 'Failed to connect to ' . $ftp_hostname,
				);
			}
		}
		else {
			return array('status' => 'error',
			'errorMsg' => 'Your server doesn\'t support FTP SSL',
			);
		}
	} else {
		if (function_exists('ftp_connect')) {
			$conn_id = ftp_connect($ftp_hostname, $port);
			if ($conn_id === false) {
				return array('status' => 'error',
				'errorMsg' => 'Failed to connect to ' . $ftp_hostname,
				);
			}
		}
		else {
			return array('status' => 'error',
			'errorMsg' => 'Your server doesn\'t support FTP',
			);
		}
	}
	$login = @ftp_login($conn_id, $ftp_username, $ftp_password);
	if ($login === false) {
		return array('status' => 'error', 
		'errorMsg' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
		);
	}
	else{
		if(!empty($ftp_passive)){
			@ftp_pasv($conn_id, true);
		}
		if(empty($FTPBase)){
			return array('status' => 'error', 
				'errorMsg' => 'Invalid FTP base path..',
			);
		}
		$testFile = '/__testFTP2'.time().'.php';
		$uploadFilePath = getTempName($testFile); 
		$FTPPathFile = rtrim($FTPBase, '/').$testFile;
		$uploadTestFile = ftp_put($conn_id, $FTPPathFile, $uploadFilePath, FTP_BINARY);
		$appPathFile = APP_ROOT.$testFile;
		@unlink($uploadFilePath);
		if ($uploadTestFile === false) {
			return array('status' => 'error', 
				'errorMsg' => 'FTP upload failed.',
			);
		}
		$isTestFileExits = file_exists($appPathFile);
		ftp_delete($conn_id, $FTPPathFile);
		if (!$isTestFileExits && $basePathValidation == true) {
			return array('status' => 'error', 
				'errorMsg' => 'Invalid FTP base path..',
			);
		}
		else{
			return array('status' => 'success');
		}
		
		
	}	
}
function SFTPTestConnection($args){
	extract($args);	

	$ftp_hostname = $ftp_hostname ? $ftp_hostname : $hostName;
	$ftp_username = $ftp_username ? $ftp_username : $hostUserName;
	$ftp_password = $ftp_password ? $ftp_password : $hostPassword;
	$FTPBase = $ftp_remote_folder ? $ftp_remote_folder : $FTPBase;
	$port = $ftp_port ? $ftp_port : 22;
	include APP_ROOT.'/lib/phpseclib/vendor/autoload.php';
	
    $sftp = new  \phpseclib\Net\SFTP($ftp_hostname, $port);
    if(!$sftp) {
        return array('status' => 'error',
                            'errorMsg' => 'Failed to connect to ' . $ftp_hostname,
            );
    }
    if (!empty($ftp_key)) {
		
		$rsa = new  \phpseclib\Crypt\RSA();
		if (false === $rsa->loadKey($ftp_key)) {
			return array('status' => 'error', 
				'errorMsg' => 'The key provided was not in a valid format, or was corrupt',
			);
		}
		$ftp_password = $rsa;
    }
    
	    if (!$sftp->login($ftp_username, $ftp_password)) {
	        return array('status' => 'error', 
				'errorMsg' => 'FTP login failed for ' . $ftp_username . ', ' . $ftp_password,
			);
	    }
	
		if(empty($FTPBase)){
			return array('status' => 'error', 
				'errorMsg' => 'Invalid FTP base path..',
			);
		}
		if(!$sftp->chdir($FTPBase)){
			return array('status' => 'error', 
				'errorMsg' => 'FTP upload failed.',
			);	
		}
		$testFile = '/__testFTP2'.time().'.php';
		$uploadFilePath = getTempName($testFile); 
		$uploadTestFile = $sftp->put(basename($testFile),$uploadFilePath);
		@unlink($uploadFilePath);
		$appPathFile = APP_ROOT.$testFile;
		if ($uploadTestFile === false) {
			return array('status' => 'error', 
				'errorMsg' => 'FTP upload failed.',
			);
		}
		$isTestFileExits = file_exists($appPathFile);
		$sftp->delete(basename($testFile));
		if (!$isTestFileExits && $basePathValidation == true) {
			return array('status' => 'error', 
				'errorMsg' => 'Invalid FTP base path..',
			);
		}
		else{
			return array('status' => 'success');
		}
	
}
function ensure_phpseclib($classes = false, $class_paths = false) {


	if ($classes) {
		$any_missing = false;
		if (is_string($classes)) $classes = array($classes);
		foreach ($classes as $cl) {
			if (!class_exists($cl)) $any_missing = true;
		}
		if (!$any_missing) return;
	}

	if ($class_paths) {
		$phpseclib_dir = APP_ROOT.'/lib/phpseclib/vendor/phpseclib/phpseclib/phpseclib';
		if (false === strpos(get_include_path(), $phpseclib_dir)) set_include_path(get_include_path().PATH_SEPARATOR.$phpseclib_dir);
		if (is_string($class_paths)) $class_paths = array($class_paths);
		foreach ($class_paths as $cp) {
			include_once($phpseclib_dir.'/'.$cp.'.php');
		}
	}
	}
function repositoryAmazons3BwdComp($args){
	require_once(APP_ROOT."/lib/s3.php");
	extract($args);
	
	if(!empty($as3_bucket_region)){
		$endpoint = 's3-' . $as3_bucket_region . '.amazonaws.com';
	}
	else{
		$endpoint = 's3.amazonaws.com';
	}
    $s3 = new S3(trim($as3_access_key), trim(str_replace(' ', '+', $as3_secure_key)), false, $endpoint);
	
	try{
		$s3->getBucket($as3_bucket, S3::ACL_PUBLIC_READ);
		return array('status' => 'success');
	}
	catch (Exception $e){
         return array('status' => 'error', 'errorMsg' => $e->getMessage());
		 //$e->getMessage();
	}
}

function repositoryDropbox($args){
	extract($args);

	if(isset($consumer_secret) && !empty($consumer_secret)){
		require_once(APP_ROOT.'/lib/dropbox.oauth.php');
		$dropbox = new Dropbox($consumer_key, $consumer_secret);				
		$dropbox->setOAuthToken($oauth_token);
		$dropbox->setOAuthTokenSecret($oauth_token_secret);
		try{
			$dropbox->accountinfo();
			return array('status' => 'success');			
		}
		catch(Exception $e){
			return array('status' => 'error', 'errorMsg' => $e->getMessage());
		}
	}
	return array('status' => 'error', 'errorMsg' => 'Consumer Secret not available');
}

function repositoryGDrive($args)
{
	if(!empty($args['gDriveEmail']))
	{
		//return googleDriveHelper::testConnectionGoogle($args);
		include_once(APP_ROOT.'/lib/googleAPIs/src/Google_Client.php');
		include_once(APP_ROOT.'/lib/googleAPIs/src/contrib/Google_DriveService.php');
		include_once(APP_ROOT.'/lib/googleAPIs/src/contrib/Google_Oauth2Service.php');
		include_once(APP_ROOT.'/lib/googleAPIs/storage.php');
		include_once(APP_ROOT.'/lib/googleAPIs/authHelper.php');
		
		if(function_exists('backupRepositorySetGoogleDriveArgs')){
			$gDriveArgs = backupRepositorySetGoogleDriveArgs($args);
		}else{
			addNotification($type='E', $title='Cloud backup Addon Missing', $message="Check if cloud backup addon exists and is active", $state='U', $callbackOnClose='', $callbackReference='');
			return array('status' => 'error', 'errorMsg' => 'Cloud backup addon missing');
		}
		if(!empty($gDriveArgs) && !empty($gDriveArgs['clientID']) && !empty($gDriveArgs['clientSecretKey']) )
		{		
			$accessToken = $gDriveArgs['token'];
			
			$client = new Google_Client();
			$client->setClientId($gDriveArgs['clientID']);

			$client->setClientSecret($gDriveArgs['clientSecretKey']);
			$client->setRedirectUri($gDriveArgs['redirectURL']);
			$client->setScopes(array(
			  'https://www.googleapis.com/auth/drive',
			  'https://www.googleapis.com/auth/userinfo.email'));
			
			$accessToken = $gDriveArgs['token'];
			$refreshToken = $accessToken['refresh_token'];
			
			try
			{
				$client->refreshToken($refreshToken);
				return array('status' => 'success');
			}
			catch(Exception $e)
			{	
				echo 'google Error ',  $e->getMessage(), "\n";
				return array('status' => 'error', 'errorMsg' => $e->getMessage());
			}
		}
		return array('status' => 'error', 'errorMsg' => 'API key not available.');
	}
	return array('status' => 'error', 'errorMsg' => 'Repository ID not available.');
}

function getAddonHeadJS(){
	$headJS = array();
	setHook('addonHeadJS', $headJS);	
	return implode("\n", $headJS);
}

function cronNotRunAlert(){
	$lastNotify = getoption('lastCronNotRunAlert');
	$retryTime = 60 * 60 * 24 * 7; // send notification again after one week
	$lastNotify += $retryTime;
	if ($lastNotify >= time()) {
		return false;
	}

	if(manageEasyCron::isActive() || Manage_IWP_Cron::isActive()){
		return;
	}	
	
	//cron job should run every 20 mins
	$cronLastRun = getOption('cronLastRun');
	
	if( $cronLastRun > (time() - (40 * 60)) ){//checking for 40 mins instead of 20 mins here
		return;	
	}	
	
	$requiredFor = array();
	
	$settings = panelRequestManager::getSettings();
	$updatesNotificationMail = $settings['notifications']['updatesNotificationMail'];

	//check setting
	if(!($updatesNotificationMail['frequency'] == 'never' || (empty($updatesNotificationMail['coreUpdates']) && empty($updatesNotificationMail['pluginUpdates']) && empty($updatesNotificationMail['themeUpdates']))) ){
		$requiredFor[] = 'Email Update Notification';
	}
	
	setHook('cronRequiredAlert', $requiredFor);
	
	if(!empty($requiredFor)){
		addNotification($type='E', $title='CRON JOB IS NOT RUNNING', $message='Please set the cron job to run every 20 minutes.<div class="droid700" style="white-space: pre; word-wrap: break-word;">'.APP_PHP_CRON_CMD.APP_ROOT.'/cron.php &gt;/dev/null 2&gt;&1</div><br>It is required for the following -<br>'.@implode('<br>', $requiredFor), $state='U', $callbackOnClose='', $callbackReference='');
		updateOption('lastCronNotRunAlert', time());
	}	
}

function onBrowserLoad(){
    manageCookies::cookieUnset('slowDownAjaxCallFrom');
	installFolderAlert();
	cronNotRunAlert();
	crossVersionAddonsNotInstalledAlert();
}

function autoSelectConnectionMethod(){
	$settings = Reg::get('settings');
        $connectionMethod = getOption('connectionMethod');
        $connectionMode = getOption('connectionMode');
        $connectionRunner = getOption('connectionRunner'); 
	if($connectionMethod == 'auto' || $connectionMethod == 'manual' ){
		$result = connectionMethodSameURLCheck();
	}
}

function defineAppFullURL(){
	$appFullURL = buildAppURL(APP_URL);
	define('APP_FULL_URL', $appFullURL);
	if(defined('APP_URL_V3')){
		$appFullURL_V3 = buildAppURL(APP_URL_V3);
		define('APP_FULL_URL_V3', $appFullURL_V3);
	}
}

function buildAppURL($appFullURL){
	$settings = Reg::get('settings');
	if(!empty($settings['httpAuth']['username'])){
		$appURLParts = parse_url($appFullURL);
		$appURLParts['user'] = urlencode($settings['httpAuth']['username']);
		$appURLParts['pass'] = urlencode($settings['httpAuth']['password']);
		$appFullURL = httpBuildURLCustom($appURLParts);
	}	
	return $appFullURL;
}

function getFullWPURL($siteID, $URL, $byPassStaging = NULL){//this will add http auth if it set for the site
	if(is_array($URL))
	{
		$finalURL = array();
		$finalKey = '';
		foreach($URL as $key => $value)
		{
			$finalURL[$key] = $value;
			$siteData = getSiteData($siteID, '', $byPassStaging);
			if(!empty($siteData['httpAuth'])){
				$siteHttpAuth = @unserialize($siteData['httpAuth']);

				if(!empty($siteHttpAuth['username'])){
					$URLParts = parse_url($value);
					$URLParts['user'] = urlencode($siteHttpAuth['username']);
					$URLParts['pass'] = urlencode($siteHttpAuth['password']);
					$finalURL[$key] = httpBuildURLCustom($URLParts);
					$finalKey = $key;
				}
			}
		}
		return $finalURL[$key];
	}
	else
	{
		$finalURL = $URL;
		$siteData = getSiteData($siteID, '', $byPassStaging);
		if(!empty($siteData['httpAuth'])){
			$siteHttpAuth = @unserialize($siteData['httpAuth']);

			if(!empty($siteHttpAuth['username'])){
				$URLParts = parse_url($URL);
				$URLParts['user'] = urlencode($siteHttpAuth['username']);
				$URLParts['pass'] = urlencode($siteHttpAuth['password']);
				$finalURL = httpBuildURLCustom($URLParts);
			}
		}
		return $finalURL;
	}
}



function checkTriggerStatus(){
	$historyStatus = array('completed','writingRequest','pending','initiated','running','scheduled','processingResponse','multiCallWaiting','retry');
	$retryErrors = new errorManager();
	$where = array(
			      		'query' =>  "recheck = 0 AND type IN('backup', 'scheduleBackup', 'staging', 'installClone') AND status = ':status'",
			      		'params' => array(
			               ':status'=>'multiCallWaiting'
           				)
        			);
	$data = DB::getArray("?:history", "siteID, historyID, type, action", $where);
	foreach($data as $key => $value){
		if ($value['action'] == 'multiCallRestore' || $value['action'] == 'restoreNew' || $value['action'] == 'bridgeExtractMulticallRestore' || $value['action'] == 'restoreBackupDownlaod') {
			continue;
		}
		$where = array(
			      		'query' =>  "parentHistoryID = ':parentHistoryID' ORDER BY historyID DESC LIMIT 16",
			      		'params' => array(
			               ':parentHistoryID'=>$value['historyID']
           				)
        			);


		$subTaskData = DB::getArray("?:history", "historyID, status, recheck, error, action", $where);
		if (empty($subTaskData)) {
			continue;
		}
		krsort($subTaskData);
		$errorCount = 0;
		foreach($subTaskData as $subTaskKey => $subTaskValue){//trying to find three consecutive error
			if (in_array($subTaskValue['status'], $historyStatus)) {
				continue;

			}elseif (in_array($subTaskValue['status'], array('error', 'netError')) && $retryErrors->checkErrorExists($subTaskValue['error'],'checkTriggerStatus')) {
				$errorCount++;
			}else{
				break;
			}

			$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$subTaskValue['historyID']
           				)
        			);
			if($errorCount == 15){
				$errorMsg = DB::getRow("?:history_additional_data", "error, errorMsg", $where);
				updateHistory(array('status' => 'error', 'error' => 'consecutiveError', 'recheck' => '1'), $value['historyID'], array('status' => 'error', 'error' => $errorMsg['error'], 'errorMsg' => $errorMsg['errorMsg']));
				break;
			}else{
				if($subTaskValue['recheck'] == 1){ continue; }
				
				$params['parentHistoryID'] = $value['historyID'];
				$actionID = uniqid('', true);
				Reg::set('currentRequest.actionID', $actionID);
				if (($value['type'] == 'staging' && $value['action'] == 'newSite') || ($value['type'] == 'installClone' && $value['action'] == 'newSite') ) {
					manageClientsInstallCloneCommon::triggerBridgeExtractMulticall($params, $value['siteID']);
				}elseif($subTaskValue['action'] == 'triggerBackupDownlaod' ){
					$where1 = array(
					      		'query' =>  "historyID = ':historyID'",
					      		'params' => array(
					      		   ':historyID' => $value['historyID']
			       				)
			    			);
					$historyData = DB::getRow("?:history", "*", $where1);
					$historyRawData = DB::getRow("?:history_raw_details", "panelRequest", $where1);
					$panelRequest = unserialize($historyRawData['panelRequest']);
					$params = $panelRequest['args']['params'];
					$siteID = $historyData['siteID'];
					$params['backupParentHID'] = $value['historyID'];
					$allParams = array('action' => 'triggerBackupDownlaod', 'args' => array('params' => $params, 'siteIDs' => array($siteID)));
					panelRequestManager::handler($allParams);
				}elseif($subTaskValue['action'] == 'bridgeExtractMulticallRestore' ){
					$where1 = array(
					      		'query' =>  "historyID = ':historyID'",
					      		'params' => array(
					      		   ':historyID' => $subTaskValue['historyID']
			       				)
			    			);
					$historyRawData = DB::getRow("?:history_raw_details", "request", $where1);
					$panelRequest = unserialize(base64_decode($historyRawData['request']));
					$params = $panelRequest['params']['responseData'];
					$params['parentHistoryID'] = $value['historyID'];
					manageClientsRestore::triggerBridgeExtractRestoreMulticall($params, 0);
				}else{
					if(empty($params['params'])){
						$where2 = array(
					      		'query' =>  "historyID = ':historyID'",
					      		'params' => array(
					      		   ':historyID' => $subTaskValue['historyID']
			       				)
			    			);
						$historyRawData = DB::getRow("?:history_raw_details", "request", $where2);
						$request = unserialize(base64_decode($historyRawData['request']));
						if(!empty($request['params']['params'])){
							$params['success'] = $request['params']['params'];
						}
					}
					manageClientsBackup::triggerRecheck($params, $value['siteID']);
				}
				DB::update("?:history", array('recheck' => 1), $where);
				break;
				//DB::update("?:history", array('recheck' => '1'), "historyID =".$value['historyID']);
			}
		}	
	}
}

function checkMulticalRetry(){
	$where = array(
			      		'query' =>  "recheck = 0 AND type IN('backup', 'scheduleBackup') AND status = ':status'",
			      		'params' => array(
			               ':status'=>'multiCallWaiting'
           				)
        			);
	$data = DB::getArray("?:history", "siteID, historyID, type, action", $where);

	foreach ($data as $key => $value) {
		if ($value['action'] == 'multiCallRestore' || $value['action'] == 'restoreNew' || $value['action'] == 'restoreBackupDownlaod' || $value['action'] == 'triggerBackupDownlaod' || $value['action'] == 'bridgeExtractMulticallRestore') {
			continue;
		}
		$where = array(
			      		'query' =>  "parentHistoryID = ':parentHistoryID' ORDER BY historyID DESC LIMIT 1",
			      		'params' => array(
			               ':parentHistoryID'=>$value['historyID']
           				)
        			);
		$subTaskData = DB::getArray("?:history", "historyID, status, recheck", $where);
		foreach($subTaskData as $subTaskKey => $subTaskValue){
			if($subTaskValue['status'] == 'completed'){
				$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$subTaskValue['historyID']
           				)
        			);
				if($subTaskValue['recheck'] == 1){ continue; }
				$params['parentHistoryID'] = $value['historyID'];
				$actionID = uniqid('', true);
				manageClientsBackup::triggerRecheck($params, $value['siteID']);
				DB::update("?:history", array('recheck' => 1), $where);
			}
		}

	}
}

function triggerPhoenixBackupFailedTask($historyID, $actionResponse, $curlErrorNo, $curlHttpCodex){
	$where = array(
			      		'query' =>  "historyID=':historyID' AND type IN('backup', 'scheduleBackup') AND parentHistoryID IS NULL AND status = ':status'",
			      		'params' => array(
			      			':historyID'=>$historyID,
			               ':status'=>'running'
           				)
        			);
	$siteID = DB::getField("?:history", "siteID", $where);

	if (!$siteID) {
		return false;
	}
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyID
					)
			);
	$parentHistoryRequest = DB::getField("?:history_raw_details", "request", $where);
	$parentHistoryRequest = unserialize(base64_decode($parentHistoryRequest));
	if ($parentHistoryRequest['params']['mechanism'] == 'advancedBackup') {
		updateHistory(array('status' => "multiCallWaiting",'param2'=>'triggerPhoenixBackupFailedTask'), $historyID);
		$params['success']['backup_id'] = $parentHistoryRequest['params']['backup_nounce'];
		$params['success']['parentHID'] = $historyID;
		manageClientsBackup::triggerRecheck($params, $siteID);
		return true;
	}
	return false;
}

function retriggerInitialMultical($historyID){
	$where = array(
	      		'query' =>  "historyID=':historyID'",
	      		'params' => array(
	               ':historyID'=>$historyID
					)
			);
	$parentHistoryRequest = DB::getField("?:history_raw_details", "request", $where);
	$parentHistoryRequest = unserialize(base64_decode($parentHistoryRequest));
	if ($parentHistoryRequest['params']['mechanism'] == 'singleCall') {
		return false;
	}
	$where = array(
			      		'query' =>  "historyID=':historyID' AND type IN('backup', 'scheduleBackup') AND parentHistoryID IS NULL AND status = ':status'",
			      		'params' => array(
			      			':historyID'=>$historyID,
			               ':status'=>'running'
           				)
        			);
	$retried = DB::getField("?:history", "retried", $where);

	if (!is_null($retried) && $retried < 3) {
		if (defined('IWP_IMMEDIATE_RETRY_MULTICAL_INITIAL_FAILURE') && IWP_IMMEDIATE_RETRY_MULTICAL_INITIAL_FAILURE) {
			updateHistory(array('status' => "pending", 'retried' => $retried+1), $historyID);
		}else{
			if ($retried == 0) {
				$timeScheduled = time()+60;
			}elseif ($retried == 1) {
				$timeScheduled = time()+300;
			}elseif ($retried == 2) {
				$timeScheduled = time()+600;
			}
			updateHistory(array('status' => "scheduled", 'retried' => $retried+1, 'timeScheduled' => $timeScheduled), $historyID);
		}

        	$where = array(
		      		'query' =>  "historyID=:historyID",
		      		'params' => array(
		               ':historyID'=>$historyID
						)
				);
			return DB::update("?:history_additional_data", array('status' => 'pending', 'errorMsg'=>NULL), $where);
	}

	return false;
}

function checkTriggerStuckBack(){
	$where = array(
			      		'query' =>  "recheck = 0 AND type IN('backup', 'scheduleBackup') AND status = ':status'",
			      		'params' => array(
			               ':status'=>'multiCallWaiting'
           				)
        			);
	$data = DB::getArray("?:history", "siteID, historyID, type, action", $where);
	foreach($data as $key => $value){
		if ($value['action'] == 'multiCallRestore' || $value['action'] == 'restoreNew' || $value['action'] == 'restoreBackupDownlaod' || $value['action'] == 'triggerBackupDownlaod' || $value['action'] == 'bridgeExtractMulticallRestore') {
				continue;
			}
		$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$value['historyID']
           				)
        			);
		$lastUpdate = DB::getField("?:history", 'param1', $where);
		if (!empty($lastUpdate)) {
			$lastUpdate = unserialize($lastUpdate);
			if ((time() - $lastUpdate['lastCallUpdate']) >= 300) {
				$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$lastUpdate['lastHistoryID']
           				)
        			);
				$params['parentHistoryID'] = $value['historyID'];
				$actionID = uniqid('', true);
				Reg::set('currentRequest.actionID', $actionID);
				manageClientsBackup::triggerRecheck($params, $value['siteID']);
				DB::update("?:history", array('recheck' => 1), $where);
			}
		}
	}
}

function isTaskRunningBySiteID($siteID, $type = NULL, $historyID = NULL){
	if (!$type) {
		$where = array(
			'query' => "siteID = ':siteID' AND status NOT IN ('completed', 'netError', 'error') GROUP BY actionID ORDER BY historyID DESC",
			'params' => array(
				':siteID'	=> $siteID,
				)
			);
	} else if ($type == 'backup') {
		$where = array(
			'query'		=> "siteID = :siteID AND ((type = 'backup' AND (action = 'now' OR action = 'multiCallNow')) OR (type = 'scheduleBackup' AND (action = 'runTask' OR action ='multiCallRunTask'))) AND status NOT IN ('completed', 'netError', 'error') GROUP BY actionID ORDER BY historyID DESC",
			'params' 	=> array(
				   ':siteID' => $siteID,
				)
			);
	}
	return DB::getField("?:history", "count(historyID)", $where);
 }

function checkBackupTasks(){
	$maxTime = time() - (60*60); //60 mins before. 
	$data = DB::getArray("?:history", "siteID,historyID,microtimeInitiated", "microtimeInitiated >= '".DB::esc($maxTime)."' AND recheck = 0 AND 
	(
		(type = 'backup' AND action = 'now') OR 
		(type = 'scheduleBackup' AND action = 'runTask') OR 
		(type = 'installClone' AND action = 'installCloneBackupNow')
	)
	AND 
	(
		(status = 'netError' AND error IN('28', '52', '500', '502', '504', 'timeoutClear')) OR
		(status = 'error' AND error IN('main_plugin_connection_error'))
	)
	"); // time and task == 'neterror', verifying check == 0 //28 => curl error: operation timeout, 52 => curl error: empty reply form server
	
	
	$checkTill = 35 * 60;//35 mins each 5 min interval
	if(!empty($data)){
		foreach($data as $key => $value){
			$siteIDs = array();
			
			$siteIDs[] = $value['siteID'];
			
			$balanceTime = $value['microtimeInitiated'] + $checkTill - time();
			
			$addTime = 0;
			do{								
				$actionID = uniqid('', true);
				Reg::set('currentRequest.actionID', $actionID);
				
				$params['timeScheduled'] = time() + $addTime;
				$params['status'] = 'scheduled';
				
				//$siteIDs = array($siteID);
				$extras  = array('sendAfterAllLoad' => false, 'doNotShowUser' => true);
				manageClientsFetch::getStatsProcessor($siteIDs, $params, $extras);
				$balanceTime -= 5*60;
				$addTime += 5*60;
			
			}
			while($balanceTime > 0);
			$where = array(
			      		'query' =>  "historyID = ':historyID'",
			      		'params' => array(
			               ':historyID'=>$value['historyID']
           				)
        			);
			DB::update("?:history", array('recheck' => '1'), $where);
			
		}
	}
	
	return;
}

function quote($str) {
	return sprintf('"%s"', $str);
}

function getRealSystemCronRunningFrequency($bothCheck = false, $onlyV3 = false, $onlyV2 = false){
	if ($bothCheck == true) {
		$cronRecentRunLogV3 = getOption('cronRecentRunLogV3');
		$cronRecentRunLog = getOption('cronRecentRunLog');
		$v3Result = calculateCronFrequency($cronRecentRunLogV3);
		$v2Result = calculateCronFrequency($cronRecentRunLog);
		if (($v2Result !=0 && $v2Result<$v3Result) || $v3Result ==0) {
			return $v2Result;
		}
		return $v3Result;
	}elseif ($onlyV2) {
		$cronRecentRunLog = getOption('cronRecentRunLog');
		return calculateCronFrequency($cronRecentRunLog);
	}elseif (defined('APP_V3') || $onlyV3) {
		$cronRecentRunLog = getOption('cronRecentRunLogV3');
		return calculateCronFrequency($cronRecentRunLog);
	}
	
	$cronRecentRunLog = getOption('cronRecentRunLog');
	return calculateCronFrequency($cronRecentRunLog);
	
	
}

function calculateCronFrequency($cronRecentRunLog){
	if(!empty($cronRecentRunLog)){
		$cronRecentRunLogs = unserialize($cronRecentRunLog);
		
		//filter last 90 mins log alone
		$lastNSecs = time() - (90*60);
		$temp = array();
		foreach($cronRecentRunLogs as $key => $value){
			if($value > $lastNSecs) array_push($temp, $value);
		}
		$cronRecentRunLogs = $temp;
		
		$cronRecentRunLogsCount = count($cronRecentRunLogs);
		if($cronRecentRunLogsCount >= 2){
			$tempArray = array();
			$cronRecentRunLogs = array_reverse($cronRecentRunLogs, true); //to take the diff from the last value.
			$lastValue = NULL;
			$i = 0;
			foreach($cronRecentRunLogs as $key => $value){
				if(!empty($lastValue)) $tempArray[] = $lastValue - $value;
				$lastValue = $value;
				$i++;
				if($i >= 5){
					break;
				}
			}
			
			$avgFrequency = array_sum($tempArray)/count($tempArray);
			$avgFrequency = floor($avgFrequency / 60);
			if($avgFrequency == 0) $avgFrequency = 1;
			
			return $avgFrequency;
		}
		elseif($cronRecentRunLogsCount == 1){
			return 20;
		}
		
	}
	return 0;
}

function getSystemCronRunningFrequency($bothCheck = false){
	$freq = getRealSystemCronRunningFrequency($bothCheck);
	if($freq > 0 && $freq <= 6){//5 min system cron
		return 5;
	}elseif($freq > 6 && $freq < 20){
		return 20;
	}elseif ($freq > 20) {
		return $freq;
	}
	return 0;
}

/*
*
* use this functinon in cron.php, to identify the cron mode.
*
*/
function cronCheck(){
	
	if($_GET['type'] == 'manage'){//easyCron triggered
		
		define('CRON_MODE', 'easyCronManage');
		$getNextTaskScheduleTime = getNextTaskScheduleTime();
		if(!empty($getNextTaskScheduleTime) && $getNextTaskScheduleTime < (time() + 30*60) || isAnyActiveOrPendingJobs()){//if manageCron trigger at 00:00. say a cron task scheduled at 00:10, it will be accepted by this if which checks less then 00:30, cronTask which will disable it self, it will keep triggering for every minutue even it doesnt have any task to execute
			
			
			// Avoid retriggering taskCron if already task cron running state.
			if(manageEasyCron::isTaskCronScheduledTimeExpired()){
				$result = manageEasyCron::taskCronEnable();
				if($result['status'] == 'error'){
					 addNotification($type='E', $title='Easy Cron API Error', $result['error']['message'], $state='U');	
				}
			}
		}
		die();
	}
	elseif($_GET['type'] == 'task'){//easyCron triggered
		define('CRON_MODE', 'easyCronTask');
		define('CRON_TIMEOUT', 30);
	}elseif($_GET['type'] === 'IWP_CRON'){
            $mode = $_GET['mode'];
            Manage_IWP_Cron::handleCronReq($mode);
        }else{
		$freq = getSystemCronRunningFrequency();
		if($freq == 5){//5 min system cron
			define('CRON_MODE', 'systemCronShortTime');
			define('CRON_TIMEOUT', 310);
		}else{//should be 20 min system cron
			define('CRON_MODE', 'systemCronDefault');
			define('CRON_TIMEOUT', 1210);
		}
	}
		
}


function getNextTaskScheduleTime(){
	$nextSchedule = array();
	
	$nextUpdateNotifyTime = updatesNotificationMailRunCheck(true);
	$nextSchedule[] = ($nextUpdateNotifyTime > 0 ? $nextUpdateNotifyTime : $nextSchedule);
	
	setHook('getNextSchedule', $nextSchedule);
	
	//Assuming all values in array are integers and time.
	if(!empty($nextSchedule)){
		return min($nextSchedule);
        }else{
		return false;	
        }
}

function isAnyActiveOrPendingJobs(){
	$where = array(
			      		'query' =>  "(H.status IN ('initiated', 'running', 'pending', 'multiCallWaiting','processingResponse')  OR (H.status = ':status' AND H.timescheduled <= ".time()." AND H.timescheduled > 0))",
			      		'params' => array(
			               ':status'=>'scheduled'
           				)
        			);
	 return DB::getExists("?:history H", "H.historyID", $where);
	
}

function getMinimumScheduledTaskTime(){
	
	 	$currentTime = time();
		$where = array(
			      		'query' =>  "(H.status = ':status' AND H.timescheduled >= ':timescheduled' AND H.timescheduled > 0)",
			      		'params' => array(
			               ':status'=>'scheduled',
			               ':timescheduled' =>$currentTime
           				)
        			);

		$timeScheduled = DB::getField("?:history H", "MIN(H.timeScheduled)", $where);
		if(empty($timeScheduled)){
			return false;
		}
		
		$timeDifference = (($timeScheduled - $currentTime)/60);   //3600/60 = 60min
		if($timeDifference > 1){
			return intval($timeDifference);
		}elseif($timeDifference <= 1){
			return 1;
		}
}

function needFreshCall($secondsPassed=3){
	if(defined('CRON_MODE') && CRON_MODE == 'easyCronTask'){
		if( (microtime(true) - $GLOBALS['cronStartTime']) > $secondsPassed ){
			exit();
		}
	}
}

function showBrowserCloseWarning(){
	$where = array(
		'query' =>  "(H.status = ':status' AND H.action = 'installCloneBackupNow' AND H.type = 'staging') OR (H.status = ':status' AND H.action = 'installCloneBackupNow' AND H.type = 'installClone') OR (H.status = ':status')",
		'params' => array(
			':status'=>'multiCallWaiting'
		)
	);
	$MultiCallJobActiveType = DB::getField("?:history H", "H.type", $where);
	if($MultiCallJobActiveType == 'staging'){
		return 'staging';
	} else if($MultiCallJobActiveType == 'installClone'){
		return 'installClone';
	} else if($MultiCallJobActiveType == 'backup'){
		if(!manageEasyCron::isActive()){
			return 'backup';
		}
	}

	return false;
}

function setMultiCallOptions(&$requestParams)
{
	//set the multicall options from config.php if available else set the default values
	$isEnableMulticalOption = getOption('isEnableMulticalOption');
	
	if(!defined('MULTICALL_ZIP_SPLIT_SIZE'))
	{
		if (!empty($isEnableMulticalOption)) {
			$requestParams['args']['zip_split_size'] = 256;	//MB
		}else{
			$requestParams['args']['zip_split_size'] = 400;	//MB
		}
	}
	else
	{
		$requestParams['args']['zip_split_size'] = MULTICALL_ZIP_SPLIT_SIZE;
	}
	if(!defined('MULTICALL_FILE_BLOCK_SIZE'))
	{
		$requestParams['args']['file_block_size'] = 5;
	}
	else
	{
		$requestParams['args']['file_block_size'] = MULTICALL_FILE_BLOCK_SIZE;
	}
	if(!defined('MULTICALL_LOOP_BREAK_TIME'))
	{
		if (!empty($isEnableMulticalOption)) {
			$breakTime = 9;	//MB
		}else{
			$breakTime = 15;	//MB
		}
		$requestParams['args']['file_loop_break_time'] = $breakTime;
		$requestParams['args']['db_loop_break_time'] = $breakTime;
		if(!empty($requestParams['secure']['account_info']))
		{
			$requestParams['secure']['account_info']['upload_loop_break_time'] = $breakTime;
		}
	}
	else
	{
		$requestParams['args']['file_loop_break_time'] = MULTICALL_LOOP_BREAK_TIME;
		$requestParams['args']['db_loop_break_time'] = MULTICALL_LOOP_BREAK_TIME;
		if(!empty($requestParams['secure']['account_info']))
		{
			$requestParams['secure']['account_info']['upload_loop_break_time'] = MULTICALL_LOOP_BREAK_TIME;
		}
	}
	if(!empty($requestParams['secure']['account_info']))
	{
		if(!defined('MULTICALL_UPLOAD_BLOCK_SIZE'))
		{
			$requestParams['secure']['account_info']['upload_file_block_size'] = 5;
		}
		else
		{
			$requestParams['secure']['account_info']['upload_file_block_size'] = MULTICALL_UPLOAD_BLOCK_SIZE;
		}
	}

	if (defined('DISABLE_IWP_CLOUD_VERIFICATION') && DISABLE_IWP_CLOUD_VERIFICATION) {
		$requestParams['args']['disable_iwp_cloud_verification'] = true;
	}
	
}


function dispatchMark($data){
	$notif_count = 0;
	$notif_count_offer = 0;
	//refresh the notify count 
	if(!getOption("notifyCenterRead")){
		$notifyCenterRead = array();
	}
	else{
		$notifyCenterRead = unserialize(getOption("notifyCenterRead"));
	}
	
	if(isset($data['notifyCenter'])){
		updateOption("markNotifyCenter", serialize($data['notifyCenter']));
		$notif_count = count($data['notifyCenter']);
		foreach($data['notifyCenter'] as $ID => $notifyDetail){
			if(array_key_exists($ID, $notifyCenterRead)){
				$notif_count -= 1;
			}
		}
		
	}
	
	if(isset($data['notifyOffer']) && !isset($data['notifyOffer']['error'])){
		updateOption("markNotifyOffer", serialize($data['notifyOffer']));
		$notif_count_offer = count($data['notifyOffer']);
		if(!empty($notif_count_offer)){
			$notif_count_offer = 1;
		}
	}
	else{
		updateOption("markNotifyOffer", '');			//clearing old notification offer
	}
	
	if(isset($data['bottomLines'])){
		updateOption("markBottomLines", jsonEncoder($data['bottomLines']));
	}
	else{
		updateOption("markBottomLines", '');
	}
	
	//update the count
	updateOption("notifCount", $notif_count + $notif_count_offer);

}

function processQueueTweak(&$data, $category, $type){
	if ($category === 'staging' && $type === 'content') {
		if($data['name'] === "newSite" || $data['name'] === "existingSite") {
			$data['action']= 'newSite';
		}else if ($data['detailedAction'] === 'plugin' || $data['detailedAction'] === 'theme' || $data['detailedAction'] === 'core'){
			$data['type']= 'PTC';
			$data['action'] = 'update';
		} else if($data['name'] === 'clientPluginBranding'){
			$data['type']= 'clientPluginBranding';
			$data['action'] = 'change';
		} else if($data['detailedAction'] === 'readd'){
			$data['type'] = 'site';
			$data['action'] = 'readd';
			$data['isStage'] = 'staging';
		} else if($data['detailedAction'] === 'add'){
			$data['type'] = 'site';
			$data['action'] = 'add';
			$data['isStage'] = 'staging';
		}
	} else if ($category === 'staging' && $type === 'title'){
			if ($data['type'] === 'staging' && $data['action'] !== 'deleteSite'){
				return 'Staging for 1 site';
			}elseif ($data['type'] === 'stagingToLive') {
				return 'Staging to live for 1 site';
			} else {
				return false;
			}
	}
}

function stagingTweakInProcessQueue(&$data){
	if ($data['type'] != 'staging') {
		return false;
	}
	foreach ($data['detailedStatus'] as $key => $task) {
		if($task['detailedAction'] == 'add' || $task['detailedAction'] == 'readd'){
			$status = $task['status'];
			$data['statusSummary']['total'] -= 1;
			$data['statusSummary'][$status] -=  1;
			unset($data['detailedStatus'][$key]);
			unset($data['detailedActions']['add']);
			unset($data['detailedActions']['readd']);
		}
	}
}

function getParentHistoryID($historyID){
	return DB::getField("?:history", "parentHistoryID" , "historyID = ".$historyID);
}

function getActionIDByHistoryID($historyID){
	return DB::getField("?:history", "actionID", "historyID = ".$historyID);
}

function isConfigWritable(){
	if (is_writable(APP_ROOT.'/config.php')) {
		return 1;
	}
	else{
		return 0;
	}
}
function isFTPDefinedConfig(){
	if(defined('APP_FTP_HOST') || defined('APP_FTP_PORT') || defined('APP_FTP_BASE') || defined('APP_FTP_USER') || defined('APP_FTP_PASS') || defined('APP_FTP_SSL') || defined('APP_FTP_USE_SFTP')){
		return 1;
	}
	return 0;
}

function isShowBetaWelcome(){
		return getOption('showBetaWelcome');
}
function isShowReSchedulePopup(){
		$isShow = getOption('showReSchedulePopup');
		if ($isShow) {
			$activeAddons = DB::getField("?:addons", "addon", "slug='scheduleBackup' AND status='active'");
			if($activeAddons){
				$emptySchedule = DB::getField("?:backup_schedules", 'scheduleID', "nextSchedule=0");
				if ($emptySchedule) {
					DB::update("?:backup_schedules",  array('paused' => 1), "nextSchedule=0");
					return true;
				}
			}
		}
		return false;
}

function getValidTill($addon=array()) {
	$extra_info = $class = '';
	if(time()-$addon['validityExpires']>=604800) { // greater than or equal to 7 days after expiry
		$class = "gp_over"; 
	} else if($addon['validityExpires']-time()>0 && $addon['validityExpires']-time()<5184000) { // between 60 days before expiry
		$class = "";
	} else if($addon['validityExpires']-time()>0 && $addon['validityExpires']-time()<604800) { // between 7 days before expiry
		$class = "in_gp"; 
	} else if(time()-$addon['validityExpires']>0 && time()-$addon['validityExpires']<604800) { // between 7 days after expiry
		$class = "in_gp"; 
		$checkTime7days = 604800-(time()-$addon['validityExpires']);

		if($checkTime7days>518400 && $checkTime7days<604800) {
			$extra_info = 'Extended to 7 days';
		} else {
			$calcDays = floor(($checkTime7days%2592000)/86400);
			
			if($calcDays==1) $dayPlural="";
			else $dayPlural="s";
			if($calcDays==0) {
				$extra_info = 'Valid till today';
			} else {
				$extra_info = 'Valid till '.$calcDays.' day'.$dayPlural;
			}
		}				
	} else if(time()-$addon['validityExpires']<0 && time()-$addon['validityExpires']>=-2592000) {
		$calcDays = (floor((((time()-$addon['validityExpires']))%2592000)/86400)*-1);
		if($calcDays==1) $dayPlural="";
		else $dayPlural="s";
		$extra_info = 'Expires in '.$calcDays.' day'.$dayPlural;
	}
	$return = array(
		'class'=>$class,
		'extra_info'=>$extra_info
	);
	return($return);
}
function addLoginLog($loginEmail, $loginAuthType = '', $loginAttemptStatus = '', $error = '', $loginRedirect = '',$HeaderInfo = ''){
	$loginTime = time();
	$browserInfo = getBrowser();
	$browser = $browserInfo['name'].' '.$browserInfo['version'];
	$loginIP = isset($_SERVER['HTTP_X_FORWARDED_FOR']) ? $_SERVER['HTTP_X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];
	$protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "HTTPS" : "HTTP";
	$loginAttemptFailedCount = getOption('loginAttemptFailedCount');
	$browserAgent = $browserInfo['userAgent'];
	if ($error == 'Invalid credentials.') {
		$loginAttemptFailedCount = !empty($loginAttemptFailedCount)?$loginAttemptFailedCount + 1:1;
		updateOption('loginAttemptFailedCount',$loginAttemptFailedCount);	
	}
	$where = array(
      		'query' =>  "email=':email'",
      		'params' => array(
               ':email'=>trim($loginEmail)
				)
		);
	$userDetails = DB::getRow("?:users", "userID, accessLevel", $where);

	if(!empty($loginEmail)){
		$isUserExists = !empty($userDetails["userID"]) ? true : false;
		if ($isUserExists) {
			$ID = DB::insert('?:login_logs',array('userID' => $userDetails['userID'], 'email' => $loginEmail,'accessLevel' => $userDetails['accessLevel'], 'time' =>$loginTime, 'browserInfo' =>$browser, 'loginAuthType' =>$loginAuthType, 'IP' =>$loginIP, 'error' => $error, 'loginAttemptStatus' => $loginAttemptStatus, 'protocol' => $protocol, 'loginRedirect' => $loginRedirect, 'browser' => $browserAgent));
		}	
		else{
			$ID = DB::insert('?:login_logs',array('email' => $loginEmail, 'time' =>$loginTime, 'browserInfo' =>$browser, 'loginAuthType' =>$loginAuthType, 'IP' =>$loginIP, 'error' => $error, 'loginAttemptStatus' => $loginAttemptStatus, 'protocol' => $protocol, 'loginRedirect' => $loginRedirect, 'browser' => $browserAgent));
		}
	
	}
	
	if ($loginAttemptStatus == 'success') {
		$loginAttemptFailedCount = 0;
		updateOption('loginAttemptFailedCount', 0);
		updateOption('loginSecurityMailDetails', 0);
	}
	if ($loginAttemptFailedCount >= 3) {
		checkAndSendLoginSecurityMail($loginIP, $userDetails["userID"], $browser, $ID);
	}
}

function checkAndSendLoginSecurityMail($loginIP, $userID, $browser,$ID){
	$loginSecurityMailDetails = unserialize(getOption('loginSecurityMailDetails'));
	$time = time()+60*60;
	$isIPPresent = 0;
	$isMailSend = 0;
	$temp = doCall("http://ipinfo.io/{$loginIP}/json", '', $timeout=30);
	list($locationDetails, , , $curlInfo) = $temp;
	$mailParams = array('loginDetails' => array('time' => time(),'loginIP' => $loginIP, 'locationDetails' =>$locationDetails, 'browserInfo'=> $browser), 'userID' => $userID);

	if (empty($loginSecurityMailDetails)) {
		$loginSecurityMailDetails = array(0 =>array('loginIP' =>$loginIP , 'nextMailSendTime' => $time));
		$isMailSend = sendLoginSecurityMail($mailParams, $userID);
		
	}
	else{
			foreach ($loginSecurityMailDetails as $key => $details) {
				if($loginIP == $details['loginIP'] ){
					$isIPPresent = 1;
					if(time() >= $details['nextMailSendTime']){
						$isMailSend = sendLoginSecurityMail($mailParams, $userID);
						$loginSecurityMailDetails[$key]['nextMailSendTime'] = $time;
					}
				}
			}
	}
	if ($isIPPresent == 0 && !$isMailSend ) {
		$isMailSend = sendLoginSecurityMail($mailParams, $userID);
		$loginSecurityMailDetails = array_merge($loginSecurityMailDetails,array(array('loginIP' =>$loginIP , 'nextMailSendTime' => $time)));
	}
		
	if ($isMailSend) {
		if(empty($locationDetails['city'])){
			addNotification($type='W', $title='FAILED LOGIN ATTEMPTS', $message='Someone tried to login to your InfiniteWP admin panel with incorrect credentials 3 times recently.<br><br>Time of first attempt:'.date('M d, Y @ h:ia', time()).'<br>IP:'.$loginIP.'<br>Browser: '.$browser.'<br><br>If the information above looks familiar, you can disregard this.<br> If you have not recently not tried to login to your panel, someone may be trying to.<br><br>To secure your admin panel, go to Settings ? Security. <a id="view_login_detail" loginID='.$ID.'>View more details</a>', $state='U', $callbackOnClose='', $callbackReference='');
		}else{ 
			addNotification($type='W', $title='FAILED LOGIN ATTEMPTS', $message='Someone tried to login to your InfiniteWP admin panel with incorrect credentials 3 times recently.<br><br>Time of first attempt:'.date('M d, Y @ h:ia', time()).'<br>IP:'.$loginIP.'<br>Location: '.$locationDetails['city'].', '.$locationDetails['country'].'.<br>Browser: '.$browser.'<br><br>If the information above looks familiar, you can disregard this.<br> If you have not recently not tried to login to your panel, someone may be trying to.<br><br>To secure your admin panel, go to Settings ? Security.<a id="view_login_detail" loginID='.$ID.'>View more details</a>', $state='U', $callbackOnClose='', $callbackReference='');
		}
		updateOption('loginSecurityMailDetails', serialize($loginSecurityMailDetails));
	}

}

function sendLoginSecurityMail($mailParams, $userID){
	$adminUserID = DB::getField("?:users", "userID", "accessLevel = 'admin' AND status = 1 ORDER BY userID ASC LIMIT 1");
	if($adminUserID == $userID || empty($userID)){
		$mailParams['userID'] = $adminUserID;
		$isMailSent = sendAppMail($mailParams, '/templates/email/loginFailedAttemptNotification.tpl.php');
	}
	else{
		$isMailSent = sendAppMail($mailParams, '/templates/email/loginFailedAttemptNotification.tpl.php');
		$mailParams['userID'] = $adminUserID;
		$isMailSent = sendAppMail($mailParams, '/templates/email/loginFailedAttemptNotification.tpl.php');
	}

	return $isMailSent;
}
function loginLogHistoryViewBeautifier($value){
	switch ($value) {
		case 'email':
			return 'Email';
		case 'browserInfo':
			return 'Browser';
		case 'loginAuthType':
			return 'Login type';
		case 'IP':
			return 'Logged IP';
		case 'error':
			return 'Error message';
		case 'loginAttemptStatus':
			return 'Login attempt status';
		case 'protocol':
			return 'Protocol';
		case 'accessLevel':
			return 'Access level';
		case 'loginRedirect':
			return 'Login redirect';
	}
}
function addURLHeader($params){
	return '__URL_PREFIX__'.$params['folderPath'].$params['fileName'];
}

function replaceURLHeader($URL){
	$headerPosV3 = strpos($URL, '__URL_PREFIX__V3');
	if($headerPosV3 !== false){
		return str_replace('__URL_PREFIX__V3', APP_FULL_URL_V3, $URL);
	}
	$headerPos = strpos($URL, '__URL_PREFIX__');
	if($headerPos !== false){
		return str_replace('__URL_PREFIX__', APP_FULL_URL, $URL);
	}
	return $URL;
}

function copyUploadsToFavoritesFolder(&$params){
	$favoritesPath = 'uploads/favorites/';
	$fullFavoritesPath = APP_ROOT.'/'.$favoritesPath;
	$currentPath = APP_ROOT.'/'.$params['folderPath'].''.$params['fileName'];
	$newPath = APP_ROOT.'/'.$favoritesPath.''.$params['fileName'];
	if (!file_exists($fullFavoritesPath)) {
		mkdir($fullFavoritesPath);
	}
	if (!copy($currentPath, $newPath)) {
		return false;
	}
	$params['folderPath'] = $favoritesPath;
	if (isV3Panel()) {
		$params['URL'] = addURLHeaderV3($params);
	}else{
		$params['URL'] = addURLHeader($params);
	}
}

function getSuperAdminDetails(){
	$where = "accessLevel = 'admin' AND status = '1' ORDER BY userID ASC LIMIT 1";
	return DB::getArray("?:users", "*", $where);
}

function isClientReportingInstalled() {
	
	$where = array(
					'query' =>  "slug = ':slug'",
					'params' => array(
					   ':slug'=> 'clientReporting'
					)
				);
	$isExist = DB::getField("?:addons", "slug", $where);
	if(!$isExist){
		$isExist = DB::getField("?:addons_v3", "slug", $where);
		return $isExist ? true : false;
	}else{
		return $isExist ? true : false;
	}
}

function isSaveActivityLogInClient(){
	return isClientReportingInstalled();
}

function isFailedBackup($backupData){
	if ($backupData['what'] === NULL && $backupData['time'] === NULL && $backupData['downloadURL'] === NULL && $backupData['size'] === NULL) {
		return true;
	}
	return false;
}

function createHTMLCacheAfterUpdate(){
	if (function_exists('loadActiveAddons')) {
		loadActiveAddons();
	}
	if (function_exists('getAddonsHTMLHead')) {
		getAddonsHTMLHead();
	}
}

function printGroupsForReloaData(){
	$groupDetails =  panelRequestManager::getGroupsSites();
	$content = '';
	if (empty($groupDetails)) {
		$content = '<li class ="l2"><a style = "font-style: italic;color: #aaaaaa;">No groups</a></li>';
	} else {
		foreach ($groupDetails as $key => $group) {
			if (!empty($group['siteIDs'])) {
				$content = $content .'<li class ="l2 groupReloadStats" groupID = '.$group['groupID'].' ><a>'.$group['name'].'</a></li>';
			}else{
				$content = $content.'<li class ="l2 disabled emptyGroups" groupID = '.$group['groupID'].' ><a style = "font-style: italic;color: #aaaaaa;">'.$group['name'].'</a></li>';
			}
		} 
	}
	return $content;
}

function multiUserGetSitesStatsCount($view, $args, $keysSearch=''){
	$wheregroups = '';
	if ( $view != 'sites' && $view != 'hiddenUpdates' && userStatus() == "admin") {
		$where = array(
					'query' =>  "type = ':type' AND URL != '' AND updatePresentCount NOT IN ('0') ".$keysSearch,
					'params' => array(
								':type'=>$view
								)
				);
		$total = DB::getFields("?:update_stats", "ID", $where);
		$total = count($total);
		return $total;
	} elseif($view != 'sites' && $view != 'hiddenUpdates'){
		$IDs = multiUserGetPTTCIDs($view, $keysSearch);
		return count($IDs);
	}elseif ($view == 'hiddenUpdates') {
		if (!empty($args['groupID']) && $args['groupID'] !='null' && $args['groupID'] !=0 && $args != '1') {
			$groupDetails = panelRequestManager::getSitesByGroupID($args);
			$siteIDs = $groupDetails['siteIDs'];
			if (!empty($siteIDs)) {
				$sites = implode(', ', $siteIDs);
				$wheregroups = "AND S.siteID IN (". implode(', ', DB::esc($siteIDs)) .")";
			}else{
				return false;
			}
		}
		if(userStatus() != "admin"){ 
			$where = array(
					'query' =>  "UA.userID = ':userID' AND HL.siteID = UA.siteID AND S.siteID = UA.siteID ".$wheregroups.$keysSearch." GROUP BY HL.siteID ",
					'params' => array(
								':userID'=>$GLOBALS['userID'],
								)
				);
			$total = DB::getFields('?:user_access UA, ?:hide_list HL, ?:sites S', 'UA.siteID', $where);
		} else{
			$total = DB::getFields('?:hide_list HL, ?:sites S', 'HL.siteID', "S.siteID = HL.siteID ".$wheregroups.$keysSearch." GROUP BY HL.siteID ");
		}
		
		$total = count($total);
		return $total;
	}
	if (!empty($args['groupID']) && $args['groupID'] !='null' && $args['groupID'] !=0 && $args != '1') {
		$groupDetails = panelRequestManager::getSitesByGroupID($args);
		$siteIDs = $groupDetails['siteIDs'];
		if (empty($siteIDs)) {
			return false;
		}
		return count($siteIDs);
	}
	if(userStatus() != "admin"){
		$whereClause = manageUpdates::generateWhereConditionByView($view,'SS.');
		$userID = $GLOBALS['userID'];
		$where2 = array(
					'query' =>  "UA.userID = ':userID' AND SS.siteID = UA.siteID AND S.siteID = UA.siteID ".$wheregroups." AND (".$whereClause.")".$keysSearch,
					'params' => array(
						':userID' => $userID
					)
		);
		$total = DB::getField("?:user_access UA, ?:site_stats SS, ?:sites S", "count(SS.siteID)", $where2, "siteID");
	} else{
		$whereClause = manageUpdates::generateWhereConditionByView($view, 'SS.');
		$total = DB::getFields("?:site_stats SS , ?:sites S", "SS.siteID", "S.siteID = SS.siteID AND S.type = 'normal' AND (".$whereClause.") ".$keysSearch);
		$total = count($total);

	}

	return $total;
}

function multiUserGetPaginatedStats($limitSQL, $view, $keysSearch='', $args=null){
	if ($view != 'sites' && $view != 'hiddenUpdates'  && userStatus() == "admin") {
		$where = array(
					'query' =>  "type = ':type' AND URL != '' AND updatePresentCount NOT IN ('0') ".$keysSearch." ORDER BY name ".$limitSQL,
					'params' => array(
								':type'=>$view
								)
				);
		$sitesStats = DB::getArray('?:update_stats', '*', $where,'URL');
		return $sitesStats;
	} elseif ($view != 'sites' && $view != 'hiddenUpdates') {
		$IDs = multiUserGetPTTCIDs($view);
		$where = array(
					'query' =>  "ID  IN (:ID)".$keysSearch." ORDER BY name ".$limitSQL,
					'params' => array(
								':ID'=>implode(', ', $IDs)	
								)
				);
		$sitesStats = DB::getArray('?:update_stats', '*', $where,'URL');
	} elseif ($view == 'hiddenUpdates'){
		$wheregroups = '';
		if (!empty($args['groupID']) && $args['groupID'] !='null' && $args['groupID'] !=0 && $args != '1') {
			$groupDetails = panelRequestManager::getSitesByGroupID($args);
			$siteIDs = $groupDetails['siteIDs'];
			if (!empty($siteIDs)) {
				$sites = implode(', ', $siteIDs);
				$wheregroups = "AND S.siteID IN ('". implode("','", DB::esc($siteIDs)) ."')";
			}else{
				return false;
			}
		}

		if(userStatus() != "admin"){ 
			$where = array(
					'query' =>  "UA.userID = ':userID' AND HL.siteID = UA.siteID AND S.siteID = UA.siteID ".$wheregroups.$keysSearch." GROUP BY HL.siteID ".$limitSQL,
					'params' => array(
								':userID'=>$GLOBALS['userID'],
								)
				);
			$siteIDs = DB::getFields('?:user_access UA, ?:hide_list HL, ?:sites S', 'UA.siteID', $where);
		} else{
			$siteIDs = DB::getFields('?:hide_list HL, ?:sites S', 'HL.siteID', "S.siteID = HL.siteID ".$wheregroups.$keysSearch." GROUP BY HL.siteID ".$limitSQL);
		}
		return $siteIDs;
	}

	$whereClause = manageUpdates::generateWhereConditionByView($view,'SS.');
	$wheregroups = '';
	if (!empty($args['groupID']) && $args['groupID'] !='null' && $args != '1') {
		$groupDetails = panelRequestManager::getSitesByGroupID($args);
		$siteIDs = $groupDetails['siteIDs'];
		if (!empty($siteIDs)) {
			$sites = implode(', ', $siteIDs);
			$wheregroups = "AND S.siteID IN ('". implode("','", DB::esc($siteIDs)) ."')";
		}else{
			return false;
		}
	}
	if(userStatus() != "admin"){
		$userID = $GLOBALS['userID'];
		$where = array(
					'query' =>  "UA.userID = ':userID' AND SS.siteID = UA.siteID AND S.siteID = UA.siteID ".$wheregroups." AND (".$whereClause.") ".$keysSearch." ORDER BY S.name ".$limitSQL,
					'params' => array(
						':userID' => $userID
					)
			);
		if ($view == 'sites') {
			$sitesStats = DB::getArray("?:user_access UA, ?:site_stats SS, ?:sites S", "SS.*, UA.siteID", $where, "siteID");
		} 
	} else{
		if ($view == 'sites') {
			$sitesStats = DB::getArray("?:site_stats SS, ?:sites S", "SS.*", "S.siteID = SS.siteID AND S.type = 'normal' ".$wheregroups." AND (".$whereClause.") ".$keysSearch." ORDER BY S.name ".$limitSQL, "siteID");
		} 
	}

	return $sitesStats;
}

function multiUserGetPTTCIDs($view, $keysSearch=''){
	if (userStatus() == "admin") {
		$where = array(
					'query' =>  "type = ':type'".$keysSearch,
					'params' => array(
								':type'=>$view
								)
				);
		$IDs = DB::getFields("?:update_stats", "ID", $where);
		return $IDs;
	}

	$arrayView = array('theme' => 'T', 'plugin' => 'P', 'core' => 'C', 'translation' => 'R');
	$requiredIDs = array();
	$where = array(
					'query' =>  "userID = ':userID'",
					'params' => array(
								':userID'=>$GLOBALS['userID'],
								)
				);
	$siteIDs = DB::getFields('?:user_access', 'siteID', $where);
	$where = array(
					'query' =>  "siteID IN (:siteID)",
					'params' => array(
								':siteID'=>implode(', ', $siteIDs),
								)
				);	
	$updateInfos = DB::getFields('?:site_stats', 'updateInfo', $where);
	foreach ($updateInfos as $key => $updateInfo) {
		$formatedPattern = manageUpdates::formatPattern($updateInfo);
		if (!empty($formatedPattern[$arrayView[$view]])) {
			$requiredIDs = array_merge($requiredIDs, $formatedPattern[$arrayView[$view]]);
		}
	}
	$requiredIDs = array_unique($requiredIDs);
	return $requiredIDs;
}

function autoConnectionMethodRetry(){
    $connectionMethod = getOption('connectionMethod');
    if($connectionMethod=='auto'){
        $where = array(
            'query' =>  "status = ':status' AND (microtimeInitiated + 10) < :intiateTimeLimit",
            'params' => array(
                ':status'=>'initiated',
                ':intiateTimeLimit' => time()
                )
            );
		$runningFailed = DB::getArray('?:history', 'historyID, connection_method, timeout', $where);
        if(!empty($runningFailed) && sizeof($runningFailed)>0){
            $settings = getOption('upperConnectionLevel');
            $retryMode = false;
            foreach($runningFailed as $history){
                $suggestedConnection = retryConnectionMethod($history);
                
                if($suggestedConnection!=$settings && $suggestedConnection=='socketMode'){
                    updateOption('upperConnectionLevel', 'socketMode');
                    $settings = 'socketMode';
                    $retryMode = true;
                } else if($suggestedConnection!=$settings && $suggestedConnection=='curlMode'){
                    updateOption('upperConnectionLevel', 'curlMode');
                    Reg::set('settings.executeUsingBrowser', true);
                    $settings = 'curlMode';
                    $retryMode = true;
                } else if($suggestedConnection!=''){
                    $retry = true;
                }
                
                if($retry){
                    reInitiateHistory($history['historyID'], $history['timeout']);
                }
            }
        }
    }
}

function retryConnectionMethod($history){
    $connectionData = ($history['connection_method']!='')?unserialize($history['connection_method']):array();
    if(isset($connectionData['mode'])){
        return downUpperConnectionLevel($connectionData['mode']);
    }
}

function reInitiateHistory($historyID, $timeout){
    $where = array(
        'query' =>   "status = 'initiated' AND historyID = :historyID",
        'params' => array(
            ':status'=>'initiated',
            ':historyID'=>$historyID
        )
    );
    $updateRequest = array(
        'status'=>'pending',
        'timeout'=>$timeout+35,
        'param2' => 'reInitiateHistory'
    );
    $isUpdated = DB::update("?:history", $updateRequest, $where);
}

function getBackupURL($params){
	$bkfile = array();
	foreach ($params as $key => $value) {
		if (($key =='plugins' || $key == 'themes' || $key == 'others' || $key == 'more' || $key == 'uploads') && !empty($value)) {
			$bkfile = array_merge($bkfile, $value);
		}elseif ($key == 'db') {
			$bkfile[] = $value;
		}
	}
	return $bkfile;
}

function resetStatusTables(){
	$Q1 = DB::doQuery("TRUNCATE TABLE  `?:site_stats`");
	$Q2 = DB::doQuery("TRUNCATE TABLE  `?:update_stats`");
	$Q3 = true;
	if (isV3Panel()) {
		$Q3 = DB::doQuery("TRUNCATE TABLE  `?:additional_stats`");
	}
	if ($Q1 && $Q2 && $Q3) {
		return true;
	}
	return false;
}

function backup_time_nonce($nonce = false) {
 	$nonce = substr(md5(time().rand()), 20);
 	return $nonce;
}

function getSizeOfBackup($data, $f, $backup){
	$size = 0;
	if (empty($data)) {
		return $size;
	}
	$count = count($data);
	foreach ($data as $key => $value) {
		$flag = $f;
		$flag = $key?$flag.$key.'-size':$flag.'-size';
		$size+=$backup[$flag];
	}
	return $size;
}

function retryTaskBasedOnErrorCode($historyID){
	$historyData = getHistory($historyID);
	if ($historyData['type'] == 'backup' && !empty($historyData['parentHistoryID'])) {
		$parentHistoryData = getHistory($historyData['parentHistoryID']);
		$where = array(
		      		'query' =>  "actionID=':actionID'",
		      		'params' => array(
		               ':actionID'=>$parentHistoryData['actionID']
						)
				);
		$historyIDs = DB::getFields("?:history", 'historyID', $where);
		if (empty($historyIDs)) {
			return false;
		}
		foreach ($historyIDs as $key => $hisID) {
			$result = updateMulticalRequest($hisID);
			if ($result && $historyData['parentHistoryID'] == $hisID) {
				if ($parentHistoryData['retried'] >=4) {
					return false;
				}
				panelRequestManager::manualRetryFailedTask($hisID);
			}
		}
		return true;
	}
}

function updateMulticalRequest($historyID){
	$where = array(
		      		'query' =>  "historyID=':historyID'",
		      		'params' => array(
		               ':historyID'=>$historyID
						)
				);
	$request = DB::getField("?:history_raw_details", "request", $where);
	$request = unserialize(base64_decode($request));
	$requestParams = $request['params'];
	setMultiCallOptions($requestParams);
	$request['params'] = $requestParams;
	DB::update("?:history", "retried = retried+1", $where);
	return DB::update("?:history_raw_details", array('request' => base64_encode(serialize($request))), $where);
}

function notifyV3Update(){
	$isV3Installed = getOption('V3Installed');
	$notifyV3Update = getOption('notifyV3Update');

	if (empty($isV3Installed) && !empty($notifyV3Update)) {
		return true;
	}

	return false;
}

function getCachedV3UpdateDetails(){
	$notifyV3Update = notifyV3Update();
	if ($notifyV3Update == false) {
		return false;
	}
	$updateAvailable = getOption('updateAvailableV3');
	if(!empty($updateAvailable)){
		$updateAvailable = @unserialize($updateAvailable);
		if($updateAvailable == 'noUpdate'){
			return false;
		}
		return $updateAvailable;
	}
	return false;
}

function isChildSite($siteID){
	$where = array(
		      		'query' =>  "multisiteID!='0' AND parent = '0' AND siteID =':siteID'",
		      		'params' => array(
		               ':siteID'=>$siteID
						)
				);
	$siteID = DB::getField("?:sites", "siteID", $where);
	if (empty($siteID)) {
		return false;
	}
	return $siteID;
}

function getParentSiteID($siteID){
	$where = array(
		      		'query' =>  "multisiteID!='0' AND parent = '0' AND siteID =':siteID'",
		      		'params' => array(
		               ':siteID'=>$siteID
						)
				);
	$parentSiteID = DB::getField("?:sites", "parentSiteID", $where);
	if (empty($parentSiteID)) {
		return false;
	}
	return $parentSiteID;
}

function getBlogID($siteID){
	$where = array(
		      		'query' =>  "siteID=':siteID'",
		      		'params' => array(
		               ':siteID'=>$siteID
						)
				);
	$multisiteID = DB::getField("?:sites", "multisiteID", $where);
	if (empty($multisiteID)) {
		return false;
	}
	return $multisiteID;
}

function saveNetworkSite($parentSiteID, $networkSites){
	if (empty($networkSites)) {
		return false;
	}

	foreach ($networkSites  as $key => $site) {
		$siteAddress = str_ireplace(array('www.', 'http://', 'https://'), '', $site);
		$siteAddress = rtrim($siteAddress, '/');
		DB::replace("?:multisites", array('parentSiteID' => $parentSiteID, 'formatedURL' => $siteAddress, 'URL' => $site));
	}
}

function removeNetworkSite($parentSiteID){
	$where = array(
		      		'query' =>  "parentSiteID=':parentSiteID'",
		      		'params' => array(
		               ':parentSiteID'=>$parentSiteID
						)
				);
	DB::delete("?:multisites", $where);
}

function getAllNetworkSitesByParentSiteID($parentSiteID){
	$where = array(
		      		'query' =>  "parentSiteID=':parentSiteID'",
		      		'params' => array(
		               ':parentSiteID'=>$parentSiteID
						)
				);
	$sites = DB::getFields("?:multisites", "URL", $where);
	if (empty($sites)) {
		return false;
	}
	return $sites;
}

function isAddonActive($slug){
	$where = array(
		      		'query' =>  "slug = ':slug'",
		      		'params' => array(
		               ':slug'=>$slug
       				)
    			);
	$status = DB::getField("?:addons", "status", $where);

	if ($status == 'active') {
		return true;
	}

	return false;
}

function processServicePopupNotification($notifications){
	$liveNotifyID = array();
	foreach ($notifications as $key => $value) {
		$liveNotifyID[]= $value['ID'];
		$where = array(
				      		'query' =>  "ID = ':ID'",
				      		'params' => array(
				               ':ID'=>$value['ID']
		       				)
		    			);
		$isExist = DB::getField("?:popup_notification", "ID", $where);
		$insertAry = array('ID' => $value['ID'],
		                   'name' => $value['name'],
		                   'status' => $value['status'],
		                   'oneTimeOnly' => $value['oneTimeOnly'],
		                   'userTypes' => $value['userTypes'],
		                   'intervalTime' => $value['intervalTime'],
		                   'html' => $value['html'],
		                   'breakTime' => $value['breakTime'],
		                   'version' => $value['version'],
					);
		if (!empty($isExist)) {
			DB::update('?:popup_notification', $insertAry, $where);
		}else{
			$nextSchedule = time()+$value['intervalTime']+$value['breakTime'];
			$insertAry['nextSchedule'] = $nextSchedule;
			DB::insert('?:popup_notification', $insertAry);
		}
	}
	// $where = "ID NOT IN (". implode(', ', DB::esc($liveNotifyID)) .")";
	// DB::delete('?:popup_notification', $where);
}

function getAddonsHTML(){
	$addonsHTML = getOption('addonsHTML');
	if (empty($addonsHTML)) {
		return '';
	}

	return $addonsHTML;
}
function getAddonsIllegalHTML(){
	$addonsHTML = getOption('addonsIllegalHTML');
	if (empty($addonsHTML)) {
		return '';
	}

	return $addonsHTML;
}
function getAddSiteHTML(){
	$addonsHTML = getOption('addSiteHTML');
	if (empty($addonsHTML)) {
		return '';
	}

	return $addonsHTML;
}

function addSiteRetry($historyID){
	$where = array(
				'query' =>  "historyID=':historyID'",
				'params' => array(
		       ':historyID'=>$historyID
				)
		);
	if (empty($GLOBALS['storage']['newSite'])) {
		$param1 = DB::getField('?:history', 'param1', $where);
		if (!empty($param1)) {
			$GLOBALS['storage']['newSite'] = unserialize($param1);
		}else{
			return 'noRetry';
		}
	}
	if(!empty($GLOBALS['storage']['newSite']['advancedCUCT'])  && $GLOBALS['storage']['newSite']['advancedCUCT'] !=0 && empty($GLOBALS['storage']['newSite']['lastCall'])){
		  $buildOptions = manageClientsSites::buildOptionalParams($GLOBALS['storage']['newSite']['connectURL'], $GLOBALS['storage']['newSite']['callOpt']['HTTPVersion'], $GLOBALS['storage']['newSite']['callOpt']['contentType']);
		  if ($buildOptions != false && is_array($buildOptions)) {
				$GLOBALS['storage']['newSite']['connectURL'] = $buildOptions['connectURL'];
				$GLOBALS['storage']['newSite']['recursiveCount'] = $GLOBALS['storage']['newSite']['recursiveCount']?$GLOBALS['storage']['newSite']['recursiveCount']+1:2;
				$GLOBALS['storage']['newSite']['callOpt']['HTTPVersion'] = $buildOptions['HTTPVersion'];
				$GLOBALS['storage']['newSite']['callOpt']['contentType'] = $buildOptions['contentType'];
				$callOpt = $GLOBALS['storage']['newSite']['callOpt'];
				$requestData = $GLOBALS['storage']['newSite']['requestData'];
				$siteURL = $requestData['params']['site_url'];
				if ($GLOBALS['storage']['newSite']['connectURL'] == 'siteURL') {
					$siteURL =  $GLOBALS['storage']['newSite']['websiteURL'];
				}
				return executeRequest($historyID, 'site','add', $siteURL, $requestData, '', true, $callOpt);
		  }elseif (empty($GLOBALS['storage']['newSite']['lastCall'])) {
		  		$callOpt = $GLOBALS['storage']['newSite']['callOpt'];
			  	$requestData = $GLOBALS['storage']['newSite']['requestData'];
			  	$siteURL = $requestData['params']['site_url'];
			  	$GLOBALS['storage']['newSite']['lastCall'] = true;
			  	$GLOBALS['storage']['newSite']['recursiveCount'] = $GLOBALS['storage']['newSite']['recursiveCount']?$GLOBALS['storage']['newSite']['recursiveCount']+1:2;
			  	return executeRequest($historyID, 'site','add', $siteURL, $requestData, '', true, $callOpt);
		  }
	}
	return 'noRetry';
}

function crossVersionAddonsNotInstalledAlert(){

	$isV3Installed = getOption('V3Installed');
	if(empty($isV3Installed) || (!defined('APP_ROOT_V3') && !defined('APP_V3'))){
		return;
	}
	$lastNotify = getoption('crossCronRunAlert');
	$retryTime = 60 * 60 * 24 * 1; // send notification again after one week
	$lastNotify += $retryTime;
	if ($lastNotify >= time()) {
		return false;
	}

	if(isV3Panel() && !DB::getExists("SHOW TABLES LIKE '?:addons_v3'")){
		return false;
	}
	
	$v2ScheduleAddons = DB::getArray('?:addons', 'slug, status',  "slug IN('scheduleBackup', 'clientReporting', 'wpOptimize')");
	$v3ScheduleAddons = DB::getArray('?:addons_v3', 'slug, status',  "slug IN('scheduleBackup', 'clientReporting', 'wpOptimize')");
	
	$panelVersion = '';
	if(manageEasyCron::isActive()){
		$panelVersion = manageEasyCron::cronPanelVersion();
		if (empty($panelVersion)) {
			return;
		}
	}else{
		$v2CronFrequency = getRealSystemCronRunningFrequency(false, false, true);
		$v3CronFrequency = getRealSystemCronRunningFrequency(false, true, false);
	}

	if (!empty($panelVersion)) {
		if ((empty($v2ScheduleAddons) && $panelVersion == 'v2') && (!empty($v3ScheduleAddons))) {
			$notification = 'v3';
			$installedAddons = 	$v3ScheduleAddons;
		}elseif ((!empty($v2ScheduleAddons) && $panelVersion == 'v3') && (empty($v3ScheduleAddons))) {
			$notification = 'v2';
			$installedAddons = 	$v2ScheduleAddons;
		}
	}else{

		if ((empty($v2ScheduleAddons) && $v2CronFrequency > 0) && (!empty($v3ScheduleAddons) && $v3CronFrequency <= 0)) {
			$notification = 'v3';
			$otherCron = 'v2';
			$installedAddons = 	$v3ScheduleAddons;
		}elseif ((!empty($v2ScheduleAddons) && $v2CronFrequency <= 0) && (empty($v3ScheduleAddons) && $v3CronFrequency > 0)) {
			$notification = 'v2';
			$otherCron = 'v3';
			$installedAddons = 	$v2ScheduleAddons;
		}
	}
	if (!empty($installedAddons)) {
		$notifyAddons = array();
		foreach ($installedAddons as $key => $value) {
			if ($value['slug'] == 'scheduleBackup') {
				$schedules = DB::getField('?:backup_schedules', 'scheduleID', "paused = '0'");
				$whichAddon = "Schedule Backup";
			}elseif ($value['slug'] == 'clientReporting') {
				$schedules = DB::getField('?:client_report_schedule', 'clientReportScheduleID', "paused = '0'");
				$whichAddon = 'Client Reporting';
			}elseif ($value['slug'] == 'wpOptimize') {
				$schedules = DB::getField('?:wp_optimize_schedules', 'scheduleID', "paused = '0'");
				$whichAddon = 'WP Maintenance';
			}

			if (!empty($schedules)) {
				$notifyAddons [] = $whichAddon;
			}
			$schedules = $whichAddon = false;
		}
		if (!empty($notifyAddons)) {
			$ad = @implode(', ', $notifyAddons);
			addNotification($type='E', $title='Action Required!', $message='It looks like you have the following addons '.$ad.' scheduled tasks to run, but the cronjob is inactive on your '.$notification.' admin panel.<br>For the scheduled jobs to work, please create a cronjob for '.$notification.' admin panel and delete the '.$otherCron.' cronjob or install the premium addons on your '.$otherCron.' admin panel interface.', $state='U', $callbackOnClose='', $callbackReference='');
			updateOption('crossCronRunAlert', time());
		}
	}

}
function getSiteHttpAuth($siteID){
	$where = array(
		'query' =>   "siteID=':siteID'",
			'params' => array(
				':siteID' => $siteID,
			)
		);
	return DB::getField('?:sites', 'httpAuth', $where);
}
function is_base64($data){
      return base64_encode(base64_decode($data, true)) === $data;
}
function fetchV3UpdateDetails(){
	$updateAvailable = getOption('V3UpdateAvailable');
	if(!empty($updateAvailable)){
		$updateAvailable = @unserialize($updateAvailable);
		if($updateAvailable == 'noUpdate'){
			return false;
		}
		return $updateAvailable;
	}
	return false;
}
function isV3Panel(){
	return defined('APP_V3');
}
Le coin du marchand VO vente véhicule entre professionnels

Accès réservé aux professionnels

Site regroupant des annonces de véhicules marchands en vente entre professionnels. Vendez, achetez vos V.O entre pros en toute simplicité et sans intermédiaires.

Déposez gratuitement vos annonces*

*Offre de lancement

Marques
Nous avons trouvé annonces pour vous.

Slide Slide Slide Slide Slide En savoir plus

A propos de nous

Le Coin du Marchand
VO

Le Coin du Marchand
VO

Parce que le métier de marchand V.O. est en perpétuelle évolution
Le coin du marchand V.O. a décidé de vous accompagner à travers cette plateforme qui vous propose un service de petites annonces pour la vente et l’achat de véhicules entre professionnels revendeurs.

Pour l’approvisionnement de votre parc, pour une recherche personnalisée ou vendre des véhicules stockés , assurez-vous des transactions uniquement entre pros.
L’accès à la plateforme est sécurisé et exclusivement réservé aux professionnels.

Soigneusement sélectionnées

Annonces Récentes

Pourquoi Nous Choisir

Professionnalisme

Plateforme regroupant les professionnels qui proposent des véhicules de divers modèles à la vente

Sur toute la France

Les ventes se font uniquement entre professionnels

Meilleurs Tarifs

Vous trouverez de très bonnes occasions de véhicules à des tarifs marchands

Partenaires

  • Développement
  • Bénéfices Mutuelles
  • Collaborations
  • Visibilité
  • Soutenir d’autres Projets

Newsletter

Abonnez-vous à notre newsletter et restez informé de nos offres

Copyright © 2023 Le Coin du Marchand VO | All Rights Reserved | Yanacom