<?php

/**
 *
 * Le connecteur est utilisé pour réaliser toutes les connexions aux bases de données
 *
 *
 */
class Connecteur
{

    // tableau contenant pour chaque bases ses attributs associés à ces valeurs
    public $infoConnect;

    public $messageError;

    private $db_encours;

    private $webService = null;

    /**
     * Constructeur
     */
    public function setWebService($webService)
    {
        $this->webService = $webService;
    }

    public function isWebServiceExiste()
    {
        return ! is_null($this->webService);
    }

    public function __construct()
    {
        global $logAuditOk;
        // On récupère toutes les variables issues du fichier base1.ini et qui étaient enregistrées dans
        // le tableau $GLOBAL
        
        // Spec 3797 : on ôte DB_OXALINKDB
        $bases = array(
            DB_OXAPROCDB,
            DB_OXACATDB,
            DB_OXASQLDB,
            DB_OXAFTDB,
        );
        $attributs = array(
            'TYPE',
            'NAME',
            'SERVER',
            'LOGIN',
            'P_PASSWORD'
        );
        $this->messageError = '';
        $this->db_encours = '';
        for ($i = 0; $i < count($bases); ++ $i) {
            for ($j = 0; $j < count($attributs); ++ $j) {
                if (array_key_exists($bases[$i] . '_' . $attributs[$j], $_SESSION)) {
                    $this->infoConnect[$bases[$i]][$attributs[$j]] = $_SESSION[$bases[$i] . '_' . $attributs[$j]];                    
                } elseif ($bases[$i] == DB_OXAFTDB) {
                    if (array_key_exists(DB_OXASQLDB . '_' . $attributs[$j], $_SESSION)) {
                        $this->infoConnect[$bases[$i]][$attributs[$j]] = $_SESSION[DB_OXASQLDB . '_' . $attributs[$j]];
                    }
                }
            }

            
            // On initialise par défaut à  NULL la connexion sur chacune des bases
            $this->infoConnect[$bases[$i]]['CONNECTED'] = NULL;
            $this->infoConnect[$bases[$i]]['ID_CONNECT'] = NULL;
            $this->infoConnect[$bases[$i]]['ACTIVE'] = false;
            
            if ($this->infoConnect[$bases[$i]]['TYPE'] == DB_MSSQL && $this->infoConnect[$bases[$i]]['NAME'] != '') {
                $this->infoConnect[$bases[$i]]['PREFIXDB'] = $this->infoConnect[$bases[$i]]['NAME'] . '.dbo.';
                $logAuditOk = true;
            } else if ($this->infoConnect[$bases[$i]]['TYPE'] == DB_ORA && $this->infoConnect[$bases[$i]]['LOGIN'] != '') {
                $this->infoConnect[$bases[$i]]['PREFIXDB'] = $this->infoConnect[$bases[$i]]['LOGIN'] . '.';
                $logAuditOk = true;
            }
        }
    }

    public function disconnect()
    {
        global $elementSynequa;
        global $elementSynequaStk;
        if (! is_null($elementSynequa)) {
            $elementSynequa->close();
            $elementSynequa = null;
        }
        if (! is_null($elementSynequaStk)) {
            $elementSynequaStk->close();
            $elementSynequaStk = null;
        }
        if (is_array($this->infoConnect))
            foreach ($this->infoConnect as $base => & $elemConnexion)
                if (! is_null($elemConnexion['CONNECTED']))
                    if ($elemConnexion['ACTIVE']) {
                        switch ($elemConnexion['TYPE']) {
                            case DB_MSSQL:
                                if (function_exists('mssql_connect'))
                                    mssql_close($elemConnexion['ID_CONNECT']);
                                else
                                    sqlsrv_close($elemConnexion['ID_CONNECT']);
                                break;
                            
                            case DB_ORA:
                                break;
                        }
                        $elemConnexion['ACTIVE'] = false;
                    }
    }

    /**
     *
     * Fonction créant une connexion pour une bd donnée
     *
     * @param string $base
     *            (OXAPROC OXACAT OXASQLDB)
     * @return Type connextion $this->infoConnect[$base]['CONNECTED']
     *        
     */
    public function &connect($base)
    {
        $con = & $this->infoConnect[$base];        
        if (is_null($con['CONNECTED'])) {
            switch ($con['TYPE']) {
                case DB_MYSQL:
                    try {
                        if ($c = mysql_connect($con['SERVER'], $con['LOGIN'], $con['P_PASSWORD'])) {
                            $con['ID_CONNECT'] = & $c;
                            $con['CONNECTED'] = mysql_select_db($con['NAME'], $con['ID_CONNECT']);
                            
                            $this->execSql("SET NAMES 'utf8'", $base);
                        } else {
                            throw new Exception(strBuild(trad('La connexion a la base @1@ a échoué, vérifiez le nom de la base, le login et le password dans le fichier base1.ini !'), $con['NAME']));
                        }
                    } catch (Exception $e) {
                        $error = new ErrorHandle();
                        $error->logError($e->getMessage());
                        $error->logError('Erreur SQL : ' . mssql_get_last_message());
                        // On affiche l'erreur pour l'utilisateur
                        if (isset($_SESSION['Session_Login'])) {
                            $error->displayError('de connexion');
                        } else {
                            $_SESSION['dbErrorMessage'] = $e->getMessage();
                        }
                    }
                    break;
                
                case DB_MSSQL:
                    if (function_exists('mssql_connect')) {
                        try {
                            if (($c = @mssql_connect($con['SERVER'], $con['LOGIN'], $con['P_PASSWORD'])) !== false) {
                                $con['ID_CONNECT'] = & $c;
                                $con['CONNECTED'] = mssql_select_db($con['NAME'], $con['ID_CONNECT']);
                            } else
                                break;
                        } catch (Exception $e) {
                            $error = new ErrorHandle();
                            $error->logError($e->getMessage());
                            $error->logError(ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                            // On affiche l'erreur pour l'utilisateur
                            if (isset($_SESSION['Session_Login']))
                                ErrorHandle::displayError('de connexion');
                            else
                                $_SESSION['dbErrorMessage'] = $e->getMessage();
                        }
                    } else {
                        try {
                            if (extension_loaded('sqlsrv')) {
                                $connextion = array(
                                    'DataBase' => $con['NAME'],
                                    'UID' => $con['LOGIN'],
                                    'PWD' => $con['P_PASSWORD'],
                                    'CharacterSet' => 'UTF-8'
                                );
                                
                                if (($c = sqlsrv_connect($con['SERVER'], $connextion)) !== false) {
                                    $con['ID_CONNECT'] = & $c;
                                    $con['CONNECTED'] = true;
                                } else
                                    break;
                            }
                        } catch (Exception $e) {
                            $error = new ErrorHandle();
                            $error->logError($e->getMessage());
                            $error->logError(ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                            // On affiche l'erreur pour l'utilisateur
                            if (isset($_SESSION['Session_Login']))
                                ErrorHandle::displayError('de connexion');
                            else
                                $_SESSION['dbErrorMessage'] = $e->getMessage();
                        }
                    }
                    break;
                
                case DB_ORA:
                    try {
                        if (extension_loaded('oci8')) {
                            if (($c = @oci_connect($con['LOGIN'], $con['P_PASSWORD'], $con['SERVER'], 'AL32UTF8', OCI_DEFAULT)) !== false) {
                                $con['ID_CONNECT'] = & $c;
                                $con['CONNECTED'] = true;
                                
                                // Oracle en dessous v10
                                $sqlAlter1 = 'ALTER SESSION SET nls_numeric_characters=".,"';
                                $this->ExecSql($sqlAlter1, $base);
                                // Oracle >=10
                                $sqlAlter2 = 'ALTER SESSION SET NLS_NUMERIC_CHARACTERS=".,"';
                                $this->ExecSql($sqlAlter2, $base);
                            } else {
                                $error = new ErrorHandle();
                                $e = oci_error();
                                $error->logError("Erreur Exec SQL SQL : $sql" . $e['message'] . "\n\r");
                                $error->logError('Erreur liée à  la requête : ' . $e['sqltext'] . "\n\r");
                                $error->logError(Debug::DebugTraceToStr());
                            }
                            break;
                        }
                    } catch (Exception $e) {
                        $error = new ErrorHandle();
                        $e = oci_error($c);
                        $error->logError('Erreur SQL : ' . $e['message']);
                        $error->logError('login : ' . $con['LOGIN']);
                        $error->logError('Password : ' . $con['P_PASSWORD']);
                        $error->logError('Service : ' . $con['SERVER']);
                        // On affiche l'erreur pour l'utilisateur
                        if (isset($_SESSION['Session_Login']))
                            ErrorHandle::displayError('de connexion');
                        else
                            $_SESSION['dbErrorMessage'] = $error->getMessage();
                    }
                    break;
                
                default:
            }
        }
        return $con['CONNECTED'];
    }

    // fin de connect
    
    /**
     *
     * Fonction retournant le type pour un connecteur donné
     *
     * @param char $base
     *            (OXAPROC OXACAT OXASQLDB)
     * @return char $type Type connextion
     *        
     */
    public function &getType($base)
    {
        return $this->infoConnect[$base]['TYPE'];
    }

    public function &getPrefixTable($base)
    {
        return $this->infoConnect[$base]['PREFIXDB'];
    }

    public function setType($base, $type)
    {
        $this->infoConnect[$base]['TYPE'] = $type;
    }

    public function &getInfoconnect()
    {
        return $this->infoConnect;
    }

    /**
     *
     * Fonction retournant la ligne de résultat trouvée
     *
     * @param string $sql
     * @param string $base
     *            (OXAPROC OXACAT OXASQLDB)
     * @param boolean $cache
     * @param boolean $memcache
     * @return array $row
     */
    public function &CanFind($sql, $base, $cache = false, $memcache = true)
    {
        $row = null;
        if ($cache) {
            $key = 'req_' . $sql;
            if ($memcache && MemcacheManage::is_memcache_activated()) {
                if (false !== MemcacheManage::getValue($key))
                    return MemcacheManage::getValue($key);
            } else if (array_key_exists($key, $_SESSION)) {
                $retour = & $_SESSION[$key];
                if ($retour == null)
                    return $retour;
                
                return unserializeSecure($retour);
            }
        }
        
        if ($this->connect($base)) {
            // tester si la requète est de type select sinon lever un exception.
            $this->infoConnect[$base]['ACTIVE'] = true;
            switch ($this->getType($base)) {
                case DB_MYSQL:
                    try {
                        if ($result = mysql_query($sql, $this->infoConnect[$base]['ID_CONNECT'])) {
                            
                            while ($row = mysql_fetch_assoc($result)) {
                                foreach ($row as $key => $element)
                                    $row[$key] = trim($row[$key]);
                                break;
                            }
                            
                            mysql_free_result($result);
                        } else {
                            throw new Exception(strBuild(trad('Une requete SQL a généré une erreur : @1@'), $sql));
                        }
                        
                        $this->isDbLocked = false;
                    }                    // Les erreurs sont enregistrées dans la log
                    catch (Exception $e) {
                        
                        $no = @mysql_errno($this->infoConnect[$base]['ID_CONNECT']);
                        
                        if ($no == 1192)
                            $this->isDbLocked = true;
                        else {
                            
                            $error = new ErrorHandle();
                            $error->logError('Version : ' . getVersionProduit() . "\n\r");
                            $error->logError($e->getMessage() . ' : ' . $sql);
                            $error->logError('Erreur SQL : ' . @mysql_errno($this->infoConnect[$base]['ID_CONNECT']));
                            // On affiche l'erreur pour l'utilisateur*
                            if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                                $error->displayError(strBuild(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' @1@"), $sql));
                            else
                                $error->displayError(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'"));
                            exit();
                        }
                    }
                    break;
                case DB_MSSQL:
                    // On capture les erreurs eventuelles
                    try {
                        $sql = Connecteur::convertiSqlUnicode($sql);
                        if ($result = sqlsrv_query($this->infoConnect[$base]['ID_CONNECT'], $sql)) {
                          
                            // AMI 20160411 : le tableau $zone doit être initialisé, sinon il y autant de warnings que de champs requêtés.
                            $zone = array();
                            foreach (sqlsrv_field_metadata($result) as $fieldMetadata)
                                $zone[$fieldMetadata['Name']] = $fieldMetadata; // AMI 20170606 : pas de référence ici, sinon on a des problèmes (notamment lorsque la dernière colonne est un booléen)...
                            
                            while ($row =  sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
                                foreach ($row as $key => & $element)
                                    if ($key == '') {
                                        $row['computed'] = trim($element);
                                        unset($row['']);
                                        // Spec 3797 : on recopie aussi les méta-données.
                                        $zone['computed'] = $zone[''];
                                        unset($zone['']);
                                    } elseif (is_a($element, 'DateTime'))
                                        $element = date('Y-m-d', $element->getTimestamp());
                                    elseif (($zone[$key]['Size'] == 1 && $zone[$key]['Type'] == - 2))
                                        if ($element == 'T')
                                            $element = '1';
                                        else
                                            $element = '0';
                                    else if (strlen($element) == 1 && ord($element) === 160) // 24408
                                        $element = '';
                                    else
                                        $element = rtrim($element);
                                
                                break;
                            }
                            
                            sqlsrv_cancel($result);
                        } else
                            throw new Exception('Une requete SQL a généré une erreur : ' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                    }                    // Les erreurs sont enregistrées dans la log
                    catch (Exception $e) {
                        $error = new ErrorHandle();
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $error->logError($e->getMessage() . ' : ' . $sql);
                        $error->logError(ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                        $error->logError(Debug::DebugTraceToStr());
                        throw new Exception(trad('Une requete SQL a généré une erreur'));
                    }
                    break;
                
                case DB_ORA:
                    // On capture les erreurs eventuelles
                    // if ($base == DB_OXAPROCDB || $base == DB_OXASQLDB)
                    // on passe par la fonction OraProtectRequest uniquement si on la requete est lancé sur OXAPROCDB
                    // permet de palier au fait que des champs dans OXAPROCDB sont en miniscule.
                    // $sql = OraProtectRequest($sql, $base);
                    
                    try {
                        $sql = Connecteur::convertiSqlUnicode($sql);
                        if ($result = oci_parse($this->infoConnect[$base]['ID_CONNECT'], $sql)) {
                            if (! oci_execute($result, OCI_DEFAULT))
                                throw new Exception('Erreur d\'analyse de la requète : oci_execute()');
                            
                            if (stripos($sql, 'call ') === 0) {
                                $sqlFind = "select * from TMP{$_SESSION['id_user']} ";
                                $result = oci_parse($this->infoConnect[$base]['ID_CONNECT'], $sqlFind);
                                if (! oci_execute($result, OCI_DEFAULT))
                                    throw new Exception('Erreur d\'analyse de la requète : oci_execute()');
                            }
                            
                            while ($row = oci_fetch_assoc($result)) {
                                foreach ($row as $key => & $element)
                                    if (strlen($element) == 1 && ord($element) === 160) // 24408
                                        $element = '';
                                    else
                                        $element = trim($element);
                                
                                break;
                            }
                            oci_free_statement($result);
                        } else
                            throw new Exception(trad('Une requete SQL a généré une erreur'));
                    }                    // Les erreurs sont enregistrées dans la log
                    catch (Exception $e) {
                        $error = new ErrorHandle();
                        $e = oci_error($result);
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $error->logError('Erreur requete début : ' . $sql . "\n\r");
                        $error->logError('Erreur SQL : ' . $e['message'] . "\n\r");
                        $error->logError('Erreur CanFind liée à  la requête : ' . $e['sqltext'] . "\n\r");
                        $error->logError(Debug::DebugTraceToStr());
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                            ErrorHandle::displayError(strBuild(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' @1@"), $sql));
                        else
                            ErrorHandle::displayError(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'"));
                        
                        $this->disconnect();
                        exit();
                    }
                    break;
                default:
                    echo 'non prevu non prevu non prevu ';
                    break;
            } // fin switch
        }
        if ($cache) {
            if ($memcache && MemcacheManage::is_memcache_activated())
                MemcacheManage::setValue('req_' . $sql, $row);
            else if ($this->getType($base) == DB_ORA) {
                // pas de mise en cache coté oracle
            } else if ($row == null)
                $_SESSION['req_' . $sql] = null;
            else
                $_SESSION['req_' . $sql] = serializeSecure($row);
        }
        return $row;
    }

    /**
     *
     * Fonction retournant un ensemble de lignes de résultat
     *
     * @param string $sql
     * @param string $base
     *            (OXAPROC OXACAT OXASQLDB)
     * @return array $indice
     */
    public function &AllFind(& $sql, $base, $champ_data = null, $cache = false)
    {
        $row = null;
        $indice = null;
        
        if ($cache && MemcacheManage::is_memcache_activated())
            if (false !== MemcacheManage::getValue('req_' . $sql))
                return MemcacheManage::getValue('req_' . $sql);
        
        if ($this->connect($base)) {
            // tester si la requète est de type select sinon lever un exception.
            $con = & $this->infoConnect[$base];
            $con['ACTIVE'] = true;
            switch ($this->getType($base)) {
                case DB_MYSQL:
                    try {
                        if ($result = & mysql_query($sql, $con['ID_CONNECT'])) {
                            
                            while ($row = & mysql_fetch_assoc($result)) {
                                foreach ($row as $key => & $element) {
                                    if (! is_null($champ_data))
                                        // Traitement des données en fonction des differentes bases
                                        foreach ($champ_data as $type => & $champ_type)
                                            foreach ($champ_type as & $champ)
                                                if ($champ == $key)
                                                    switch (strtolower($type)) {
                                                        case 'bool':
                                                            $element = ((stripos($element, 'T') === 0) ? 1 : 0);
                                                            break;
                                                        default:
                                                            break;
                                                    }
                                    
                                    $element = trim($element);
                                }
                                
                                $indice[] = $row;
                            }
                            
                            mysql_free_result($result);
                        } else {
                            throw new Exception('Une requete SQL a généré une erreur ' . $sql);
                        }
                    } catch (Exception $e) {
                        
                        $error = new ErrorHandle();
                        $error->logError($e->getMessage());
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $error->logError('Erreur requete début : ' . $sql . "\n\r");
                        $error->logError('Erreur liée à  la requète : ' . $sql);
                        $error->logError('Erreur SQL : ' . mysql_error($sql, $con['ID_CONNECT']));
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                            $error->displayError(strBuild(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'"), $sql));
                        else
                            $error->displayError(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' "));
                        exit();
                    }
                    break;
                
                case DB_MSSQL:
                    try {
                        $sql = Connecteur::convertiSqlUnicode($sql);
                        if ($result = sqlsrv_query($this->infoConnect[$base]['ID_CONNECT'], $sql)) {
                           
                            // AMI 20160411 : le tableau $zone doit être initialisé, sinon il y autant de warnings que de champs requêtés.
                            $zone = array();
                            foreach (sqlsrv_field_metadata($result) as $fieldMetadata)
                                $zone[$fieldMetadata['Name']] = $fieldMetadata;
                                
                            while ($row = sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) {
                              
                                foreach ($row as $key => & $element)
                                    // Traitement des données en fonction des differentes bases
                                    
                                    if (($zone[$key]['Size'] == 1 && $zone[$key]['Type'] == - 2))
                                        if ($element == 'T')
                                            $element = '1';
                                        else
                                            $element = '0';
                                    else if (strlen($element) == 1 && ord($element) === 160) { // 24408
                                        $element = '';
                                    } else
                                        $element = rtrim($element);
                                
                                $indice[] =  $row;
                            }
                            sqlsrv_cancel($result);
                        } else {
                            throw new Exception('Une requete SQL a généré une erreur : ' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                        }
                    } catch (Exception $e) {
                        $error = new ErrorHandle();
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $error->logError($e->getMessage());
                        $error->logError('Erreur requete début : ' . $sql . "\n\r");
                        $error->logError('Erreur liée à  la requète : ' . $sql);
                        $error->logError(ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                        $error->logError(Debug::DebugTraceToStr());
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                            ErrorHandle::displayError("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'\n {$e->getMessage()} \n $sql");
                        else
                            ErrorHandle::displayError("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'\n ");
                        $this->disconnect();
                        exit();
                    }
                    break;
                case DB_ORA:
                    
                    // if ($base == DB_OXAPROCDB || $base == DB_OXASQLDB)
                    // on passe par la fonction OraProtectRequest uniquement si on la requete est lancé sur OXAPROCDB
                    // permet de palier au fait que des champs dans OXAPROCDB sont en miniscule.
                    // $sql = OraProtectRequest($sql, $base);
                    
                    try {
                        $sql = Connecteur::convertiSqlUnicode($sql);
                        if ($result = oci_parse($this->infoConnect[$base]['ID_CONNECT'], $sql)) {
                            if (! oci_execute($result, OCI_DEFAULT))
                                throw new Exception("Erreur d'analyse de la requète : oci_execute() " . __FILE__ . " à  la ligne " . __LINE__ . " fonction :" . __FUNCTION__);
                            
                            if (stripos($sql, 'call ') === 0) {
                                $sqlFind = "select * from TMP{$_SESSION['id_user']} ";
                                $result = oci_parse($this->infoConnect[$base]['ID_CONNECT'], $sqlFind);
                                if (! oci_execute($result, OCI_DEFAULT))
                                    throw new Exception("Erreur d'analyse de la requète : oci_execute()");
                            }
                            while ($row = oci_fetch_assoc($result)) {
                                foreach ($row as $key => $element) {
                                    if (! is_null($champ_data) && is_array($champ_data))
                                        // Traitement des données en fonction des differentes bases
                                        foreach ($champ_data as $type => & $champ_type)
                                            foreach ($champ_type as $champ)
                                                if ($champ == $key)
                                                    switch (strtolower($type)) {
                                                        case 'bool':
                                                            $row[$key] = ((stripos($row[$key], 'T') === 0) ? 1 : 0);
                                                            break;
                                                        default:
                                                            if (strlen($row[$key]) == 1 && ord($row[$key]) === 160)
                                                                $row[$key] = ''; // 24408
                                                            break;
                                                    }
                                    
                                    $row[$key] = rtrim($row[$key]);
                                }
                                $indice[] = $row;
                            }
                            oci_free_statement($result);
                        } else
                            throw new Exception("Erreur d'analyse de la requète : oci_parse() " . __FILE__ . ' à  la ligne ' . __LINE__ . ' fonction :' . __FUNCTION__);
                    } catch (Exception $e) {
                        $error = new ErrorHandle();
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $error->logError($e->getMessage());
                        $e = oci_error($result);
                        $error->logError('Erreur requete début : ' . $sql . "\n\r");
                        $error->logError('Erreur AllFind SQL : ' . $e['message'] . "\n\r");
                        $error->logError('Erreur liée à  la requête : ' . $e['sqltext'] . "\n\r");
                        $error->logError(Debug::DebugTraceToStr());
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                            ErrorHandle::displayError("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' \n {$e['message']} \n $sql");
                        else
                            ErrorHandle::displayError("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' ");
                        $this->disconnect();
                        exit();
                    }
                    break;
            }
            
            if ($cache && MemcacheManage::is_memcache_activated())
                MemcacheManage::setValue("req_{$sql}", $indice);
            
            return $indice;
        }
        return $row;
    }

    /**
     */
    public function ConvData(& $data, $base, $type)
    {
        switch ($this->GetType($base)) {
            case DB_MYSQL:
                switch (strtolower($type)) {
                    case 'bool':
                        if ($data == 'T' || $data == 1 || $data === true || $data == 'true')
                            return '0x54';
                        else
                            return '0x46';
                        break;
                }
                break;
            case DB_MSSQL:
                switch (strtolower($type)) {
                    case 'bool':
                        if ($data == 'T' || $data == 1 || $data === true || $data == 'true')
                            return '0x54';
                        else
                            return '0x46';
                        break;
                }
                break;
            case DB_ORA:
                switch (strtolower($type)) {
                    case 'bool':
                        if ($data == 'T' || $data == 1 || $data === true || $data == 'true')
                            return '1';
                        else
                            return '0';
                        break;
                }
                break;
        }
    }

    /**
     *
     * Fonction retournant le nombre de ligne affectées par la requète
     *
     * @param string $sql
     * @param string $base
     *            (OXAPROC OXACAT OXASQLDB)
     * @return int $result
     */
    public function ExecSql($sql, $base, $OraExecMode = OCI_COMMIT_ON_SUCCESS)
    {
        $result = false;
        if ($this->connect($base)) {
            $con = & $this->infoConnect[$base];
            $con['ACTIVE'] = true;
            
            switch ($this->GetType($base)) {
                case DB_MYSQL:
                    
                    try {
                        if (stripos($sql, 'USE ') === 0) {} // Rien
else if ($this->db_encours != $con['NAME']) {
                            $this->execSql('USE ' . $con['NAME'], $base);
                            
                            $this->db_encours = $con['NAME'];
                        }
                        
                        if (! ($result = mysql_query($sql, $con['ID_CONNECT']))) {
                            throw new Exception(trad("Une requete SQL a généré une erreur  : {$sql}"));
                        } else {
                            $lOk = true;
                        }
                        $this->isDbLocked = false;
                    } catch (Exception $e) {
                        
                        $no = mysql_errno($con['ID_CONNECT']);
                        
                        if ($no == 1192) {
                            $this->isDbLocked = true;
                        } else {
                            $error = new ErrorHandle();
                            $error->logError('Version : ' . getVersionProduit() . "\n\r");
                            $error->logError($e->getMessage() . ' : ' . $sql);
                            $error->logError("Erreur SQL : $sql " . mysql_errno($con['ID_CONNECT']));
                            // On affiche l'erreur pour l'utilisateur
                            if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                                $error->displayError(trad(mysql_errno($con['ID_CONNECT']) . " : Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' : {$sql}"));
                            else
                                $error->displayError(trad(" : Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' "));
                        }
                    }
                    
                    break;
                case DB_MSSQL:
                    try {
                        if (stripos($sql, 'USE ') === 0) {} // Rien
else if ($this->db_encours != $con['NAME']) {
                            $this->execSql('USE ' . $con['NAME'], $base);
                            
                            $this->db_encours = $con['NAME'];
                        }
                        
                        // En 5.34 Avec le systeme de pool connexion plutot bizarre le result
                        if (trim($sql) == 'BEGIN TRAN') {
                            if (! $result = sqlsrv_begin_transaction($con['ID_CONNECT']))
                                throw new Exception(('Une requete SQL a généré une erreur.' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors())));
                            else
                                $lOk = true;
                        } elseif (trim($sql) == 'COMMIT TRAN') {
                            if (! $result = sqlsrv_commit($con['ID_CONNECT']))
                                throw new Exception(('Une requete SQL a généré une erreur.' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors())));
                            else
                                $lOk = true;
                        } elseif (trim($sql) == 'ROLLBACK TRAN') {
                            if (! $result = sqlsrv_rollback($con['ID_CONNECT']))
                                throw new Exception(('Une requete SQL a généré une erreur.' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors())));
                            else
                                $lOk = true;
                        } else {
                            $sql = Connecteur::convertiSqlUnicode($sql);
                            if (! ($result = sqlsrv_query($con['ID_CONNECT'], $sql)))
                                throw new Exception(('Une requete SQL a généré une erreur.' . ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors())));
                            else
                                $lOk = true;
                        }
                    } catch (Exception $e) {
                        $error = new ErrorHandle();
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        echo 'err  ' . $base . ': ' . $sql;
                        $error->logError($e->getMessage() . ' : ' . $sql);
                        $error->logError(ErrorHandle::SqlsrvErrorToStr(sqlsrv_errors()));
                        $error->logError(Debug::DebugTraceToStr());
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true')
                            ErrorHandle::displayError(("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' $sql"));
                        else
                            ErrorHandle::displayError(("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' "));
                        $this->disconnect();
                        exit();
                    }
                    break;
                
                case DB_ORA:
                    $sqlOri = $sql;
                    try {
                        
                        // $sql = OraProtectRequest($sql,$base);
                        // if ($base == DB_OXAPROCDB || $base == DB_OXASQLDB)
                        // on passe par la fonction OraProtectRequest uniquement si on la requete est lancé sur OXAPROCDB
                        // permet de palier au fait que des champs dans OXAPROCDB sont en miniscule.
                        // $sql = OraProtectRequest($sql, $base);
                        
                        $sql = Connecteur::convertiSqlUnicode($sql);
                        if ($result = oci_parse($con['ID_CONNECT'], $sql))
                            if (! (oci_execute($result, $OraExecMode)))
                                throw new Exception("Erreur d'analyse de la requète : oci_execute() " . __FILE__ . " à  la ligne " . __LINE__ . " fonction :" . __FUNCTION__);
                            else
                                $lOk = true;
                        else
                            throw new Exception("Erreur d'analyse de la requète : oci_parse() " . __FILE__ . " à  la ligne " . __LINE__ . " fonction :" . __FUNCTION__);
                    } catch (Exception $e) {
                        oci_rollback($result);
                        $error = new ErrorHandle();
                        $error->logError('Version : ' . getVersionProduit() . "\n\r");
                        $e = oci_error($result);
                        $error->logError('Erreur Exec SQL SQL : ' . $sql . $e['message'] . "\n\r");
                        $error->logError('Erreur liée à  la requête : ' . $e['sqltext'] . "\n\r");
                        $error->logError(Debug::DebugTraceToStr());
                        // On affiche l'erreur pour l'utilisateur
                        if (array_key_exists('_debug', $_SESSION) && $_SESSION['_debug'] == 'true') {
                            echo $sqlOri . "\n";
                            echo $sql . "\n";
                            ErrorHandle::displayError(strBuild(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG'"), $sql));
                        } else
                            ErrorHandle::displayError(trad("Une erreur SQL est survenue, veuillez consulter le fichier 'GENERAL ERROR LOG' "));
                        $this->disconnect();
                        exit();
                    }
                    
                    break;
            }
        } // fin if
        return $result;
    }

    public static function &convertiSqlUnicode($element)
    {
        $flg_debut = false;
        $base = 0;
        $string_ret = '';
        $arrayControle = array(
            '0',
            '1',
            '2',
            '3',
            '4',
            '5',
            '6',
            '7',
            '8',
            '9',
            '.',
            '+',
            '-',
            ',',
            ' ',
            '_'
        );
        
        if (stripos($element, 'USE ') === 0)
            return $element;
        if (stripos($element, 'ALTER ') === 0)
            return $element;
        
        $element .= '  ';
        
        for ($icpt = 0; $icpt < (strlen($element) - 1); $icpt ++) {
            if ($element[$icpt] == "'") {
                if ($flg_debut) {
                    $icpt1 = $icpt + 1;
                    if ($element[$icpt] == $element[$icpt1])
                        $icpt ++;
                    else {
                        $mot = substr($element, $base, $icpt - $base);
                        
                        $unicodeMode = '';
                        
                        for ($index = 0; $index < strlen($mot); $index ++)
                            if ($mot[$index] < 'A' || $mot[$index] > 'Z')
                                if (! in_array($mot[$index], $arrayControle)) {
                                    // NE JAMAIS CHANGER CETTE LIGNE ICI CAR SINON RECURSIVITE DU AU FAIT que la fonction va declecher une requete SQL
                                    if (Param::ISBddUnicode())
                                        $unicodeMode = 'N';
                                    break;
                                }
                        
                        $string_ret .= $unicodeMode . '\'' . $mot . '\'';
                        $flg_debut = false;
                        
                        $base = $icpt + 1;
                    }
                } else { // on additionne à  la chaine de retour
                    $string_ret .= substr($element, $base, $icpt - $base);
                    $base = $icpt + 1;
                    $flg_debut = true;
                }
            }
        }
        
        // Ajout de la fin de chaine
        
        if ($base < strlen($element) - 1)
            $string_ret .= substr($element, $base, strlen($element) - 1 - $base);
        
        return $string_ret;
    }

    public static function convertBinaryToSqlBinary($binary)
    {
        if ($binary == 0)
            return '0x46';
        elseif ($binary == 1)
            return '0x54';
    }
}
