/* ***********************IMPORTANT *********************************************
 *  Copyright (C) 2004-2007 Thierry Lagarde <tlagarde@users.sourceforge.net>
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License.
 *
 *
 *                      ********************
 *
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Library General Public License for more details.
 *
 *
 *                      ********************
 *
 *
 * You are highly encouraged to send your changes to <tlagarde@users.sourceforge.net>
 * for possible incorporation into the main distribution.
 * By sending these changes to <tlagarde@users.sourceforge.net>,
 * it is assumed that you are offering <tlagarde@users.sourceforge.net>
 * the unlimited, non-exclusive right to reuse, modify, and relicense the code.
 *
 *
 *                      ********************
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **************************************************************************************/
#include "Equipement_Port.h"
#include "Equipement.h"
#include "Equipement_Historique.h"
#include "Debug.h"
#include "Settings_Port.h"
#include "Objet.h"
#include "Com/Commun.h"
#include "Com/Communication.h"
#include "Interface/Alert_Interface.h"
#include "Modules.h"
#include "Image.h"
#include "Animation.h"
#include "Sound.h"
#include "Smtp.h"
#include "Declaration_Constante.h"
#include "Macro.h"


void Retour_Modification_Etat_Port (gpointer * Donnee)
{
	struct struct_Retour_Rachaichir_Liste_Ports *Message = (struct struct_Retour_Rachaichir_Liste_Ports *) Donnee;
	struct Struct_Liste_Reseau *Reseau = NULL;
	struct Struct_Equipement *Equipement = NULL;
	struct Struct_Modele_Objet *Objet = NULL, *Objet_Port = NULL;
	struct Struct_Port *Port_Equipement = NULL;
	gchar    *Texte_Notification = NULL;

	ERROR_if (Donnee == NULL);
	Reseau = Recupere_Pointeur_Structure_Reseau (Message->ID_Reseau);
	Objet = Recherche_Objet_Equipement (Message->ID_Equipement, Message->ID_Reseau);
	if (Objet == NULL) {
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Retour_Modification_Etat_Equipement (Equipment unknown)");
		return;
	}
	Equipement = (struct Struct_Equipement *) Objet->Pointeur_Attacher;

	Port_Equipement = Cherche_Pointeur_Port (Equipement, Message->Num_Port);
	Port_Equipement->Etat_Port = Message->Etat_Port;
	Port_Equipement->Derniere_Modification_Etat_Port = Message->Derniere_Modification_Etat_Port;


	if ((Message->ID_Reseau == Reseau_Selectionner->Id_Reseau)
		&& (Equipement == Equipement_Selectionner)
		&& (Modules_Actuel == MODULES_LISTE_PORTS)) {

		if ((Objet_Port = Recherche_Objet_Port (Message->Num_Port)) != NULL) {
			if (Port_Equipement->Alert_notification)
				Reseau->GList_Test_Etat = Supprime_Dans_Liste_Objets (Reseau->GList_Test_Etat, Objet_Port, TRUE);
			if (Port_Equipement->Etat_Port == OUVERT) {
			
				Affiche_Icone_Defaut_Objet_liste (Objet_Port, Reseau);
				Change_Couleur_Noir_Texte_liste (Objet_Port, Reseau);
			}
			else {
			
				Affiche_Icone_Defaut_Griser_Objet_liste (Objet_Port, Reseau);
				Change_Couleur_Gris_Texte_liste (Objet_Port, Reseau);
			}
		}
	}
	if (Port_Equipement->Etat_Port == OUVERT) {
		Texte_Notification = g_strdup_printf ("Port [%d] on [%s] is up", Message->Num_Port, Equipement->Adresse_Ip_Char);
		Ajouter_Historique (Equipement, Texte_Notification, HISTORIQUE_INFO);
		if (Equipement->Contact_Admin)
			Envoie_Email_Notification (Texte_Notification, Equipement->Contact_Admin);
		MYFREE (Texte_Notification);
	}
	Port_Equipement->Alert_notification = FALSE;
	Recuperation_Nb_Octet_Recu (sizeof (struct struct_Retour_Rachaichir_Liste_Ports), Reseau);
}


void Retour_Notification_Port (gpointer * Donnee)
{
	struct struct_Retour_Notification_Changement_Etat_Port *Message = (struct struct_Retour_Notification_Changement_Etat_Port *) Donnee;
	struct Struct_Modele_Objet *Objet = NULL;
	struct Struct_Liste_Reseau *Reseau = NULL;
	struct Struct_Equipement *Equipement = NULL;
	gchar    *Texte_Notification = NULL;

	ERROR_if (Donnee == NULL);
	Reseau = Recupere_Pointeur_Structure_Reseau (Message->ID_Reseau);
	Objet = Recherche_Objet_Equipement (Message->ID_Equipement, Message->ID_Reseau);
	if (Objet == NULL) {
		debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Retour notification (Equipment unknown)");
		return;
	}
	Equipement = (struct Struct_Equipement *) Objet->Pointeur_Attacher;
	Texte_Notification = g_strdup_printf ("Port [%d] on [%s] is down\nNetwork : [%s]", Message->Num_Port, Equipement->Adresse_Ip_Char, Reseau->Nom_Complet_Reseau);
	Affiche_Win_Alert();
	gtk_label_set_text (GTK_LABEL (label_Info_Alert), Texte_Notification);
	if (Equipement->Contact_Admin)
		Envoie_Email_Notification (Texte_Notification, Equipement->Contact_Admin);
	MYFREE (Texte_Notification);
	Modifie_Etat_Port_Equipement (Equipement, Message->Num_Port, FERMER);
	if ((Message->ID_Reseau == Reseau_Selectionner->Id_Reseau)
		&& (Equipement == Equipement_Selectionner)
		&& (Modules_Actuel == MODULES_LISTE_PORTS)) {
		if ((Objet = Recherche_Objet_Port (Message->Num_Port)) != NULL)
			Active_Test_Etat_Objet (Objet, Reseau_Selectionner);
	}
	Texte_Notification = g_strdup_printf ("Port [%d] on [%s] is down", Message->Num_Port, Equipement->Adresse_Ip_Char);
	Ajouter_Historique (Equipement, Texte_Notification, HISTORIQUE_ALERTE);
	MYFREE (Texte_Notification);
	Recuperation_Nb_Octet_Recu (sizeof (struct struct_Retour_Notification_Changement_Etat_Port), Reseau);
#ifdef  __SOUND_ENABLE	
	Sound_Alarme_Active = TRUE;
#endif
}


struct Struct_Modele_Objet *Recherche_Objet_Port (gint Num_Port)
{
	struct Struct_Liste_Reseau *Reseau = NULL;
	struct Struct_Port *Port_Equipement = NULL;
	struct Struct_Modele_Objet *Objet = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Num_Port < 0);
	Reseau = Recupere_Pointeur_Structure_Reseau (ID_Reseau_En_Cours);
	Nb_Objet_Liste = g_list_length (Reseau->GList_Liste_Module);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Objet = g_list_nth_data (Reseau->GList_Liste_Module, i);
		if (Objet->Pointeur_Attacher != NULL) {
			Port_Equipement = (struct Struct_Port *) Objet->Pointeur_Attacher;
			if (Port_Equipement->Num_Port == Num_Port) {
				return Objet;
			}
		}
	}
	return NULL;	
}


void Copie_Icone_Port (gpointer * pointeur)
{			
	struct Struct_Modele_Objet *Objet = (struct Struct_Modele_Objet *) pointeur;
	struct Struct_Port *Port_Equipement = NULL;
	struct Struct_Liste_Port *Port = NULL;
	gchar *path = NULL;
	
	ERROR_if (pointeur == NULL);
	Port_Equipement = (struct Struct_Port *) Objet->Pointeur_Attacher;
	Port = Pointeur_Du_Port (Port_Equipement->Num_Port);

	if ((Port->icone == NULL) && (Port->Icon != NULL) && (strlen (Port->Icon) != 0)) {
	
		path = g_strdup_printf(PATH_ROOT "%s",Port->Icon);
	
		Port->icone = Chargement_Image (path, COULEUR);
		Port->icone_griser = Chargement_Image (path, NOIR_ET_BLANC);
		MYFREE (path);
	}
	if (Port->icone != NULL) {
		Objet->icone = Port->icone;
		Objet->icone_griser = Port->icone_griser;
	}
}


struct Struct_Port *Recherche_Info_Port_Equipement_Selectionner (gchar * Nom_Port)
{
	gint      Num_Port;

	ERROR_if (Nom_Port == NULL);
	if ((Num_Port = Num_Du_Port (Nom_Port)) == -1)
		return NULL;
	return Cherche_Pointeur_Port (Equipement_Selectionner, Num_Port);
}


struct Struct_Port *Cherche_Pointeur_Port (struct Struct_Equipement *Equipement, gint Num_Port)
{
	struct Struct_Port *Port_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port) {
			return Port_Equipement;
		}
	}
	debug_printf (INTERFACE, D_ERRO, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Port %d Inconnu", Num_Port);
	return NULL;
}


gboolean Recherche_Port_SSH_Ouvert_Sur_Equipement_Selectionner (void)
{
	return Cherche_Si_Port_Ouvert (Equipement_Selectionner, PORT_SSL);
}


gboolean Recherche_Port_Telnet_Ouvert_Sur_Equipement_Selectionner (void)
{
	return Cherche_Si_Port_Ouvert (Equipement_Selectionner, PORT_TELNET);
}


gboolean Recherche_Port_Samba_Ouvert_Sur_Equipement_Selectionner (void)
{
	return Cherche_Si_Port_Ouvert (Equipement_Selectionner, PORT_SAMBA);
}


gboolean Cherche_Si_Port_Ouvert (struct Struct_Equipement * Equipement, gint Num_Port)
{
	struct Struct_Port *Port_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port) {
			return (Port_Equipement->Etat_Port == OUVERT);
		}
	}
	return FALSE;	
}

unsigned char Cherche_Flags_Port (struct Struct_Equipement * Equipement, gint Num_Port)
{
	struct Struct_Port *Port_Equipement = NULL;
	struct Struct_Port_Fermer_Firewall *Port_Equipement_fw = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);


	Nb_Objet_Liste = g_list_length (Equipement->GList_Port_Fermer);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement_fw = g_list_nth_data (Equipement->GList_Port_Fermer, i);
		if (Port_Equipement_fw->Num_Port == Num_Port){
				return Port_Equipement_fw->Flags;
		}
	}

	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port){
				return Port_Equipement->Flags;
		}
	}
	return 255;
}

gboolean Cherche_Si_Port_Serveur (struct Struct_Equipement * Equipement)
{
	struct Struct_Port *Port_Equipement = NULL;
	struct Struct_Liste_Port *Port = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		Port = Pointeur_Du_Port (Port_Equipement->Num_Port);
		if (Port->Type == SERVEUR) {
			return TRUE;
		}
	}
	return FALSE;	
}


void Modifie_Etat_Port_Equipement (struct Struct_Equipement *Equipement, gint Num_Port, gint Nouvelle_Etat)
{
	struct Struct_Port *Port_Equipement = NULL;
	gint      Nb_Objet_Liste, i;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);
	for (i = 0; i < Nb_Objet_Liste; i++) {
		Port_Equipement = g_list_nth_data (Equipement->GList_Port, i);
		if (Port_Equipement->Num_Port == Num_Port) {
			if (Port_Equipement->Notification_En_Cours) {
				Port_Equipement->Etat_Port = Nouvelle_Etat;
				Port_Equipement->Alert_notification = TRUE;
			}
			else {
				G_LIST_REMOVE (Equipement->GList_Port, Port_Equipement);
			}
			return;
		}
	}
	debug_printf (INTERFACE, D_WARN, __FILE__, __PRETTY_FUNCTION__, __LINE__, "Port %d Inconnu", Num_Port);
}


void Efface_Tout_Les_Ports (struct Struct_Equipement *Equipement)
{
	struct Struct_Port_Fermer_Firewall *Port_Equipement_F = NULL;
	struct Struct_Port *Port_Equipement = NULL;
	gint      Nb_Objet_Liste;

	ERROR_if (Equipement == NULL);
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port);

	if (Nb_Objet_Liste != 0) {
		while ((Port_Equipement = g_list_nth_data (Equipement->GList_Port, 0)) != NULL) {
			G_LIST_REMOVE (Equipement->GList_Port, Port_Equipement);
			MYFREE(Port_Equipement); 
		}
	}
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port_Fermer);

	if (Nb_Objet_Liste != 0) {
		while ((Port_Equipement_F = g_list_nth_data (Equipement->GList_Port_Fermer, 0)) != NULL) {
			G_LIST_REMOVE (Equipement->GList_Port_Fermer, Port_Equipement_F);
			MYFREE(Port_Equipement_F); 
		}
	}
	Nb_Objet_Liste = g_list_length (Equipement->GList_Port_Firewall);

	if (Nb_Objet_Liste != 0) {
		while ((Port_Equipement_F = g_list_nth_data (Equipement->GList_Port_Firewall, 0)) != NULL) {
			G_LIST_REMOVE (Equipement->GList_Port_Firewall, Port_Equipement_F);
			MYFREE(Port_Equipement_F); 
		}
	}
}


struct Struct_Port *Ajouter_Nouveau_Port_Equipement (struct Struct_Equipement *Equipement, gint Num_Port,unsigned char Flags)
{
	struct Struct_Port *Port_Equipement = NULL;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);
	MALLOC (Port_Equipement, sizeof (struct Struct_Port));
	Port_Equipement->Num_Port = Num_Port;
	Port_Equipement->Notification_En_Cours = FALSE;
	Port_Equipement->Alert_notification = FALSE;
	Port_Equipement->Etat_Port = OUVERT;
	Port_Equipement->Niveau_Notification = NOTIFICATION_STANDARD;
	time (&Port_Equipement->Derniere_Modification_Etat_Port);
	Port_Equipement->Flags = Flags;
	G_LIST_APPEND (Equipement->GList_Port, Port_Equipement);
	return Port_Equipement;
}



struct Struct_Port_Fermer_Firewall *Ajouter_Nouveau_Port_Equipement_Fermer_Firewall (struct Struct_Equipement *Equipement, gint Num_Port,gint Etat,unsigned char Flags)
{
	struct Struct_Port_Fermer_Firewall *Port_Equipement = NULL;

	ERROR_if (Equipement == NULL);
	ERROR_if (Num_Port < 0);
	MALLOC (Port_Equipement, sizeof (struct Struct_Port_Fermer_Firewall));
	Port_Equipement->Num_Port = Num_Port;
	Port_Equipement->Etat_Port = Etat;
	Port_Equipement->Flags = Flags;

	if (Etat==FERMER)
		G_LIST_APPEND (Equipement->GList_Port_Fermer, Port_Equipement);
	if (Etat==FIREWALLED)
		G_LIST_APPEND (Equipement->GList_Port_Firewall, Port_Equipement);
	return Port_Equipement;
}
