<?php
##############################################################
# Database abstraction functions                             #
##############################################################
$MAX_CONNECT_ERROR = 3;

# fonction de connexion spéciale pour la gestion des sessions
# NON UTILISE
function session_db_connect()
{
	main_db_connect(0);
}
//fonction de vérifiaction d'une requete pour éviter les attaques de type Injection SQL
function prevent_sql_injection_query($query)
{
	$query = trim($query);
	$error = "";	
	
	//on verifie qu'on ne fait rien d'autre qu'un SELECT, INSERT, UPDATE OU DELETE
	$pattern = "#^(REPLACE|SELECT|INSERT|UPDATE|DELETE)(.*)#i";
	preg_match ($pattern, $query, $resultat);
	if($resultat[0])
	{
		//on ne teste plus que la fin de requete
		$query = $resultat[2];

		//tous ce qui n'est pas entre "" ou entre '' est qui ressemble à -- ou à une commande SQL
		$pattern = "#(('[^']*'|\"[^\"]*\")|(-{2})| REPLACE | SELECT | DELETE | UPDATE | INSERT | UNION | DROP | CREATE | ALTER | EXEC )#";
		preg_match_all($pattern, $query, $resultats);			
		foreach($resultats[1] AS $string)
		{
			switch($string)
			{
				case "--" :	
					$error = "Les commentaires SQL non autorisées depuis IP =".$_SERVER["REMOTE_ADDR"];
				break;
				
				case " SELECT " :
				case " DELETE " :
				case " UPDATE " :
				case " INSERT " :
				case " UNION " :
				case " DROP " :
				case " CREATE " :
				case " ALTER " :
				case " EXEC " :
					$error = "Commande SQL non autorisée depuis IP =".$_SERVER["REMOTE_ADDR"];
				break;
			}
		}	
	}
	//si ca ne commence pas par le bon mot clef SQL on rejete
	else
	{
		$error = "Seuls les commandes SELECT, DELETE, UPDATE, INSERT sont autorisées en début de requête";			
	}	
	return $error;	
}


function sendFatalError($s)
{
	global $ROOT_EMAIL, $SCRIPT_NAME, $GAME_NAME,$GAME_CODE_NAME, $LOGIN_PAGE,$ADMIN_USER,$ADMIN_PWD,$PRODMAN_SERVER_NAME;
	
	$date = date("Y-m-d H:i:s", my_local_time());
	//on désactive les mail d'alerte sql
	//mail($ROOT_EMAIL, "Error : ".$GAME_NAME, $date." : ".$SCRIPT_NAME." >> ".$s);
	
	//on appelle l'api de gestion d'erreur de prodman
	file("http://".$ADMIN_USER.":".$ADMIN_PWD."@".$PRODMAN_SERVER_NAME."/error_api_check_msg.php?GameName=".urlencode($GAME_CODE_NAME)."&Script=".urlencode($_SERVER["SCRIPT_NAME"])."&Error=".urlencode($s));
	
	debug("Error : ".$GAME_NAME." : ".$SCRIPT_NAME." >> ".$s);
	header("Location:".$LOGIN_PAGE."?errorLogin=".urlencode("Une erreur fatale est survenue, veuillez nous en excuser, merci de nous prévenir nous contactant via notre service client."));
	exit();
}

# connexion à la db
# cette fonction n'a pas a être utilisé par le developpeur
function main_db_connect($database, $force = false)
{
	global $DATABASE, $MAX_CONNECT_ERROR, $VG_tabDbLinks;
	
	# par défaut on prend $DATABASE, si une autre base n'est passpécifiée
	if (empty($database))
	{
		unset($database);
		$database = $DATABASE;
	}
	
	$dbId = $database["host"].$database["main_name"];
	 
	# on se connecte à la bdd si on force
	# si la connexion n'existe pas encore (elle est identifiée par le couple $database["host"].$database["main_name"]). 
	# S'il vaut qql chose dans le tableau $VG_tabDbString c'est qu'elle existe déjà
	//if (($force == true) or (empty($VG_tabDbLinks[$dbId])))
	//{
		# plusieurs tentative de connexion à la BDD
		$iConnectErrorCounter = 0;
		do
		{
			$iConnectErrorCounter++;
   			$VG_tabDbLinks[$dbId] = mysql_connect($database["host"], $database["login"], $database["password"]);
   			
   			# si c la première tentative de connexion on ne fait pas de temporisation
   			# sinon on temporise la seconde tentative
   			if ($iConnectErrorCounter > 1)
   			{
   				debug("Pb de connexion à la bdd, retry ".$iConnectErrorCounter." : ".$dbId);
				sleep(2);
			}
		}
		while(!$VG_tabDbLinks[$dbId] and $iConnectErrorCounter < $MAX_CONNECT_ERROR);
			
		if ($VG_tabDbLinks[$dbId])
		{
    		$res = mysql_select_db($database["main_name"], $VG_tabDbLinks[$dbId]);
    	
	    	if (!$res)
				sendFatalError("Pb de selection de la bdd : ".$dbId);
		}
		else
		{
			sendFatalError("Connexion impossible à la bdd : ".$dbId);
		}
	//}
	
	return $VG_tabDbLinks[$dbId];
}

# détruit le contenu du tableau $VG_tabDbLinks. Forçant ainsi la reconnection de la prochaine requete
function clear_db_connect()
{
	global $VG_tabDbLinks;
	
	$VG_tabDbLinks = array();
}


function main_db_query($query, $forceMaster = false, $database = "",$checkSQLInjection = true)
{
	global $DATABASE, $DATABASE_SLAVE, $VG_DEBUG;

	if($checkSQLInjection)
		$query_error = prevent_sql_injection_query($query);
	
	if (!$query_error)
	{
		# on détecte toutes les requetes SELECT
		# elles sont effectuées en local sur la base SLAVE (répliquée)
		# les requetes de modifications sont effectuées directement sur la base principale
		
		#$isMaster = ($forceMaster or strtoupper(substr(ltrim($query), 0, 1)) != "S") ? 1 : 0;
		$isMaster = 1;
		
		# si on est en mode debug
		if ($VG_DEBUG)
		{		
			debug($VG_DEBUG_THREAD." ".$query." isMaster:".$isMaster);
		}
		
		if ($database != "")
			$dbLink = main_db_connect($database);
		else
			$dbLink = main_db_connect(($isMaster == 1) ? $DATABASE : $DATABASE_SLAVE);

		$status = mysql_query($query, $dbLink);
		
		# en cas de pb de db on envoie un mail, on log et on retourne sur la home
		if (!$status)
			sendFatalError(print_r($dbLink, 1)." >> ".$query." >> ".$isMaster);
	}	
	else
	{
		sendFatalError("SQL Injection (".$query_error.") >> ".$query." >> ".$isMaster);
	}
	
	return $status;
}

function session_db_query($query)
{
	return main_db_query($query);
}  

function db_fetch_array($result)
{
	return @mysql_fetch_array($result);
}

function db_fetch_assoc($result)
{
	return @mysql_fetch_assoc($result);
}

function db_fetch_row($result)
{
	return @mysql_fetch_row($result);
}

function db_num_rows($result)
{
	return @mysql_num_rows($result);
}

function db_data_seek($result,$row)
{
	return @mysql_data_seek($result,$row);
}

function db_insert_id()
{
	return mysql_insert_id();
}

function db_free_result($result) {
  return mysql_free_result($result);
}

function db_affected_rows()
{
	return mysql_affected_rows();
}

?>