<?php
/**------------------------------------------------
*
* Rooty, 2018 <rooty@rooty.me>
*
*
* This software is protected by copyright, please
* read the file COPYRIGHT.
* This program is distributed in the hope that it
* will be useful, but without any warranty; without
* even the implied warranty of merchantability or
* fitness for a particular purpose. Please
* read the file LICENCE.
*
*                               postgres7.php
*                            -------------------
*   begin                : Saturday, Feb 13, 2001
*   copyright            : (C) 2001 The phpBB Group
*   email                : supportphpbb.com
*
*   $Id: postgres7.php,v 1.2 2006/06/10 20:51:19 mathieu Exp $
*
*
*   This program is free software; you can redistribute it and/or modify
*   it under the terms of the GNU General Public License as published by
*   the Free Software Foundation; either version 2 of the License, or
*   (at your option) any later version.
*
*
*Fichier postgres.php
*
*Ce fichier contient la classe d'accès aux données pour PostGreSQL 7
*<BR>
* @author The phpBB Group
* @since 2018/03/05
* @version 1.19
* @link http://www.phpbb.com
* @package system_data_source
* @subpackage database
* @modify by Initiance <www.initiance.com|olivier@initiance.com>
*
*/

#####################################################################################################
################################# Parametrage
#####################################################################################################
/**
* declaration du system... si cette variable n'est pas définie, les fichier inclus ne marche pas...
* cette variable est déclarée sur la page d'execution du script.
*<p> if ( !defined('SYSTEM_IN') )
* {
* die("Hacking attempt");
* }</p>
*/
if ( !defined('SYSTEM_IN') )
{
 die("Hacking attempt");
}

/**
* classe PostGres
*
* classe de gestion de PostGreSQL
*
* @package system_data_source
* @subpackage database
*/
class PostGres7 extends Database
{

/**#@+
* @access public
*/

/**
* @var entier
* @desc identifiant de la connection a la base
*/
	var $db_connect_id;
/**
* @var result
* @desc pointeur de résultat sur requete SELECT
*/
	var $query_result;
/**
* @var booléen
* @desc indique si la requete est en mode de transaction
*/
	var $in_transaction = 0;
/**
* @var tableau
* @desc Contient une ligne de résultat
*/
	var $row = array();
/**
* @var tableau
* @desc Contient tout le jeu de résultats
*/
	var $rowset = array();
/**
* @var tableau
* @desc tableau contenant le nombre de resultats par requetes
*/
	var $rownum = array();
/**
* @var entier
* @desc Nombre total de requetes effectuées
*/
	var $num_queries = 0;

/**#@-*/

	//
	// Constructor
	//

/**
*Constructeur de DataBase_PostGres
*
*Initialise la connection a la base de données PostGreSQL
*
* @param chaine Nom de l'hote PostGreSQL
* @param chaine Nom d'utilisateur
* @param chaine Mot de passe de connection
* @param chaine Nom de la base a utiliser
* @param booléen Connection persistante
*/
	function PostGres7($sqlserver, $sqluser, $sqlpassword, $database, $persistency = true)
	{
		$this->__construct($sqlserver, $sqluser, $sqlpassword, $database, $persistency);
	}

	function __construct($sqlserver, $sqluser, $sqlpassword, $database, $persistency = true)
	{
		$this->connect_string = "";

		if( $sqluser )
		{
			$this->connect_string .= "user=$sqluser ";
		}

		if( $sqlpassword )
		{
			$this->connect_string .= "password=$sqlpassword ";
		}

		if( $sqlserver )
		{
			if( ereg(":", $sqlserver) )
			{
				list($sqlserver, $sqlport) = split(":", $sqlserver);
				$this->connect_string .= "host=$sqlserver port=$sqlport ";
			}
			else
			{
				if( $sqlserver != "localhost" )
				{
					$this->connect_string .= "host=$sqlserver ";
				}
			}
		}

		if( $database )
		{
			$this->dbname = $database;
			$this->connect_string .= "dbname=$database";
		}

		$this->persistency = $persistency;
		$this->db_connect_id = ( $this->persistency ) ? pg_pconnect($this->connect_string) : pg_connect($this->connect_string);

		if ( $this->db_connect_id )
		{
			return $this->db_connect_id;
		}else{
			/* Olivier 12/07/04 */
			$seuil=1;
			$classe="ODBC";
			$message="Erreur de configuration de la base de donnée:Base non disponible";
			addError($seuil,$classe,$message, __line__, __file__);
			return false;
		}
	}

	//
	// Other base methods
	//

/**
*fermeture de connection
*
* fonction qui ferme la connection a la source de données
*
* @return booléen
*/
	function sql_close()
	{
		if( $this->db_connect_id )
		{
			//
			// Commit any remaining transactions
			//
			if( $this->in_transaction )
			{
				@pg_exec($this->db_connect_id, "COMMIT");
			}

			if( $this->query_result )
			{
				@pg_freeresult($this->query_result);
			}

			return @pg_close($this->db_connect_id);
		}
		else
		{
			return false;
		}
	}

	//
	// Query method
	//
	
/**
*fonction de requete SQL
*
* permet de faire une requete sur la connection ODBC ouverte 
*
* @param chaine Requete SQL
* @param booléen inutilisé dans ce cas
* @return result renvoie un pointeur de resultat ou faux si erreur de requete
*/
	function sql_query($query = "", $transaction = false)
	{
		//
		// Remove any pre-existing queries
		//
		unset($this->query_result);
		$query=Database::rewriteQuery($query);
		if( $query != "" )
		{
			$this->num_queries++;

			$query = preg_replace("/LIMIT ([0-9]+),([ 0-9]+)/", "LIMIT \\2 OFFSET \\1", $query);

			if( $transaction == BEGIN_TRANSACTION && !$this->in_transaction )
			{
				$this->in_transaction = TRUE;

				if( !@pg_exec($this->db_connect_id, "BEGIN") )
				{
					return false;
				}
			}

			$this->query_result = @pg_exec($this->db_connect_id, $query);
			if( $this->query_result )
			{
				if( $transaction == END_TRANSACTION )
				{
					$this->in_transaction = FALSE;

					if( !@pg_exec($this->db_connect_id, "COMMIT") )
					{
						@pg_exec($this->db_connect_id, "ROLLBACK");
						return false;
					}
				}

				$this->last_query_text[$this->query_result] = $query;
				$this->rownum[$this->query_result] = 0;

				unset($this->row[$this->query_result]);
				unset($this->rowset[$this->query_result]);

				return $this->query_result;
			}
			else
			{
				if( $this->in_transaction )
				{
					@pg_exec($this->db_connect_id, "ROLLBACK");
				}
				$this->in_transaction = FALSE;

				return false;
			}
		}
		else
		{
			if( $transaction == END_TRANSACTION && $this->in_transaction )
			{
				$this->in_transaction = FALSE;

				if( !@pg_exec($this->db_connect_id, "COMMIT") )
				{
					@pg_exec($this->db_connect_id, "ROLLBACK");
					return false;
				}
			}

			return true;
		}
	}

	//
	// Other query methods
	//
/**
*Nombre de resultats retournés
*
*permet de récuperer le nombre de lignes retournées lors de la dernière requête effectuée.
*
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return entier nombre de résultats
*/
	function sql_numrows($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		return ( $query_id ) ? @pg_numrows($query_id) : false;
	}

/**
*Nombre de champs
*
* retourne le nombre de champs de la derniere requete effectuée
*
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return entier nombre de champs
*/
	function sql_numfields($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		return ( $query_id ) ? @pg_numfields($query_id) : false;
	}

/**
*Nom d'un champ
*
* retourne le nom du champ placé a offset
*
* @param entier emplacement du champ
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return chaine nom du champ
*/
	function sql_fieldname($offset, $query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		return ( $query_id ) ? @pg_fieldname($query_id, $offset) : false;
	}

/**
*Type d'un champ
*
* retourne le type du champ placé a offset
*
* @param entier emplacement du champ
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return chaine type de champ
*/		
	function sql_fieldtype($offset, $query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		return ( $query_id ) ? @pg_fieldtype($query_id, $offset) : false;
	}

/**
*Obtenir un résultat
*
* retourne l'enregistrement courant sous forme de tableau
*
* @param entier facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return tableau tableau contenant les différents champs
*/
	function sql_fetchrow($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		if($query_id)
		{
			$this->row = pg_fetch_array($query_id);

			if( $this->row )
			{
				$this->rownum[$query_id]++;
				return $this->row;
			}
		}

		return false;
	}

/**
*Obtenir tous les résultats
*
* retourne tous les enregistrements courants (derniere requete effectuée) sous forme de tableau 
*
* @param entier  (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return tableau_2D tableau à deux dimensions contant tous les enregistrement
*/
	function sql_fetchrowset($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		if( $query_id )
		{
			unset($this->rowset[$query_id]);
			unset($this->row[$query_id]);
			$this->rownum[$query_id] = 0;

			while( $this->rowset = @pg_fetch_array($query_id, $this->rownum[$query_id], PGSQL_ASSOC) )
			{
				$result[] = $this->rowset;
				$this->rownum[$query_id]++;
			}

			return $result;
		}

		return false;
	}

/**
*Obtenir un champ particulier d'un resultat
*
* retourne un champ déterminé d'un enregistrement déterminé
*
* @param entier (ou chaine) champ a renvoyer
* @param entier (facultatif) identifiant de l'enregistrement (dernier par defaut)
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return chaine valeur du champ
*/
	function sql_fetchfield($field, $row_offset=-1, $query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		if( $query_id )
		{
			if( $row_offset != -1 )
			{
				$this->row = @pg_fetch_array($query_id, $row_offset, PGSQL_ASSOC);
			}
			else
			{
				if( $this->rownum[$query_id] )
				{
					$this->row = @pg_fetch_array($query_id, $this->rownum[$query_id]-1, PGSQL_ASSOC);
				}
				else
				{
					$this->row = @pg_fetch_array($query_id, $this->rownum[$query_id], PGSQL_ASSOC);

					if( $this->row )
					{
						$this->rownum[$query_id]++;
					}
				}
			}
			return $this->row[$field];
		}
		return false;
	}

/**
*Déplacement de pointeur de résultat
*
* permet de déplacer le pointeur de résultat.
*
* @param entier ligne
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return result nouveau pointeur de resultat
*/
	function sql_rowseek($offset, $query_id = 0)
	{

		if(!$query_id)
		{
			$query_id = $this->query_result;
		}

		if( $query_id )
		{
			if( $offset > -1 )
			{
				$this->rownum[$query_id] = $offset;
				return true;
			}
			else
			{
				return false;
			}
		}
		return false;
	}

/**
*Identifiant d'insertion
*
* permet d'obtenir l'identifiant d'insertion (Requete INSERT)
*
* @return entier identifiant
*
*/
	function sql_nextid()
	{
		$query_id = $this->query_result;
		if($query_id && $this->last_query_text[$query_id] != "")
		{
			if( preg_match("/^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)/is", $this->last_query_text[$query_id], $tablename) )
			{
				$query = "SELECT currval('" . $tablename[1] . "_id_seq') AS last_value";
				$temp_q_id =  @pg_exec($this->db_connect_id, $query);
				if( !$temp_q_id )
				{
					return false;
				}
				$temp_result = @pg_fetch_array($temp_q_id, 0, PGSQL_ASSOC);
				return ( $temp_result ) ? $temp_result['last_value'] : false;
			}
		}
		return false;
	}

/**
*Nombre d'enregistrements modifiés
*
* retourne le nombre d'enregistrements affectés par la derniere requete.
*
* @param entier (facultatif) identifiant de requete ,utilise la dernière requete par defaut
* @return entier nombre d'enregistrements modifiés
*/
	function sql_affectedrows($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		return ( $query_id ) ? @pg_cmdtuples($query_id) : false;
	}

/**
*Liberer l'espace mémoire
*
* permet de liberer la memoire occupée par le pointeur de résultat
*
* Bug de la lib phpBB (si aucun id de query_result si sql_close->bug)
* @version 1.1
* @param entier (facultatif) identifiant de requete , utilise la dernière requete par defaut
* @return booléen effectué avec succès
*/
	function sql_freeresult($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}
		$this->query_result=false;
		return ( $query_id ) ? @pg_freeresult($query_id) : false;
	}

/**
* Fonction d'erreur
*
* retourne un tableau contenant le numero et le message d'erreur
*
* @return tableau contenant les index ['message'] et ['code']
*/
	function sql_error($query_id = 0)
	{
		if( !$query_id )
		{
			$query_id = $this->query_result;
		}

		$result['message'] = @pg_errormessage($this->db_connect_id);
		$result['code'] = -1;

		return $result;
	}
}
?>
