<?php
setlocale(LC_ALL, 'fr', 'fr_FR', 'french', 'fra', 'fra_FRA', 'fr_FR.ISO_8859-1', 'fra_FRA.ISO_8859-1', 'fr_FR.utf8', 'fr_FR.utf-8', 'fra_FRA.utf8', 'fra_FRA.utf-8');

$today = date("Y-m-d H:i:s");

$dateFr = date("d/m/Y");
$dateTimeFr = date("d/m/Y H:i:s");
$timeFr = date("H:i:s");

$jour = array("Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi");
$jour_abr = array("Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam");
$mois = array("", "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre");
$mois_abr = array("", "Jan", "Fév", "Mar", "Avr", "Mai", "Jui", "Jul", "Aoû", "Sep", "Oct", "Nov", "Déc");

function getinfos($cSQL, $dbn = "gen", $format = "normal") {
  $result = array();

  $resql = qSQL($cSQL, $dbn);
  while ($rec = $resql->fetch_assoc()) {
    $result[] = $rec;
  }
  if (strtolower($format) == "json") {
    $jsonresult = json_encode($result);
    $lignes = $jsonresult;
    return $lignes;
  } else {
    return $result;
  }
}

//! qSQL : fonction de requête SQL à la base de données
function qSQL($qsql, $dbn = "gen", $lastid = false) {
  global $Conf;
  $dbh = $Conf->_dbhost;
  //! si en paramètre on spécifie une base de données $dbn, on s'y connecte,
  //! sinon on regarde si la base utilisateur est renseignée, si c'est le cas on s'y connecte, sinon on prend la base par défaut
  if ($dbn == "gen") {
    if ($Conf->_dbuname == "") {
      $dbn = $Conf->_dbname;
      $dbu = $Conf->_dbuser;
      $dbp = $Conf->_dbpass;
    } else {
      $dbn = $Conf->_dbuname;
      $dbu = $Conf->_dbuuser;
      $dbp = $Conf->_dbupass;
    }
  } else {
    if (strtolower($dbn) == "principale" || strtolower($dbn) == "frontal") {
      $dbn = $Conf->_dbname;
      $dbu = $Conf->_dbuser;
      $dbp = $Conf->_dbpass;
    } else {
      if (strtolower($dbn) == "credemo") {
        $dbn = $Conf->_dbcname;
        $dbu = $Conf->_dbcuser;
        $dbp = $Conf->_dbcpass;
      } else {
        //! sinon on prend le groupe
        $dbn = $Conf->_dbgname;
        $dbu = $Conf->_dbguser;
        $dbp = $Conf->_dbgpass;
      }
    }
  }

  // Logger la requête SQL si le mode debug SQL est activé
  if (isset($Conf->_log_sql) && $Conf->_log_sql) {
    $start_time = microtime(true);
  }
  
  $mysqli = new mysqli($dbh, $dbu, $dbp, $dbn);
  $mysqli->set_charset("utf8");
  if ($mysqli->connect_error) {
    // la connexion ne s'est pas faite
    if (isset($Conf->_log_sql) && $Conf->_log_sql) {
      debug("Erreur de connexion MySQL: " . $mysqli->connect_error . " | DB: $dbn", "SQL_ERROR", 1);
    }
    $mysqli->close();
    return false;
  } else {
    // la connexion s'est faite correctement
    if ($qres = $mysqli->query($qsql)) {
      if ($lastid) {
        $qres = $mysqli->insert_id;
      }
      
      // Logger la requête SQL réussie
      if (isset($Conf->_log_sql) && $Conf->_log_sql) {
        $exec_time = round((microtime(true) - $start_time) * 1000, 2); // en ms
        $query_type = strtoupper(substr(trim($qsql), 0, 6));
        $log_data = array(
          'query' => $qsql,
          'database' => $dbn,
          'exec_time_ms' => $exec_time,
          'type' => $query_type
        );
        
        // Pour les INSERT avec lastid, ajouter l'ID inséré
        if ($lastid && $query_type == 'INSERT') {
          $log_data['insert_id'] = $qres;
        }
        
        debug($log_data, "SQL_QUERY", 2);
      }
      
      $mysqli->close();
      return $qres;
    } else {
      // Erreur dans la requête SQL
      $error_msg = $mysqli->error;
      
      if (isset($Conf->_log_sql) && $Conf->_log_sql) {
        $exec_time = isset($start_time) ? round((microtime(true) - $start_time) * 1000, 2) : 0;
        debug(array(
          'query' => $qsql,
          'database' => $dbn,
          'error' => $error_msg,
          'exec_time_ms' => $exec_time
        ), "SQL_ERROR", 1);
      }
      
      $mysqli->close();
      return false;
    }
  }
}

function hashPsswd($p) {
  $options = [
    'cost' => 11,  // Cout algorithmique
  ];
  // Génération du MDP
  $psswd = password_hash($p, PASSWORD_BCRYPT, $options);
  return $psswd;
}

function createPsswd($id, $p, $dbgen = "gen") {
  global $Conf;
  global $Route;

  $psswd = hashPsswd($p);

  if ($Conf::admin) {
    if (substr($Conf->_appname, 0, 3) == "ce_") {
      if ($Route->_script == "salaries") {
        $sql = 'UPDATE salaries SET userpswd="' . $psswd . '", userpass="xxx" WHERE rowid=' . $id . ';';
      } else {
        $sql = 'UPDATE users SET userpswd="' . $psswd . '", userpass="xxx" WHERE rowid=' . $id . ';';
      }
    } else {
      $sql = 'UPDATE users SET userpswd="' . $psswd . '", userpass="xxx" WHERE rowid=' . $id . ';';
    }
  } else {
    $sql = 'UPDATE salaries SET userpswd="' . $psswd . '", userpass="xxx" WHERE rowid=' . $id . ';';
  }

  qSQL($sql);

  eLog($sql);

  return true;
}

function checkPsswd($p, $pCr) {
  // Récupération et vérification du MDP saisi par l'utilisateur
  // $p : le pass en clair, $pCr : le pass enregistré et hashé
  if (password_verify($p, $pCr)) {
    return true;
  } else {
    return false;
  }
}

function generateRandomPassword() {
  //Initialize the random password
  $password = '';

  //Initialize a random desired length
  $desired_length = rand(8, 12);

  for ($length = 0; $length < $desired_length; $length++) {
    //Append a random ASCII character (including symbols)
    $password .= chr(rand(44, 122));
  }
  // On remplace quelques caractères non désirés
  $password = str_replace("/", "&", $password);
  $password = str_replace("<", "!", $password);
  $password = str_replace(">", "!", $password);
  $password = str_replace("=", "#", $password);
  $password = str_replace("\\", "&", $password);
  $password = str_replace("^", "%", $password);
  $password = str_replace(chr(96), "#", $password);

  return $password;
}

function eLog($comment, $notif = false) {
  global $Session;
  global $Route;
  global $Conf;

  if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
    $ip = $_SERVER["HTTP_CLIENT_IP"];
  } elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
    $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
  } else {
    $ip = $_SERVER["REMOTE_ADDR"];
  }
  $hn = getHostByName($ip);
  $ha = @getHostByAddr($hn);
  $us = substr($_SERVER["HTTP_USER_AGENT"], 0, 100);
  if (isset($Session->_user["rowid"])) {
    $user = $Session->_user["rowid"];
    if ($user == "") {
      $user = 0;
    }
  } else {
    $user = 0;
  }
  $script = $Route->_script;
  $comment = nettoie_input($comment);
  $dt = date("Y-m-d H:i:s");
  if ($notif) {
    $not = 1;
  } else {
    $not = 2;
  }
  $sql = 'INSERT INTO z_logs (date, ip, host, adrhost, infos, fk_user, page, commentaire, chk_notif) VALUES ("' . $dt . '", "' . $ip . '", "' . $hn . '", "' . $ha . '", "' . $us . '", "' . $user . '", "' . $script . '", "' . $comment . '", ' . $not . ');';
  qSQL($sql, "gen");

  if (strpos(strtolower($comment), 'erreur') !== false) {
    //! S'il y a spécifiquement une erreur on l'enregistre dans un fichier log à la racine du site
    $log_dir = dirname(dirname(dirname(__DIR__))) . "/log/";
    $log_file = $log_dir . $Conf->_appname . "_" . date('Y-m-d') . ".log";
    
    // Vérifier que le répertoire existe
    if (!is_dir($log_dir)) {
      @mkdir($log_dir, 0775, true);
    }
    
    // Si le fichier n'existe pas, le créer avec les bonnes permissions
    if (!file_exists($log_file)) {
      @touch($log_file);
      @chmod($log_file, 0664);
    }
    
    // Purger les anciens logs (garder seulement les 10 derniers jours)
    purge_old_logs($log_dir, $Conf->_appname, 10);
    
    // Écrire dans le log seulement si on peut
    if (is_writable($log_file)) {
      error_log($dt . ";" . $ip . ";" . $script . ";" . $comment . "\r\n", 3, $log_file);
    }
  }
}

//! *****************************************************************************************//
//! Fonction de debug globale
function debug($data, $label = '', $level = 4) {
  global $Conf;
  
  // Vérifier si le debug est activé et si le niveau est suffisant
  if (!isset($Conf->_debug_level) || $Conf->_debug_level < $level) {
    return;
  }
  
  $debug_info = array(
    'timestamp' => date('Y-m-d H:i:s'),
    'level' => $level,
    'label' => $label,
    'type' => gettype($data),
    'file' => '',
    'line' => '',
    'function' => ''
  );
  
  // Récupérer les informations de debug
  $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
  if (isset($backtrace[0])) {
    $debug_info['file'] = $backtrace[0]['file'];
    $debug_info['line'] = $backtrace[0]['line'];
  }
  if (isset($backtrace[1])) {
    $debug_info['function'] = $backtrace[1]['function'];
  }
  
  // Préparer le message de debug
  $debug_message = "[{$debug_info['timestamp']}] ";
  $debug_message .= "DEBUG LVL{$level}";
  if ($label) {
    $debug_message .= " - {$label}";
  }
  $debug_message .= " | {$debug_info['file']}:{$debug_info['line']}";
  if ($debug_info['function']) {
    $debug_message .= " in {$debug_info['function']}()";
  }
  $debug_message .= "\n";
  
  // Formatter les données
  if (is_array($data) || is_object($data)) {
    $debug_message .= print_r($data, true);
  } elseif (is_bool($data)) {
    $debug_message .= $data ? 'true' : 'false';
  } elseif (is_null($data)) {
    $debug_message .= 'null';
  } else {
    $debug_message .= $data;
  }
  $debug_message .= "\n" . str_repeat('-', 80) . "\n";
  
  // Écrire dans le fichier de log si configuré
  if (isset($Conf->_log_file_path) && $Conf->_log_file_path) {
    // Remplacer la date dans le chemin du fichier si elle existe déjà
    $log_file = preg_replace('/_debug_\d{4}-\d{2}-\d{2}\.log$/', '_debug_' . date('Y-m-d') . '.log', $Conf->_log_file_path);
    
    // Si le pattern n'a pas matché, c'est un ancien format, on ajoute la date
    if ($log_file == $Conf->_log_file_path && !preg_match('/_' . date('Y-m-d') . '\.log$/', $log_file)) {
      $log_file = str_replace('.log', '_' . date('Y-m-d') . '.log', $log_file);
    }
    
    // Vérifier que le répertoire existe et est accessible en écriture
    $log_dir = dirname($log_file);
    if (!is_dir($log_dir)) {
      @mkdir($log_dir, 0775, true);
    }
    
    // Si le fichier n'existe pas, le créer avec les bonnes permissions
    if (!file_exists($log_file)) {
      @touch($log_file);
      @chmod($log_file, 0664);
    }
    
    // Purger les anciens logs
    $app_name = isset($Conf->_appname) ? $Conf->_appname : 'app';
    purge_old_logs($log_dir, $app_name, 10);
    
    // Écrire dans le log seulement si on peut
    if (is_writable($log_file)) {
      error_log($debug_message, 3, $log_file);
    }
  }
  
  // Afficher à l'écran si display_errors est activé et niveau >= 3
  if (ini_get('display_errors') && $level >= 3) {
    echo "<pre style='background:#f0f0f0; border:1px solid #ccc; padding:10px; margin:10px; font-size:12px;'>";
    echo htmlspecialchars($debug_message);
    echo "</pre>";
  }
}

function logstats($delay = 0, $fk_user = 0, $appname = "") {
  global $Conf;
  $dt = date("Y-m-d H:i:s");

  $exclude_clients_ip = "aucune";
  if (isset($Conf->_excludeIp)) {
    $exclude_clients_ip = $Conf->_excludeIp;
  }

  if (isset($Conf->_clientIp)) {
    $client_ip = $Conf->_clientIp;
  } else {
    if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
      $client_ip = $_SERVER["HTTP_CLIENT_IP"];
    } elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
      $client_ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    } else {
      $client_ip = $_SERVER["REMOTE_ADDR"];
    }
  }
  $verif_ip = strpos($exclude_clients_ip, $client_ip);

  if ($verif_ip === false) {

    $home = $_SERVER["HOME"];
    $doc_root = $_SERVER["DOCUMENT_ROOT"];
    $doc_root = substr($doc_root, strlen($home));

    $sql = 'INSERT INTO z_stats SET ';
    $sql .= 'date="' . $dt . '", ';
    $sql .= 'root="' . $doc_root . '", ';
    $sql .= 'server_ip="' . $_SERVER["SERVER_ADDR"] . '", ';
    $sql .= 'server_soft="' . $_SERVER["SERVER_SOFTWARE"] . '", ';
    $sql .= 'server_name="' . $_SERVER["SERVER_NAME"] . '", ';
    $sql .= 'client_ip="' . $client_ip . '", ';
    $sql .= 'client_browser="' . $_SERVER["HTTP_USER_AGENT"] . '", ';
    if (isset($_SERVER["HTTP_REFERER"])) {
      $sql .= 'client_origine="' . $_SERVER["HTTP_REFERER"] . '", ';
    }
    $sql .= 'client_page="' . $_SERVER["REQUEST_URI"] . '", ';
    $sql .= 'client_delay=' . str_replace(',', '.', $delay) . ', ';
    $sql .= 'appname="' . $appname . '", ';
    $sql .= 'fk_user=' . $fk_user . ', ';
    $sql .= 'status="' . $_SERVER["REDIRECT_STATUS"] . '";';

    // server : 51.255.35.214
    $mysqli = new mysqli("localhost", "logs_user", "d66,Logs.User", "logs");
    $mysqli->set_charset("utf8");
    $mysqli->query($sql);
    $mysqli->close();
  }
}

//! *****************************************************************************************//
//! nettoie_input : prépare une zone d'un formulaire avant son enregistrement dans la base   //
//! En paramètre, on passe la valeur à nettoyer                                              //
//! *****************************************************************************************//
function nettoie_input($data) {
  if (ctype_digit((string)$data)) {
    $data = intval($data);
  } else {
    global $Conf;
    $dbn = $Conf->_dbname;
    $mysqli = new mysqli($Conf->_dbhost, $Conf->_dbuser, $Conf->_dbpass, $dbn);
    $mysqli->set_charset("utf8");
    $data = mysqli_real_escape_string($mysqli, $data);
    // $data = addcslashes($data, '%_');
    $mysqli->close();
  }
  return $data;
}

function str_normalize($string, $minuscules = true) {
  //! Normalise une chaîne de caractères en remplaçant tous les caractères accentués, les espaces et caractères spéciaux
  $result = "";
  $string = trim($string);    // on efface tous les espaces à gauche et à droite
  if (strlen($string) > 0) {
    if ($minuscules) {
      $result = strtolower($string);
    } else {
      $result = $string;
    }
    $result = str_replace(" ", "_", $result);
    //$result = str_replace("-", "_", $result);
    //$result = str_replace(".", "_", $result);
    $result = str_replace("é", "e", $result);
    $result = str_replace("è", "e", $result);
    $result = str_replace("ê", "e", $result);
    $result = str_replace("ë", "e", $result);
    $result = str_replace("à", "a", $result);
    $result = str_replace("â", "a", $result);
    $result = str_replace("ä", "a", $result);
    $result = str_replace("ô", "o", $result);
    $result = str_replace("ö", "o", $result);
    $result = str_replace("ù", "u", $result);
    $result = str_replace("û", "u", $result);
    $result = str_replace("ü", "u", $result);
    $result = str_replace("ç", "c", $result);
    $result = str_replace("'", "", $result);
    $result = str_replace("\"", "", $result);
    $result = str_replace("/", "", $result);
    $result = str_replace("(", "_", $result);
    $result = str_replace(")", "_", $result);
    $result = str_replace("!", "_", $result);
    //! Ajout du 08/12/2015
    $result = str_replace("?", "_", $result);

    $result = trim($result);
  }
  return $result;
}

function affiche_date($ladate) {
  /**
   * This is a sample function to illustrate additional PHP formatter
   * options.
   * @param $ladate date au format MySQL
   *
   * @return String date au format Fr dd/mm/yyyy
   * @author D6SOFT
   *
   */
  //! Retourne une date MySQL yyyy-mm-dd HH:ii:ss au format dd/mm/yyyy
  $ladate = trim($ladate);
  if ($ladate == "" || substr($ladate, 0, 2) == "00") {
    return "";
  } else {
    if (strlen($ladate) < 10) {
      return "";
    } else {
      $theday = substr($ladate, 8, 2) . "/" . substr($ladate, 5, 2) . "/" . substr($ladate, 0, 4);
      return $theday;
    }
  }
}

function d6GetDate($laDate, $transform = "MF", $hours = false, $seconds = false) {
  //! Retourne une date
  //! $format="MF"  du format MySQL yyyy-mm-dd    au format Fr dd/mm/yyyy
  //! $format="FM"  du format Fr dd/mm/yyyy       au format MySQL yyyy-mm-dd

  $ret = "";
  if (strlen($laDate) >= 10) {
    if ($transform == "FM") {
      $ret = substr($laDate, -4) . "-" . substr($laDate, 3, 2) . "-" . substr($laDate, 0, 2);
    } else {
      $ret = substr($laDate, -2) . "/" . substr($laDate, 5, 2) . "/" . substr($laDate, 0, 4);
    }
  }
  return $ret;
}

function loadtel($numero, $prefix = "+33") {
  //! retourne un numéro de téléphone sans espace et . et avec le préfixe devant : +33 par défaut
  $lenumero = trim($numero);
  $lenumero = preg_replace('/[^0-9]/', '', $lenumero);
  if (strlen($lenumero) == 10) {
    $lenumero = substr($lenumero, 1);
  }
  if (strlen($lenumero) == 9) {
    $lenumero = $prefix . $lenumero;
  }
  return $lenumero;
}

function formattel($numero, $separateur = " ") {
  //! formate le n° de téléphone de 651234567 ou 0651234567 en 06 51 23 45 67
  if (strlen($numero) == 9) {
    $numero = "0" . $numero;
  }
  if (strlen($numero) == 10) {
    $numero = substr($numero, 0, 2) . $separateur . substr($numero, 2, 2) . $separateur . substr($numero, 4, 2) . $separateur . substr($numero, 6, 2) . $separateur . substr($numero, 8, 2);
  }
  return $numero;
}

//! *****************************************************************************************//
//! Fonction pour purger les anciens fichiers de log
function purge_old_logs($log_dir, $app_name, $days_to_keep = 10) {
  // Vérifier que le répertoire existe
  if (!is_dir($log_dir)) {
    return;
  }
  
  // Date limite pour conserver les logs
  $date_limit = strtotime("-{$days_to_keep} days");
  
  // Patterns des fichiers à purger
  $patterns = array(
    $app_name . '_????-??-??.log',
    $app_name . '_debug_????-??-??.log'
  );
  
  foreach ($patterns as $pattern) {
    $files = glob($log_dir . $pattern);
    if ($files) {
      foreach ($files as $file) {
        // Extraire la date du nom de fichier
        if (preg_match('/(\d{4}-\d{2}-\d{2})\.log$/', $file, $matches)) {
          $file_date = strtotime($matches[1]);
          // Si le fichier est plus ancien que la limite, le supprimer
          if ($file_date < $date_limit) {
            @unlink($file);
          }
        }
      }
    }
  }
}