<?php

class Session {
  public $_user;

  function __construct($Route, $Conf) {
    if ($Route->_script != "login") {
      if ($Conf::intra) {
        //! on vérifie que le user a bien une session ouverte
        $this->getUserInfos($Route->_script, $Conf);
        if (!$this->_user) {
          header('Location: /login');
          exit;
        } else {
          $sql = 'UPDATE z_sessions s SET s.date_modified="' . date("Y-m-d H:i:s") . '" WHERE s.sid="' . session_id() . '";';
          qSQL($sql, "gen");
        }
      } else {
        //! ce n'est pas un intranet, donc un site vitrine public, on doit laisser passer mais mémoriser
        $sql = "SELECT s.* FROM z_sessions s WHERE s.sid='" . session_id() . "';";
        $res = qSQL($sql, "gen");
        if ($res instanceof PDOStatement) {
          $this->_user = $res->fetch(PDO::FETCH_ASSOC);
        } else {
          $this->_user = false;
        }
        if (empty($this->_user)) {
          //! pas de session pour lui, on en crée une
          if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
            //check for ip from share internet
            $uip = $_SERVER["HTTP_CLIENT_IP"];
          } elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
            // Check for the Proxy User
            $uip = $_SERVER["HTTP_X_FORWARDED_FOR"];
          } else {
            $uip = $_SERVER["REMOTE_ADDR"];
          }
          $utime = time();
          $uid = 0;
          $urole = 0;

          //! en session on récupère son prénom et nom, son id, son ip et son rôle
          $_SESSION['uname'] = 'anonyme';
          $_SESSION['uid'] = $uid;
          $_SESSION['urole'] = $urole;
          $_SESSION['umodified'] = $utime;
          $_SESSION['uip'] = $uip;
          session_write_close();

          // On insère le nouvel id de session dans la db
          $sql = "INSERT INTO z_sessions (sid, fk_user, role, date_modified, ip, browser) VALUES ('" . session_id() . "', " . $uid . ", '" . $urole . "', '" . date("Y-m-d H:i:s") . "', '" . $uip . "', '" . $_SERVER['HTTP_USER_AGENT'] . "');";
          qSQL($sql, "gen");

          // et on en profite pour purger les logs
          $sql = "DELETE FROM z_logs WHERE DATEDIFF(curdate(), z_logs.date)>31;";
          qSQL($sql, "gen");
          // ainsi que les sessions qui ont une date antérieure à 1 jour
          $sql = "DELETE FROM z_sessions WHERE DATEDIFF(curdate(), z_sessions.date_modified)>1;";
          qSQL($sql, "gen");

        }
      }
    } else {
      //! c'est la page de Login
    }
  }

  function getUserInfos($leScript, $Conf) {
    $sql = "SELECT s.data, s.ip, s.browser, u.* FROM z_sessions s INNER JOIN users u ON s.sid='" . session_id() . "' AND s.fk_user=u.rowid;";
    $res = qSQL($sql, "gen");
    if ($res instanceof PDOStatement) {
      $this->_user = $res->fetch(PDO::FETCH_ASSOC);
    } else {
      $this->_user = false;
    }
    if (empty($this->_user)) {
      eLog('Erreur Session.getUserInfos User inconnu dans Session ' . session_id());
      $this->_user = FALSE;
    } else {
      //! Il faut tester l'adresse IP et le browser : si différence, laisser passer mais alerte.

      if (!empty($_SERVER["HTTP_CLIENT_IP"])) {
        //check for ip from share internet
        $uip = $_SERVER["HTTP_CLIENT_IP"];
      } elseif (!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) {
        // Check for the Proxy User
        $uip = $_SERVER["HTTP_X_FORWARDED_FOR"];
      } else {
        $uip = $_SERVER["REMOTE_ADDR"];
      }

      if ($uip != $this->_user["ip"]) {
        eLog("Erreur cet utilisateur " . $this->_user["username"] . " a changé d'IP : " . $uip . " au lieu de " . $this->_user["ip"]);
      }
      if ($this->_user["browser"] != $_SERVER['HTTP_USER_AGENT']) {
        eLog("Erreur cet utilisateur " . $this->_user["username"] . " a changé de navigateur");
      }
    }
    // PDO ne nécessite pas de free()
  }

  public function set_data($cle, $valeur) {
    //! Ajoute ou met à jour la valeur d'une clé contenue dans z_sessions.data
    //! ======================================================================
    //! 1. on récupère le tableau contenu dans z_sessions.data
    global $Conf;
    $tabdata = $this->get_data();
    //! 2. on ajoute ou met à jour ce tableau avec la clé et la valeur passés en paramètre
    $tabdata[$cle] = $valeur;
    //! 3. on transforme ce tableau mis à jour en string
    //! base64_encode pour pouvoir embarquer des valeurs avec des " ou ' sans gérer des anti-slashes
    $data = base64_encode(serialize($tabdata));
    //! 4. on enregistre ce tableau
    $sql = "UPDATE z_sessions s SET s.data='" . $data . "' WHERE s.sid='" . session_id() . "';";
    qSQL($sql, "gen");
  }

  public function get_data($cle = "") {
    //! Récupère le contenu de z_sessions.data et le retourne en tableau
    //! ================================================================
    global $Conf;
    $sql = "SELECT s.data FROM z_sessions s WHERE s.sid='" . session_id() . "';";
    $res = qSQL($sql, "gen");
    if ($res instanceof PDOStatement) {
      $rec = $res->fetch(PDO::FETCH_ASSOC);
    } else {
      $rec = false;
    }
    if ($rec["data"] == "") {
      $tabdata = array();
    } else {
      //! base64_decode pour pouvoir embarquer des valeurs avec des " ou ' sans gérer des anti-slashes
      $tabdata = unserialize(base64_decode($rec["data"]));
    }
    if ($cle == "") {
      //! si la clé est vide, on récupère tout le contenu de data
      return $tabdata;
    } else {
      //! si une clé est spécifiée, on la teste et on récupère son contenu
      if (isset($tabdata[$cle])) {
        // debug("session->get_data récupère la valeur de la clé ".$cle." : ".$tabdata[$cle]);
        $valeur = $tabdata[$cle];
        return $valeur;
      } else {
        return 0;
      }
    }
  }

  public function set_a($niveau, $valeur) {
    //! Met à jour la valeur du champ z_sessions.ax
    if ($niveau >= 0 && $niveau < 10) {
      $sql = "UPDATE z_sessions s SET s.a" . $niveau . "='" . $valeur . "' WHERE s.sid='" . session_id() . "';";
      qSQL($sql, "gen");
    }
  }

  public function get_a($niveau) {
    //! Récupère la valeur du champ z_sessions.ax
    if ($niveau >= 0 && $niveau < 10) {
      $sql = "SELECT s.a" . $niveau . " as data FROM z_sessions s WHERE s.sid='" . session_id() . "';";
      $res = qSQL($sql, "gen");
      if ($res instanceof PDOStatement) {
        $rec = $res->fetch(PDO::FETCH_ASSOC);
      } else {
        $rec = false;
      }
      // PDO ne nécessite pas de free()
      return $rec["data"];
    }
  }

  public function del_data($cle) {
    //! Supprime une clé contenue dans z_sessions.data
    //! ======================================================================
    //! 1. on récupère le tableau contenu dans z_sessions.data
    global $Conf;
    $tabdata = $this->get_data();
    //! 2. on supprime la clé passée en paramètre de ce tableau
    unset($tabdata[$cle]);
    //! 3. on transforme ce tableau mis à jour en string
    $data = serialize($tabdata);
    //! 4. on enregistre ce tableau
    $sql = "UPDATE z_sessions s SET s.data='" . $data . "' WHERE s.sid='" . session_id() . "';";
    qSQL($sql, "gen");
  }

}