#!/usr/bin/perl

# v0.8rc2 Programme de Guillaume Lehmann. Programme sous licence GPL v3 (www.gnu.org).

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
# AFFICHAGE, HISTORISATION DES REMONTÉES DES SCANS, #
#  DESSIN DE L'ARBORESCENCE, ALARMES DE DEBIT ET    #
#               DE CHANGEMENT D'ETAT                #
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#




use Time::localtime ;
use Date::Calc qw (Delta_DHMS) ; # À Commenter sous MS Windows et sous Ubuntu
use Date::Calc qw (Add_Delta_YMDHMS) ; # À Commenter sous MS Windows et sous Ubuntu
use DBI ;

# Package maison
use ModelePage ;
use Arborescence ;
use AlarmeDebit ;
use Historique ;
use AlarmeChgt ;


##############################################################################
# Modèle des alertes stockées dans le fichier d'historique et dans le fichier
# des dernières alertes.

# colonne 1 : Adresse IP (168.45.24.1)
# colonne 2 : Nom de la machine (Ma_tuture)
# colonne 3 : Etat global (UP, DOWN, OTHER, ...)
# colonne 4 : Numéro du port (331)
# colonne 5 : Etat du port (UP, DOWN, OTHER, ...)
# colonne 6 : Nombre d'erreurs en entrée (98765)
# colonne 7 : Nombre d'erreurs en sortie (987)
# colonne 8 : Débit en entrée (288844)
# colonne 9 : Débit en sortie (5511)
# colonne 10 : Date de l'analyse effectuée par le module de scan (20040428034834)
# colonne 11 : Nom du site hébergeant l'équipement
# colonne 12 : Groupe 1 où se trouve la machine (France)
# colonne 13 : Groupe 2 (sous Groupe 1) où se trouve la machine (Sud_Ouest)
# colonne 14 : Groupe 3 (sous Groupe 2) où se trouve la machine (Toulouse)
# colonne 15 : Groupe 4 (sous Groupe 3) où se trouve la machine (Site_3)
# colonne 16 : Groupe 5 (sous Groupe 4) où se trouve la machine (Bat_Vic)
##############################################################################




##############################################################################
# Modèle des alarmes dans le fichier des "alarmes non acquitées".

# colonne 1 : AdresseIP de la machine
# colonne 2 : Nom
# colonne 3 : Site hébergeant l'équipement
# colonne 4 : Ancien état
# colonne 5 : Nouvel état
# colonne 6 : Date au format AAAAMMJJHHMMSS
##############################################################################


#############################
# INITIALISATION HORS BOUCLE

# Ouverture du fichier.
open(HISTORIQUE, '>>Historique.txt') || die "!! Problème à  l'ouverture du fichier d'archivage" ;

# En-tete en première ligne du fichier seulement.
print HISTORIQUE "AdresseIP  Nom  Etat  NumPort EtatPort NbErrIn  NbErrOut  DebIn  DebOut DateCtrl  Site  Niveau1  Niveau2  Niveau3  Niveau4  Niveau5\n" ;


# Fermeture du fichier
close(HISTORIQUE) ;


# Récupération des identifiants pour accéder à  la base de données.
open(ACCESBD, 'AccesBD.txt') || die "Problème à  l'accès au fichier AccesBD.txt" ;
$resultat = <ACCESBD> ;
close (ACCESBD) ;
($database, $hostname, $login, $password, $typBD) = $resultat =~ /^(\w*)\s*(\w*)\s*(\w*)\s*(\w*)\s*(\w*)\s*$/ ;
$dsn = "DBI:$typBD:database=$database;host=$hostname" ;

# Connexion à  la base de données.
$dbh = DBI->connect($dsn, $login, $password) ;

# Ouverture du fichier de configuration.
open(CONFARBO, 'ConfArborescence.txt') ;

# Purge de la BD.
$dbh->do("DELETE FROM Conteneurs ;") ;

# Lecture de chaque ligne du fichier de configuration.
while ($ligneconf = <CONFARBO>) {
($ConteneurNom, $ConteneurNiv1, $ConteneurNiv2, $ConteneurNiv3, $ConteneurNiv4, $ConteneurNiv5) = $ligneconf =~ /^(\S*)\s*(\d*)_(\d*)_(\d*)_(\d*)_(\d*)\s*$/ ;

$CaseTab = $ConteneurNiv1."_".$ConteneurNiv2."_".$ConteneurNiv3."_".$ConteneurNiv4."_".$ConteneurNiv5 ;

# Insertion des informations dans la BD.
$dbh->do("INSERT INTO Conteneurs(Cont_Nom, Cont_Etat, Cont_Niveau1, Cont_Niveau2, Cont_Niveau3, Cont_Niveau4, Cont_Niveau5) VALUES (\"$ConteneurNom\", \"OTHER\", $ConteneurNiv1, $ConteneurNiv2, $ConteneurNiv3, $ConteneurNiv4, $ConteneurNiv5);") ;

} # fin du while de lecture du fichier d'arborescence


# Fermeture du fichier et de la base de données
$dbh->disconnect() ;
close(CONFARBO) ;
#############################


#######################################################
# RECAPITULATIF DE L'ARBORESCENCE DANS UN FICHIER
##> Dessiner dans un fichier l'arborescence telle que définie dans
##>le fichier de configuration.

Arborescence::main() ;
#######################################################


## BOUCLE DE TRAITEMENT ##
while (TRUE) {

# Nettoyer l'affichage de la console.
    print ".. Debut du programme\n" ;

#################
# INITIALISATION
# Calcul de la date et heure actuelle pour l'insérer dans la page html.
$DatePageAnnee = localtime->year + 1900 ;
$DatePageMois = localtime->mon + 1 ; # +1 sinon a un mois de retard
$DatePageJour = localtime->mday ;
$DatePageHeure = localtime->hour ;
$DatePageMinute = localtime->min ;
$DatePageSeconde = localtime->sec ;


# Effacer le contenu de la page html.
open(PAGE, '>Surv.html') || die "!! Problème à  l'initialisation de la page html" ;

# Création du début de la page html.
print PAGE "<html>\n" ;
print PAGE "<head>\n" ;
print PAGE "<meta http-equiv=\"content-Type\" content=\"text/html; charset=iso-8859-1\">\n" ;
print PAGE "<meta content=\"30;\" http-equiv=\"Refresh\"> \n" ;
print PAGE "<style type=\"text/css\">\n" ;
print PAGE "body {margin: 0; padding: 0 } /* marges intérieures et extérieures */\n" ;

print PAGE "h4 { /* style des en-tête et en-pied */\n" ;
print PAGE "  font-size: 40px; /* taille de la police */\n" ;
print PAGE "  margin: 0; /* pas de marge : colle aux bords de l'écran */\n" ;
print PAGE "  background-color: #F0F5FF; /* couleur de fonds */\n" ;
    print PAGE "  color: black ;\n" ;
print PAGE "  text-align:center ; /* le texte est centré */\n" ;
print PAGE "  border-top: 3px solid black; /* style de l'encadrement haut */\n" ;
print PAGE "  border-bottom: 3px solid black} /* style de l'encadrement bas */\n" ;

print PAGE "h5 { /* style des en-tête et en-pied */\n" ;
print PAGE "  font-size: 20px; /* taille de la police */\n" ;
print PAGE "  margin: 0; /* pas de marge : colle aux bords de l'écran */\n" ;
print PAGE "  background-color: #F0F5FF; /* couleur de fonds */\n" ;
    print PAGE "  text-align:center ; /* le texte est centré */\n" ;
print PAGE "  border-top: 3px solid #DADADA; /* style de l'encadrement haut */\n" ;
    print PAGE "  border-bottom: 1px dashed #DADADA} /* style de l'encadrement bas */\n" ;


    print PAGE ".container { /* boite qui entoure les 3 colonnes */\n" ;
print PAGE "  background: #F8F8F8 url(\"./images/fond.jpg\"); /* couleur de fond */\n" ;
    print PAGE "  margin:0 ; padding:0} /* marges intérieures et extérieures à  0 */\n" ;

print PAGE ".gauche {\n" ;
print PAGE "   position: absolute;\n" ;
print PAGE "   left: 10px; /* démarre à  10 pixels de la gauche de la boite parent */\n" ;
print PAGE "   width: 10%;\n" ;
print PAGE "   border:dashed 1px orange;\n" ;
print PAGE "   background-color: #e8ffea; \n" ;
    print PAGE "}\n" ;

print PAGE ".centre {\n" ;
print PAGE "   margin: 0 20% 0 11%; /* marges gauche et droite, pour la place des 2 autres colonnes */\n" ;
print PAGE "   border-left: 3px solid black; /* bordure gauche */\n" ;
print PAGE "   border-right: 3px solid black; /* bordure droite */\n" ;
print PAGE "  padding: 10px; /* marge intérieure - indispensable */\n" ;
print PAGE "}\n" ;

print PAGE ".droite {\n" ;
print PAGE "  position: absolute; /* positionné par rapport à  la boite parent (ici .container) */\n" ;
print PAGE "  right: 10px; /* démarre à  10 pixels de la droite de la boite parent */\n" ;
print PAGE "  width: 19%; /* largeur */\n" ;
print PAGE "   border:dashed 1px orange;\n" ;
print PAGE "   background-color: #e8ffea; \n" ;
    print PAGE "}\n" ;



print PAGE "</style>\n" ;
print PAGE "<title>Supervision avec FEDSnmp</title>\n" ;
print PAGE "</head>\n" ;

print PAGE "<body>\n" ;
print PAGE "<div class=\"container\">\n" ;

print PAGE "<h4>Supervision avec FEDSnmp</h4>\n" ;




print PAGE "<div class=\"gauche\">\n" ;
print PAGE " <h5>MENU</h5>\n" ;
print PAGE "<p><a href=\"Surv.html\">Page d'accueil</a></p>\n" ;
print PAGE "<p><a href=\"Historique.txt\">Historique</a></p>\n" ;
print PAGE "<p><a href=\"ResAlarmesChgt.html\">Alarmes d'&eacute;tat non acquit&eacute;es</a></p>\n" ;
print PAGE "<p><a href=\"ResAlarmesDebit.html\">Alarmes de d&eacute;bit non acquit&eacute;es</a></p>\n" ;
print PAGE "<p><a href=\"ConfSurvScanPre.txt\">Fichier de configuration 1</a></p>\n" ;
print PAGE "<p><a href=\"ConfSurvScanSec.txt\">Fichier de configuration 2</a></p>\n" ;
print PAGE "<p><a href=\"ConfSurvScanTer.txt\">Fichier de configuration 3</a></p>\n" ;
print PAGE "<p><a href=\"ConfSurvScanQua.txt\">Fichier de configuration 4</a></p>\n" ;
print PAGE "<p><a href=\"Arborescence.txt\">Arborescence (texte)</a></p>\n" ;
print PAGE "<p><a href=\"Arborescence.jpeg\">Arborescence (jpeg)</a></p>\n" ;
print PAGE "<p><a href=\"pagesHtml\">R&eacute;pertoire des pages html</a></p>\n" ;
print PAGE "<p><a href=\"Carte.html\">Carte du r&eacute;seau (no code)</a></p>\n" ;
print PAGE "<p><a href=\"README\">README</a></p>\n" ;
print PAGE "</div>\n" ;

print PAGE "<img class=\"droite\" src=\"FondCentre.jpg\" alt=\"\">\n" ;
print PAGE "<div class=\"droite\">\n" ;
print PAGE "<h5>Remarques :</h5>\n" ;
print PAGE "<p>FEDSnmp est un outil de supervision.</p>\n" ;
print PAGE "<p>Licence, documentation, demande d'aide, etc : voir le site <a href=\"http://lehmann.free.fr/Contributions/FEDSnmp/\">http://lehmann.free.fr</a></p>\n" ;
print PAGE "Il est conseill&eacute; de lire le fichier README. Il contient de nombreuses informations sur l'utilisation et le fonctionnement g&eacute;n&eacute;ral du logiciel.\n" ;
print PAGE "</div>\n" ;

print PAGE "<div class=\"centre\">\n" ;
print PAGE "<H3>G&eacute;n&eacute;ration automatique de la page le $DatePageJour/$DatePageMois/$DatePageAnnee &agrave; $DatePageHeure:$DatePageMinute.$DatePageSeconde</H3>\n" ;


close(PAGE) ;
#################


# Connexion à la base de données.
$dbh = DBI->connect($dsn, $login, $password) ;

# Mettre OTHER aux élements qui n'ont pas été supervisés depuis plus de 10 min.
($DateMinAnnee, $DateMinMois, $DateMinJour, $DateMinHeure, $DateMinMinute, $DateMinSeconde) = Add_Delta_YMDHMS($DatePageAnnee, $DatePageMois, $DatePageJour, $DatePageHeure, $DatePageMinute, $DatePageSeconde, 0, 0, 0, 0, -10, 0);
# Convertir les mois/jours/heures/minutes qui sont sur un chiffre en 2 chiffres.
if ($DateMinMois =~ /^.$/) {
    $DateMinMois = "0".$DateMinMois ;
}
if ($DateMinJour =~ /^.$/) {
    $DateMinJour= "0".$DateMinJour ;
}
if ($DateMinHeure =~ /^.$/) {
    $DateMinHeure= "0".$DateMinHeure ;
}
if ($DateMinMinute =~ /^.$/) {
    $DateMinMinute= "0".$DateMinMinute ;
}
if ($DateMinSeconde =~ /^.$/) {
    $DateMinSeconde= "0".$DateMinSeconde ;
}

$DateMin = $DateMinAnnee.$DateMinMois.$DateMinJour.$DateMinHeure.$DateMinMinute.$DateMinSeconde ;    

$dbh->do("UPDATE Elements SET Elem_Etat=\"OTHER\" WHERE Elem_Date < $DateMin ;") ;



##############################################################
# METTRE A JOUR LA COHÉRENCE DES ÉTATS DES SITES PÈRES<-->FILS

# Initialisation des états des sites.
$dbh->do("UPDATE Conteneurs SET Cont_Etat=\"OTHER\" ;") ;

# L'état de chaque élément déteint sur son site d'appartenance (prise en compte des priorités entre les états).
$ResReqTeinte = $dbh->prepare("SELECT * from Elements ;") ;
$ResReqTeinte->execute() ;

while ($ResReqTeinteLign = $ResReqTeinte->fetchrow_hashref()) {
    if ($ResReqTeinteLign->{'Elem_Etat'} eq "UP") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"$ResReqTeinteLign->{'Elem_Etat'}\" WHERE (Cont_Nom = \"$ResReqTeinteLign->{'Elem_Site'}\" AND Cont_Etat NOT LIKE \"DOWN\" AND Cont_Etat NOT LIKE \"MIDDLE\") ;") ;
    }
    if ($ResReqTeinteLign->{'Elem_Etat'} eq "MIDDLE") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"$ResReqTeinteLign->{'Elem_Etat'}\" WHERE (Cont_Nom = \"$ResReqTeinteLign->{'Elem_Site'}\" AND Cont_Etat NOT LIKE \"DOWN\") ;") ;
    }
    if ($ResReqTeinteLign->{'Elem_Etat'} eq "DOWN") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"$ResReqTeinteLign->{'Elem_Etat'}\" WHERE Cont_Nom = \"$ResReqTeinteLign->{'Elem_Site'}\" ;") ;
    }
    
} # fin while $ResReqTeinteLign = $ResReqTeinte->fetchrow_hashref()

$ResReqTeinte->finish() ;


# Remonter aux pères l'état du site (prise en compte des priorités).
## Remontée du niveau 5 au niveau 4
$ResReqTrsf5to4 = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1 != 0 AND Cont_Niveau2 != 0 AND Cont_Niveau3 != 0 AND Cont_Niveau4 != 0 AND Cont_Niveau5 != 0 ;") ;
$ResReqTrsf5to4->execute() ;
while ($ResReqTrsf5to4Lign = $ResReqTrsf5to4->fetchrow_hashref()) {
    if ($ResReqTrsf5to4Lign->{'Cont_Etat'} eq "UP") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"UP\" WHERE Cont_Niveau1 = $ResReqTrsf5to4Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf5to4Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf5to4Lign->{'Cont_Niveau3'} AND Cont_Niveau4 = $ResReqTrsf5to4Lign->{'Cont_Niveau4'} AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" AND Cont_Etat NOT LIKE \"MIDDLE\" ;") ;
    }
    if ($ResReqTrsf5to4Lign->{'Cont_Etat'} eq "MIDDLE") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"MIDDLE\" WHERE Cont_Niveau1 = $ResReqTrsf5to4Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf5to4Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf5to4Lign->{'Cont_Niveau3'} AND Cont_Niveau4 = $ResReqTrsf5to4Lign->{'Cont_Niveau4'} AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" ;") ;
    }
    if ($ResReqTrsf5to4Lign->{'Cont_Etat'} eq "DOWN") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"DOWN\" WHERE Cont_Niveau1 = $ResReqTrsf5to4Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf5to4Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf5to4Lign->{'Cont_Niveau3'} AND Cont_Niveau4 = $ResReqTrsf5to4Lign->{'Cont_Niveau4'} AND Cont_Niveau5 = 0  ;") ;
    }
} # fin while $ResReqTrsf5to4Lign = $ResReqTrsf5to4->fetchrow_hashref()
$ResReqTrsf5to4->finish() ;




## Remontée du niveau 4 au niveau 3
$ResReqTrsf4to3 = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1 != 0 AND Cont_Niveau2 != 0 AND Cont_Niveau3 != 0 AND Cont_Niveau4 != 0 AND Cont_Niveau5 = 0 ;") ;
$ResReqTrsf4to3->execute() ;
while ($ResReqTrsf4to3Lign = $ResReqTrsf4to3->fetchrow_hashref()) {
    if ($ResReqTrsf4to3Lign->{'Cont_Etat'} eq "UP") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"UP\" WHERE Cont_Niveau1 = $ResReqTrsf4to3Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf4to3Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf4to3Lign->{'Cont_Niveau3'} AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" AND Cont_Etat NOT LIKE \"MIDDLE\" ;") ;
    }
    if ($ResReqTrsf4to3Lign->{'Cont_Etat'} eq "MIDDLE") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"MIDDLE\" WHERE Cont_Niveau1 = $ResReqTrsf4to3Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf4to3Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf4to3Lign->{'Cont_Niveau3'} AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" ;") ;
    }
    if ($ResReqTrsf4to3Lign->{'Cont_Etat'} eq "DOWN") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"DOWN\" WHERE Cont_Niveau1 = $ResReqTrsf4to3Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf4to3Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = $ResReqTrsf4to3Lign->{'Cont_Niveau3'}  AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 ;") ;
    }
} # fin while $ResReqTrsf4to3Lign = $ResReqTrsf4to3->fetchrow_hashref()
$ResReqTrsf4to3->finish() ;


## Remontée du niveau 3 au niveau 2
$ResReqTrsf3to2 = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1 != 0 AND Cont_Niveau2 != 0 AND Cont_Niveau3 != 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 ;") ;
$ResReqTrsf3to2->execute() ;
while ($ResReqTrsf3to2Lign = $ResReqTrsf3to2->fetchrow_hashref()) {
    if ($ResReqTrsf3to2Lign->{'Cont_Etat'} eq "UP") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"UP\" WHERE Cont_Niveau1 = $ResReqTrsf3to2Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf3to2Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" AND Cont_Etat NOT LIKE \"MIDDLE\" ;") ;
    }
    if ($ResReqTrsf3to2Lign->{'Cont_Etat'} eq "MIDDLE") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"MIDDLE\" WHERE Cont_Niveau1 = $ResReqTrsf3to2Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf3to2Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" ;") ;
    }
    if ($ResReqTrsf3to2Lign->{'Cont_Etat'} eq "DOWN") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"DOWN\" WHERE Cont_Niveau1 = $ResReqTrsf3to2Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = $ResReqTrsf3to2Lign->{'Cont_Niveau2'} AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0  ;") ;
    }
} # fin while $ResReqTrsf3to2Lign = $ResReqTrsf3to2->fetchrow_hashref()
$ResReqTrsf3to2->finish() ;


## Remontée du niveau 2 au niveau 1
$ResReqTrsf2to1 = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1 != 0 AND Cont_Niveau2 != 0 AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 ;") ;
$ResReqTrsf2to1->execute() ;
while ($ResReqTrsf2to1Lign = $ResReqTrsf2to1->fetchrow_hashref()) {
    if ($ResReqTrsf2to1Lign->{'Cont_Etat'} eq "UP") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"UP\" WHERE Cont_Niveau1 = $ResReqTrsf2to1Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = 0 AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" AND Cont_Etat NOT LIKE \"MIDDLE\" ;") ;
    }
    if ($ResReqTrsf2to1Lign->{'Cont_Etat'} eq "MIDDLE") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"MIDDLE\" WHERE Cont_Niveau1 = $ResReqTrsf2to1Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = 0 AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 AND Cont_Etat NOT LIKE \"DOWN\" ;") ;
    }
    if ($ResReqTrsf2to1Lign->{'Cont_Etat'} eq "DOWN") {
	$dbh->do("UPDATE Conteneurs SET Cont_Etat = \"DOWN\" WHERE Cont_Niveau1 = $ResReqTrsf2to1Lign->{'Cont_Niveau1'} AND Cont_Niveau2 = 0 AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 ;") ;
    }
} # fin while $ResReqTrsf2to1Lign = $ResReqTrsf2to1->fetchrow_hashref()
$ResReqTrsf2to1->finish() ;
##############################################################




#################
# Calculs divers

# Calcul du débit en entrée
$ResReq = $dbh->prepare("SELECT * FROM Elements ;") ;
$ResReq->execute() ;

while ($ResReqLign = $ResReq->fetchrow_hashref()) {
    # Retouver l'ancien enregistrement dans AncienEnreg du tuple en train d'être analysé.
    $ResReqBis = $dbh->prepare("SELECT Anci_AncienneDate, Anci_AncienNbOctetEntree, Anci_AncienNbOctetSortie FROM AncienEnreg WHERE AncienEnreg.Anci_Nom LIKE \"$ResReqLign->{'Elem_Nom'}\" AND AncienEnreg.Anci_AdresseIP LIKE \"$ResReqLign->{'Elem_AdresseIP'}\" AND AncienEnreg.Anci_NumeroPort=$ResReqLign->{'Elem_NumeroPort'} ;") ;
    
    $ResReqBis->execute() ;
    $ResReqBisLign = $ResReqBis->fetchrow_hashref() ;

    # Découpage de la date pour calcul du temps écoulé entre les 2 analyses.
    ($DateRecenteAnnee, $DateRecenteMois, $DateRecenteJour, $DateRecenteHeure, $DateRecenteMinute, $DateRecenteSeconde) = $ResReqLign->{'Elem_Date'} =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
    ($DateAncienneAnnee, $DateAncienneMois, $DateAncienneJour, $DateAncienneHeure, $DateAncienneMinute, $DateAncienneSeconde) = $ResReqBisLign->{'Anci_AncienneDate'} =~ /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/;
    
    # Découpage du délai entre les 2 analyses en années, mois, jours, ...
    ($DeltaJour, $DeltaHeure, $DeltaMinute, $DeltaSeconde) = Delta_DHMS($DateAncienneAnnee, $DateAncienneMois, $DateAncienneJour, $DateAncienneHeure, $DateAncienneMinute, $DateAncienneSeconde, $DateRecenteAnnee, $DateRecenteMois, $DateRecenteJour, $DateRecenteHeure, $DateRecenteMinute, $DateRecenteSeconde) ; # à commenter sous MS Windows et Ubuntu
    
    # Calcul du delai en secondes. Si < 1, alors =1 pour éviter une division par zéro ensuite.
#	$Delai = ($DeltaJour * 86400) + ($DeltaHeure * 3600) + ($DeltaMinute * 60) + $DeltaSeconde ; # à commenter sous MS Windows et Ubuntu
    
    $Delai = (($DateRecenteJour * 86400) + ($DateRecenteHeure * 3600) + ($DateRecenteMinute * 60) + ($DateRecenteSeconde)) - (($DateAncienneJour * 86400) + ($DateAncienneHeure * 3600) + ($DateAncienneMinute * 60) + ($DateAncienneSeconde)) ; # à décommenter sous MS Windows et Ubuntu
    

    if ($Delai < 1) {
	$Delai = 1 ;
    }
    
    # On ne fait les calculs que si l'équipement et le port sont actifs
    if ($MachineEtat eq "UP" and $MachineEtatPort eq "UP") {
	
	# Calcul du débit en entrée
	$DebitEntree = $ResReqLign->{'Elem_NbOctetEntree'} - $ResReqBisLign->{'Anci_AncienNbOctetEntree'} / $Delai ;
	if ($DebitEntree < 0) { # Ne pas avoir des débits négatifs (dà»s à  des retours de compteurs ifInOctets)
	    $DebitEntree = 0 ;
	}
	
	
	# Calcul du débit en sortie
	$DebitSortie = $ResReqLign->{'Elem_NbOctetSortie'} - $ResReqBisLign->{'Anci_AncienNbOctetSortie'} / $Delai ;
	if ($DebitSortie < 0) { # Ne pas avoir des débits négatifs (dà»s à  des retours de compteurs ifOutOctets)
	    $DebitSortie = 0 ;
	}
    } # fin if équipement et port actifs
    else {
	$DebitEntree = 0 ;
	$DebitSortie = 0 ;
    }
    
    # Entrée des résultats des calculs dans la BD.
    $dbh->do("UPDATE Elements SET Elem_DebitEntree=$DebitEntree, Elem_DebitSortie=$DebitSortie WHERE Elem_Nom LIKE \"$ResReqLign->{'Elem_Nom'}\" AND Elem_AdresseIP LIKE \"$ResReqLign->{'Elem_AdresseIP'}\" AND Elem_NumeroPort=$ResReqLign->{'Elem_NumeroPort'} ;") ;

    # Fermeture des requêtes SQL.
    $ResReqBis->finish() ;

} # Fin du while qui effectue une série de calcul pour chaque ligne.

# Fermeture des requêtes SQL inutiles
$ResReq->finish() ;
$dbh->disconnect() ;
#################


#############################
# ARCHIVAGE DES INFORMATIONS
##> Les informations de débits, du nombre d'erreurs, etc sont archivées dans un fichier.

Historique::main() ;

#############################




##########################################
# LISTER TOUTES LES MACHINES AVEC ALARMES
##> Seules les machines ayant un "problème" sont listées, sans tenir compte 
##>de la hiérarchie.
##> Des informations diverses sont données pour chaque.
##> Un gif de couleur permet de voir rapidement l'état des machines.

# Calcul du nombre d'alarmes à remonter pour savoir si on les affiche dans la page principale ou si on met un lien vers la page d'affichage.
$dbh = DBI->connect($dsn, $login, $password) ;
#$ResReq = $dbh->prepare("SELECT count(*) FROM Elements WHERE Elem_Etat NOT LIKE \"UP\" ;") ;
#$ResReq->execute() ;
#$ResReqLign = $ResReq->fetchrow_hashref() ;
#if ($ResReqLign->{'count(*)'} >= 50) {
#    open(PAGEORIGIN, 'Surv.html') || die "!! Problème à l'ouverture de la page html" ;
#    open(PAGE, '>SurvAlm.html') || die "!! Problème à  l'ouverture de la page html" ;
#    while ($varTransfert = <PAGERORIGIN>) {
#	print PAGE $varTransfert ;
#    }
#    close(PAGEORIGIN) ;
#}
#else {
#    # Ouverture de la page html déjà  initialisée.
#    open(PAGE, '>>Surv.html') || die "!! Problème à  l'ouverture de la page html" ;
#}
#$ResReq->finish() ;

# Ouverture de la page html déjà  initialisée.
open(PAGE, '>>Surv.html') || die "!! Problème à  l'ouverture de la page html" ;

# Insertion dans la page html de la date du dernier relevé effectué : on regarde la date la plus récente dans la BD.
#$dbh = DBI->connect($dsn, $login, $password) ;
$ResReq = $dbh->prepare("SELECT MAX(Elem_Date) FROM Elements ;") ;
$ResReq->execute() ;
$ResReqLign = $ResReq->fetchrow_hashref() ;

($DerReleveAnnee, $DerReleveMois, $DerReleveJour, $DerReleveHeure, $DerReleveMinute, $DerReleveSeconde) = $ResReqLign->{'MAX(Elem_Date)'} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ;

print PAGE "\n<H3>Dernier relev&eacute; effectu&eacute; le : $DerReleveJour/$DerReleveMois/$DerReleveAnnee &agrave; $DerReleveHeure:$DerReleveMinute.$DerReleveSeconde</H3>\n" ;


# Début du tableau contenant les alertes.
print PAGE "\n<h5>LISTING</h5>" ;
print PAGE "\n<BODY>\n<table cellpadding=\"2\" cellspacing=\"2\" border=\"1\" \n";
print PAGE "style=\"text-align: center; width: 100% ; background-color: rgb(204, 204, 255);\"> \n" ;
print PAGE "<tbody> \n" ;

# En-tete du tableau contenant les alertes.
print PAGE "\n<TR style=\"color: rgb(0, 0, 0);\">\n<TD>Niveau</TD>\n<TD>Adresse IP</TD>\n<TD>Nom</TD>\n<TD>Etat</TD>\n<TD>Port</TD>\n<TD>Arborescence</TD>\n<TD>Heure contr&ocirc;le</TD>\n</TR> \n" ;

# Fermeture de la requête SQL.
$ResReq->finish() ;

$ResReq = $dbh->prepare("SELECT * FROM Elements WHERE Elem_Etat NOT LIKE \"UP\" ;") ;
$ResReq->execute() ;
while ($ResReqLign = $ResReq->fetchrow_hashref()) {
    
    # Découpage de la date pour la suite.
    ($ReleveAnnee, $ReleveMois, $ReleveJour, $ReleveHeure, $ReleveMinute, $ReleveSeconde) = $ResReqLign->{'Elem_Date'} =~ /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ ;
    
    # Composition de l'arborescence du site pour la suite.
    $ResReqBis = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Nom LIKE \"$ResReqLign->{'Elem_Site'}\" ;") ;  
    $ResReqBis->execute() ;
    $ResReqBisLign = $ResReqBis->fetchrow_hashref() ;
    
    # Si machine down, alors mettre le bon gif et donner les infos.
    if ($ResReqLign->{'Elem_Etat'} eq "DOWN") {
	print PAGE "\n<TR style=\"color: rgb(0, 0, 0);\">\n<TD><img src=\"images/down.jpg\" alt=\"message critique\"</TD>\n" ;
	## Écriture de la ligne html donnant les informations de l'alerte remontée.
	print PAGE "<TD>", $ResReqLign->{'Elem_AdresseIP'}, "</TD> \n <TD>", $ResReqLign->{'Elem_Nom'}, "</TD>\n <TD>", $ResReqLign->{'Elem_Etat'}, "</TD>\n <TD>", $ResReqLign->{'Elem_NumeroPort'} , "</TD>\n <TD>", $ResReqLign->{'Elem_Site'}, ":", $ResReqBisLign->{'Cont_Niveau1'}, "/", $ResReqBisLign->{'Cont_Niveau2'}, "/", $ResReqBisLign->{'Cont_Niveau3'}, "/", $ResReqBisLign->{'Cont_Niveau4'}, "/", $ResReqBisLign->{'Cont_Niveau5'}, "</TD>\n <TD>", $ReleveJour, "/", $ReleveMois, "/", $ReleveAnnee, "<BR>", $ReleveHeure, "h", $ReleveMinute, ".", $ReleveSeconde, "</TD>\n</TR>\n\n" ;
    }
    
    # Si machine down, alors mettre le bon gif et donner les infos.
    if ($ResReqLign->{'Elem_Etat'} eq "MIDDLE") {
	print PAGE "<TR style=\"color: rgb(0, 0, 0);\">\n<TD><img src=\"images/middle.jpg\" alt=\"message moyen\"</TD>\n" ;
	## Écriture de la ligne html donnant les informations de l'alerte remontée.
	print PAGE "<TD>", $ResReqLign->{'Elem_AdresseIP'}, "</TD> \n <TD>", $ResReqLign->{'Elem_Nom'}, "</TD>\n <TD>", $ResReqLign->{'Elem_Etat'}, "</TD>\n <TD>", $ResReqLign->{'Elem_NumeroPort'} , "</TD>\n <TD>", $ResReqLign->{'Elem_Site'}, ":", $ResReqBisLign->{'Cont_Niveau1'}, "/", $ResReqBisLign->{'Cont_Niveau2'}, "/", $ResReqBisLign->{'Cont_Niveau3'}, "/", $ResReqBisLign->{'Cont_Niveau4'}, "/", $ResReqBisLign->{'Cont_Niveau5'}, "</TD>\n <TD>", $ReleveJour, "/", $ReleveMois, "/", $ReleveAnnee, "<BR>", $ReleveHeure, "h", $ReleveMinute, ".", $ReleveSeconde, "</TD></TR>\n\n" ;
    }
    
    # Si machine down, alors mettre le bon gif et donner les infos.
    if ($ResReqLign->{'Elem_Etat'} eq "OTHER") {
	print PAGE "<TR style=\"color: rgb(0, 0, 0);\">\n<TD><img src=\"images/other.jpg\" alt=\"message non-r&eacute;f&eacute;renc&eacute;\"</TD>\n" ;
	## Écriture de la ligne html donnant les informations de l'alerte remontée.
	print PAGE "<TD>", $ResReqLign->{'Elem_AdresseIP'}, "</TD> \n <TD>", $ResReqLign->{'Elem_Nom'}, "</TD>\n <TD>", $ResReqLign->{'Elem_Etat'}, "</TD>\n <TD>", $ResReqLign->{'Elem_NumeroPort'} , "</TD>\n <TD>", $ResReqLign->{'Elem_Site'}, ":", $ResReqBisLign->{'Cont_Niveau1'}, "/", $ResReqBisLign->{'Cont_Niveau2'}, "/", $ResReqBisLign->{'Cont_Niveau3'}, "/", $ResReqBisLign->{'Cont_Niveau4'}, "/", $ResReqBisLign->{'Cont_Niveau5'}, "</TD>\n <TD>", $ReleveJour, "/", $ReleveMois, "/", $ReleveAnnee, "<BR>", $ReleveHeure, "h", $ReleveMinute, ".", $ReleveSeconde, "</TD></TR>\n\n" ;
    }

    # Fermeture des requêtes SQL.
    $ResReqBis->finish() ;

} # fin du while de lecture du résultat des machines non UP.
# Fermeture de la base de données.
$ResReq->finish();
$dbh->disconnect ;

# Fin du tableau contenant les alertes.
print PAGE "</tbody>" ;
print PAGE "</table>" ;
## Fermeture de la page contenant les alertes (page principale si peu d'alarmes, soit page autre).
#close(PAGE) ;
## Réouverture de la page d'accueil
#open(PAGE, '>>Surv.html') || die "!! Problème à  l'ouverture de la page html" ;
##########################################






##############################################################################
# CRÉATION DES PAGES HTML REMONTANT LE RÉSULTAT DE LA SUPERVISION HIÉRARCHISÉE
##> Architecture en 5 niveaux. Les niveaux ont chacun une page html.
##> Toutes les pages d'un même niveau sont créées au même moment, 
##>même si elles n'ont pas le même père ... c'est un fait, pas une contrainte.
##> La page est automatiquement rafraîchie.

    $dbh = DBI->connect($dsn, $login, $password) ;
    
    # Création des pages de niveau 1.
    ## Connexion à  la base de données pour récupérer les sites de premier niveau.
    $ResReqNiveau = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1!=0 AND Cont_Niveau2=0 AND Cont_Niveau3=0 AND Cont_Niveau4=0 AND Cont_Niveau5=0 ;") ;
    $ResReqNiveau->execute() ;
    # Pour chaque site, on crée sa page html avec les infos sur les fils.
    while ($ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()) {
	ModelePage::main(1, $ResReqNiveauLign, $dbh) ;
      } # fin while $ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()
    $ResReqNiveau->finish() ;
    
    
    # Création des pages de niveau 2.
    ## Connexion à la base de données pour récupérer les sites de second niveau.
    $ResReqNiveau = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1!=0 AND Cont_Niveau2!=0 AND Cont_Niveau3=0 AND Cont_Niveau4=0 AND Cont_Niveau5=0 ;") ;
    $ResReqNiveau->execute() ;
    # Pour chaque site, on crée sa page html avec les infos sur les fils.
    while ($ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()) {
	ModelePage::main(2, $ResReqNiveauLign, $dbh) ;
      } # fin while $ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()
    $ResReqNiveau->finish() ;
    

    # Création des pages de niveau 3.
    ## Connexion à la base de données pour récupérer les sites de troisième niveau.
    $ResReqNiveau = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1!=0 AND Cont_Niveau2!=0 AND Cont_Niveau3!=0 AND Cont_Niveau4=0 AND Cont_Niveau5=0 ;") ;
    $ResReqNiveau->execute() ;
    # Pour chaque site, on crée sa page html avec les infos sur les fils.
    while ($ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()) {
	ModelePage::main(3, $ResReqNiveauLign, $dbh) ;
      } # fin while $ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()
    $ResReqNiveau->finish() ;


    # Création des pages de niveau 4.
    ## Connexion à  la base de données pour récupérer les sites de quatrième niveau.
    $ResReqNiveau = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1!=0 AND Cont_Niveau2!=0 AND Cont_Niveau3!=0 AND Cont_Niveau4!=0 AND Cont_Niveau5=0 ;") ;
    $ResReqNiveau->execute() ;
    # Pour chaque site, on crée sa page html avec les infos sur les fils.
    while ($ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()) {
	ModelePage::main(4, $ResReqNiveauLign, $dbh) ;
      } # fin while $ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()
    $ResReqNiveau->finish() ;


    # Création des pages de niveau 5.
    ## Connexion à  la base de données pour récupérer les sites de cinquième niveau.
    $ResReqNiveau = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1!=0 AND Cont_Niveau2!=0 AND Cont_Niveau3!=0 AND Cont_Niveau4!=0 AND Cont_Niveau5!=0 ;") ;
    $ResReqNiveau->execute() ;
    # Pour chaque site, on crée sa page html avec les infos sur les fils.
    while ($ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()) {
	ModelePage::main(5, $ResReqNiveauLign, $dbh) ;
      } # fin while $ResReqNiveauLign = $ResReqNiveau->fetchrow_hashref()
    $ResReqNiveau->finish() ;

    
    # Fermeture de la base de données.
    $dbh->disconnect ;
    



###########################################
# AFFICHER LES SITES DE NIVEAU 1 AVEC ÉTAT

# Récupération de toutes les données de tous les sites de niveau 1.
$dbh = DBI->connect($dsn, $login, $password) ;
$ResReqPeres = $dbh->prepare("SELECT * FROM Conteneurs WHERE Cont_Niveau1 != 0 AND Cont_Niveau2 = 0 AND Cont_Niveau3 = 0 AND Cont_Niveau4 = 0 AND Cont_Niveau5 = 0 ;") ;
$ResReqPeres->execute() ;

# Code html du début de la rubrique.
print PAGE "\n\n<h5>ARBORESCENCE</h5>\n" ;
print PAGE "<BODY><TABLE><TBODY>\n" ;

# Ecriture d'une ligne par site, avec indication de son état.
while ($ResReqPeresLign = $ResReqPeres->fetchrow_hashref()) {
    if ($ResReqPeresLign->{'Cont_Etat'} eq "UP") {
	print PAGE "<TR>\n<TD><IMG SRC=\"images/up.jpg\" alt=\"UP\"></TD>\n" ;
    }
    if ($ResReqPeresLign->{'Cont_Etat'} eq "MIDDLE") {
	print PAGE "<TR>\n<TD><IMG SRC=\"images/middle.jpg\" alt=\"MIDDLE\"></TD>>\n" ;
    }
    if ($ResReqPeresLign->{'Cont_Etat'} eq "DOWN") {
	print PAGE "<TR>\n<TD><IMG SRC=\"images/down.jpg\" alt=\"DOWN\"></TD>\n" ;
    }
    if ($ResReqPeresLign->{'Cont_Etat'} eq "OTHER") {
	print PAGE "<TR>\n<TD><IMG SRC=\"images/other.jpg\" alt=\"OTHER\"></TD>\n" ;
    }

    print PAGE "<TD><A HREF=\"pagesHtml/$ResReqPeresLign->{'Cont_Nom'}.html\">$ResReqPeresLign->{'Cont_Nom'}</A></TD>\n</TR>\n" ;
}

# Fin code html de la rubrique.
print PAGE "</TBODY></TABLE>" ;

# Clôture de la requête SQL.
$ResReqPeres->finish() ;
$dbh->disconnect() ;
###########################################




##############################################################################
# LISTER LES ALARMES NON ACQUITEES PAR L'UTILISATEUR
##> Enregistrer les changements d'états dans un fichier.
##> Lire le fichier ci-dessus et écrire dans la page html les alarmes.

AlarmeChgt::main() ;

# Insertion du code généré dans la page principale
open (PAGEALMCHGT, 'ResAlarmesChgt.html') || die "Problème à l'ouverture de la page de résultat des alarmes de changement d'état" ;
while ($ResAlm = <PAGEALMCHGT>) {
    print PAGE $ResAlm ;
}
close(PAGEALMCHGT) ;
##############################################################################


##############################################################################
# LISTER LES ALARMES DE DÉBIT
##> Inclure le code html du fichier ResAlarmesDebit.txt.

AlarmeDebit::main() ;

# Insertion du code généré dans la page principale
open (PAGEALMDEB, 'ResAlarmesDebit.html') || die "Problème à l'ouverture de la page de résultat des alarmes de débit" ;
while ($ResAlm = <PAGEALMDEB>) {
    print PAGE $ResAlm ;	
}
close(PAGEALMDEB) ;
##############################################################################


##############################################################################
# CLOTURE DE LA PAGE HTML
##> Signature de bas de page.
##> Fermeture du descripteur de fichier.

print PAGE "</div>\n" ; # fin de <div class="centre">

## Signature et fermeture du code html.
print PAGE "<h5>Version 0,8 rc2 (27/02/2008). Auteur : Guillaume Lehmann\n<br>\n" ;
print PAGE "Pour tout renseignement : <img src=\"images/Signature.png\" alt=\"Signature\" style=\"width: 238px; height: 32px;\"> et http://lehmann.free.fr<\h5>" ;

print PAGE "\n</div>" ; # fin de <div class="container">
print PAGE "\n</body>";
print PAGE "\n</html>";

# Fermeture du descripteur du fichier.
close(PAGE) ;
##############################################################################


print ".. Fin du programme. Nouvelle boucle dans quelques secondes.\n\n" ;
# Attente de quelques secondes avant de recommencer tout le shmilblik.
sleep 10 ;

} # fin "while (TRUE)" 
