#!/usr/bin/perl -wU

#----------------------------------------------------------------------
# heading     : Configuration
# description : DHCP manager
# navigation  : 2000 2500
# 
# Copyright (c) 2003 Thierry Quaak  thierry@quaak.net
#               2014 Stephane de Labrusse stephdl@de-labrusse.fr
#----------------------------------------------------------------------
      
my $fm = esmith::FormMagick->new();
$fm->parse_xml();

###Call Modules
use strict;
use CGI ':all';
use CGI::Carp qw(fatalsToBrowser);
use esmith::cgi;
use esmith::util;
use esmith::templates;
use esmith::ConfigDB;
use esmith::AccountsDB;
use esmith::FormMagick;
use Net::Ping;
use esmith::util::network qw(:all);
use Socket qw( inet_aton );

###Declare function prototypes
sub Main_Display ($$);
sub Load_leases ($);
sub Main_Save ($);
sub Del_Lease ($);
sub Perform_Del_Lease ($);
sub Wake_Up ($);
sub Perform_Wake_Up ($);
sub Message ($$);
sub Global_WinPopup ($);
sub Perform_Message ($);
sub Table_IP ($$);
sub Scan_Local_Network ($);
sub Del_all_Lease ($);
sub Perform_del_all_Lease ($);
sub Save_checkip ($);


### Clear PATH and related environment variables so that calls to
### external programs do not cause results to be tainted. See
### "perlsec" manual page for details.
BEGIN {
    $ENV {'PATH'} = '';
    $ENV {'SHELL'} = '/bin/bash';
    delete $ENV {'ENV'};
}

###Define package global to SME configuration paramters using "old" method.
###We are using this method, over esmith::ConfigDB, to satisfy syntax in
###esmith::cgi
our %conf = ();
tie %conf, 'esmith::config';
our @liste_computer  ;
our @liste_connected  ;

###Change UID -- not sure what we are doing this, but all panels seem to 
###call this function.
esmith::util::setRealToEffective ();

our %status           = ('enabled'  => $fm->localise('ENABLED'),
                        'disabled' => $fm->localise('DISABLED')
                        );

our %check           = ('enabled'  => $fm->localise('ENABLED'),
                        'disabled' => $fm->localise('DISABLED')
                        );

###Restrict uploads to form submittals only
$CGI::POST_MAX=1024 * 100;  # max 100K posts
$CGI::DISABLE_UPLOADS = 1;  # no uploads

###Examine state parameter and display the appropriate form
my $q = new CGI;
if (! grep (/^state$/, $q->param)){    Main_Display($q, '');}
elsif ($q->param ('state') eq "main_display"){Main_Display ($q,'');}
elsif ($q->param ('state') eq $fm->localise('REFRESH')){Table_IP ($q, '');}
elsif ($q->param ('state') eq "main_save"){Main_Save ($q);}
elsif ($q->param ('state') eq "del_lease"){Del_Lease ($q);}
elsif ($q->param ('state') eq "perform_del_lease"){Perform_Del_Lease ($q);}
elsif ($q->param ('state') eq "wake_up"){Wake_Up ($q);}
elsif ($q->param ('state') eq "perform_wake_up"){Perform_Wake_Up ($q);}
elsif ($q->param ('state') eq $fm->localise('GLOBAL_WINPOPUP')){Global_WinPopup ($q);}
elsif ($q->param ('state') eq "message"){Message ($q,'');}
elsif ($q->param ('state') eq "perform_message"){Perform_Message ($q);}
elsif ($q->param ('state') eq $fm->localise('CONNECTED_IP')){Table_IP ($q,'');}
elsif ($q->param ('state') eq $fm->localise('SCAN_YOUR_NETWORK')){Scan_Local_Network ($q);}
elsif ($q->param ('state') eq $fm->localise('REMOVE_ALL_LEASES')){Del_all_Lease ($q);}
elsif ($q->param ('state') eq $fm->localise('REMOVE_ALL_LEASES_ACTION')){Perform_del_all_Lease ($q);}
elsif ($q->param ('state') eq 'Save_checkIP'){Save_checkip ($q);}
else{esmith::cgi::genStateError ($q, \%conf);}
exit (0);

#===============================================================================
#SUBROUTINE TO SHOW MAIN PANEL
#===============================================================================
sub Main_Display ($$){

    ###Pull cgi object from parameters array
    my $q = shift;
	my @computer;
	my $status ;

    ###Pull action message, if any, from parameters array
    my $action_message = shift;

    ###Retrieve SME configuration entry for dhcpd
    my $dbh_sme = esmith::ConfigDB->open('/home/e-smith/db/configuration');
    my %sme_conf = $dbh_sme->get('dhcpd')->props;

    ###Display Main Panel Title
    esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('DHCPD_TITLE'));

    ###Check to see if we just processed a panel action.  If so, display
    ###action message and bail.
    if ($action_message) {
        print $q->h3 ($fm->localise('STATUS_REPORT') . " $action_message");
    }

    #------------------------------------------------------------
    # Start DHCP client Panel 
    #------------------------------------------------------------
    print $q->p ('');
    print $q->startform (-method => 'POST',
                         -action => $q->url (-absolute => 1));
print $q->Tr (esmith::cgi::genButtonRow ($q,$q->submit (-name => 'state',-value => $fm->localise('CONNECTED_IP'))));
    
print $q->Tr (esmith::cgi::genButtonRow ($q,$q->submit (-name => 'state',-value => $fm->localise('SCAN_YOUR_NETWORK'))));

    print $q->Tr (esmith::cgi::genButtonRow ($q,$q->submit (-name => 'state',-value => $fm->localise('GLOBAL_WINPOPUP'))));

    print $q->hidden (-name => 'liste_connected', -override => 1, -default => "@liste_connected");


    #------------------------------------------------------------
    # Start DHCP daemon Panel 
    #------------------------------------------------------------
    print $q->hr;
    print $q->h3 ($fm->localise('DHCPD_SETTINGS_TITLE'));

	if (! $sme_conf{'winscustom'} ) {
		$sme_conf{'winscustom'} = 'disabled' ;
	}
	if (! $sme_conf{'dnscustom'} ) {
		$sme_conf{'dnscustom'} = 'disabled' ;
	}
	if ( ! $sme_conf{'leasetime'} )
	{ $sme_conf{'leasetime'} =  "86400" ; 
	}
	if (! $sme_conf{'gatewaycustom'} ) {
		$sme_conf{'gatewaycustom'} = 'disabled' ;
	}
#check the status (up or down) of dhcp client
        print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
    esmith::cgi::genWidgetRow ($q, $fm->localise('CHECK_CLIENT_STATUS'),
      $q->popup_menu (-name    => 'dhcp_check',
                      -values  => ['disabled', 'enabled'],
                      -default => $sme_conf{'check'},
                      -labels  => \%check)) );
		
	# - modofication des plage DHCP
	print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
    esmith::cgi::genWidgetRow ($q, $fm->localise('STATUS_DHCP_SERVER'),
      $q->popup_menu (-name    => 'dhcp_enable',
                      -values  => ['enabled', 'disabled'],
                      -default => $sme_conf{'status'},
                      -labels  => \%status)) ,

    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('DHCP_START'),
                                  'dhcp_start',
                                  $sme_conf{'start'}) ,
    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('DHCP_END') ,
                                  'dhcp_end',
                                  $sme_conf{'end'}),

	esmith::cgi::genTextRow ($q,
     $q->p ($fm->localise('CUSTOM_WINSERVER_TITLE'))),
    esmith::cgi::genWidgetRow ($q, $fm->localise('CUSTOM_WINSERVER_STATUS'),
      $q->popup_menu (-name    => 'dhcp_winscustom',
                      -values  => ['enabled', 'disabled'],
                      -default => $sme_conf{'winscustom'},
                      -labels  => \%status)),

    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('CUSTOM_WINSERVER_ADDRESS'),
                                  'dhcp_winsserver',
                                  $dbh_sme->get_prop('smb','WINSServer')),

	#### Custom DNS
	esmith::cgi::genTextRow ($q,
     $q->p ($fm->localise('CUSTOM_DNS_TITLE'))),
    esmith::cgi::genWidgetRow ($q, $fm->localise('CUSTOM_DNS_STATUS'),
      $q->popup_menu (-name    => 'dhcp_dnscustom',
                      -values  => ['enabled', 'disabled'],
                      -default => $sme_conf{'dnscustom'},
                      -labels  => \%status)),

    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('PRIMARY_DNS_ADDRESS'),
                                  'dhcp_dns1server',
                                  $sme_conf{'dns1server'}),
    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('SECONDARY_DNS_ADDRESS'),
                                  'dhcp_dns2server',
                                  $sme_conf{'dns2server'}),
    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('TERTIARY_DNS_ADDRESS'),
                                  'dhcp_dns3server',
                                  $sme_conf{'dns3server'}),

	#### Custom default Gateway
	esmith::cgi::genTextRow ($q,
     $q->p ($fm->localise('CUSTOM_GATEWAY_TITLE'))),
    esmith::cgi::genWidgetRow ($q, $fm->localise('CUSTOM_GATEWAY_STATUS'),
      $q->popup_menu (-name    => 'dhcp_gatewaycustom',
                      -values  => ['enabled', 'disabled'],
                      -default => $sme_conf{'gatewaycustom'},
                      -labels  => \%status)),

    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('CUSTOM_GATEWAY_ADDRESS'),
                                  'dhcp_gateway',
                                  $sme_conf{'gateway'}),

	#dhcp LEASE SET UP
	esmith::cgi::genTextRow ($q,
     $q->p ($fm->localise('CUSTOM_LEASETIME_TITLE'))),
    esmith::cgi::genNameValueRow ($q,
                                  $fm->localise('CUSTOM_LEASETIME'),
                                  'dhcp_leasetime',
                                  $sme_conf{'leasetime'})
	);
    print '</table>';

    print $q->start_table ({width => "100%", -class => "sme-noborders"}),
                "\n";
    print esmith::cgi::genButtonRow ($q,
      $q->submit (-name => 'action', -value => $fm->localise('SAVE/RESTART')));

        print $q->end_table,"\n";
    print $q->hidden (
            -name => 'state',
            -override => 1,
            -default => 'main_save'
        ),"\n";
    print $q->endform;
    esmith::cgi::genFooter ($q);

}

#
#===============================================================================
#SUBROUTINE: Process Save From Main Panel
#===============================================================================
sub Main_Save ($){

    ##Pull CGI object from parameters array
    my $q = shift;

    ###Build Hash of config parameters to update from cgi submit
    my $dhcpd_status     	= $q->param ('dhcp_enable');
    my $dhcpd_winscustom    = $q->param ('dhcp_winscustom');
    my $dhcpd_check     	= $q->param ('dhcp_check');
    my $dhcpd_start     	= $q->param ('dhcp_start');
    my $dhcpd_end     	    = $q->param ('dhcp_end');
    my $dhcpd_winsserver    = $q->param ('dhcp_winsserver');
    my $dhcpd_leasetime     = $q->param ('dhcp_leasetime');
    my $dhcpd_dnscustom     = $q->param ('dhcp_dnscustom');
    my $dhcpd_dns1server    = $q->param ('dhcp_dns1server');
    my $dhcpd_dns2server    = $q->param ('dhcp_dns2server');
    my $dhcpd_dns3server    = $q->param ('dhcp_dns3server');
    my $dhcpd_gatewaycustom = $q->param ('dhcp_gatewaycustom');
    my $dhcpd_gateway     	= $q->param ('dhcp_gateway');
    
    ###Update SME configuration dbase
    my $dbh_sme = esmith::ConfigDB->open('/home/e-smith/db/configuration');

    ##Initiate get method --> create record object
    my $sme_record  = $dbh_sme->get('dhcpd');
    #get localip of server
    my $local_ip    = $dbh_sme->get_value('LocalIP');

    ##Set status of service
    $sme_record->set_prop('status', $dhcpd_status);
    $sme_record->set_prop('check' , $dhcpd_check);
    $sme_record->set_prop('winscustom', $dhcpd_winscustom);
    $sme_record->set_prop('leasetime' , $dhcpd_leasetime);
    $sme_record->set_prop('dnscustom' , $dhcpd_dnscustom);
    $sme_record->set_prop('gatewaycustom' , $dhcpd_gatewaycustom);

    #checkip to the dhcpserver, perform the save in DB configuration or display an error if value != of a valid ip or if dhcp_start is greater than dhcp_end
    if ($dhcpd_status eq "enabled") 
    {
        if ( isValidIP ($dhcpd_start) && isValidIP ($dhcpd_end))
        {
            #check if $dhcpd_start is greater than $dhcpd_end and if yes, display an error message.
            if (inet_aton($dhcpd_start) ge inet_aton($dhcpd_end))
            {
             Main_Display($q, $fm->localise('DHCP_START_GREATER_DHCP_END_ERRORS') . ' (' . $dhcpd_start . '/' . $dhcpd_end .')');
            }
            elsif ( ( (inet_aton($dhcpd_start) le inet_aton($local_ip) ) && ( inet_aton($dhcpd_end)) ge inet_aton($local_ip) ) )
            {
            #display an error if the range of dhcp server include the ip of the server address
            Main_Display($q, $fm->localise('DHCP_RANGE_MUST_NOT_INCLUDE_SERVER_IP') . ' (' . $local_ip . ')');
            }
            else
            {
            #set value
            my $dhcpd_start = cleanIP($dhcpd_start);
            my $dhcpd_end = cleanIP($dhcpd_end);

            $sme_record->set_prop('end', $dhcpd_end);
            $sme_record->set_prop('start', $dhcpd_start);
            }
        }  
        #if $dhcpd_start or $dhcpd_end are not valid ip then display an error
        else
        {
        Main_Display($q, $fm->localise('DHCP_RANGE_WITH_BAD_IP') . ' (' . $dhcpd_start . '/' . $dhcpd_end .')');
        }  
    }  
       
    #checkip to the winserver perform the save in DB configuration or display an error if value != of a valid ip
    if ($dhcpd_winscustom eq "enabled")
    {

        if ( isValidIP ($dhcpd_winsserver) )
        {
        #set value
        my $dhcpd_winsserver = cleanIP($dhcpd_winsserver);
        $dbh_sme->set_prop('smb','WINSServer', $dhcpd_winsserver);
        }  
        else
        {
        #if $dhcpd_winsserver is not valid ip then display an error
        Main_Display($q, $fm->localise('WINSSERVER_BAD_IP') . ' (' . $dhcpd_winsserver .')');
        }
    }
    elsif ($dhcpd_winscustom eq "disabled")
    {
        my $delws = $dbh_sme->get('smb');
        $delws->delete_prop('WINSServer');
    }

    #checkip to the dnsserver custom, perform the save in DB configuration or display an error if value != of a valid ip
    if ($dhcpd_dnscustom eq "enabled")
    {
        #check if $dhcpd_dns1server and ( $dhcpd_dns2server are valid ip or $dhcpd_dns2server = null )
        if ( isValidIP ($dhcpd_dns1server) &&  (isValidIP($dhcpd_dns2server) || ( $dhcpd_dns2server eq "")  ) &&  (isValidIP($dhcpd_dns3server) || ( $dhcpd_dns3server eq "")  )   )
        {
        #set value
        my $dhcpd_dns1server = cleanIP($dhcpd_dns1server);
        $sme_record->set_prop('dns1server' , $dhcpd_dns1server);
        my $dhcpd_dns2server = cleanIP($dhcpd_dns2server);
        $sme_record->set_prop('dns2server' , $dhcpd_dns2server);
        my $dhcpd_dns3server = cleanIP($dhcpd_dns3server);
        $sme_record->set_prop('dns3server' , $dhcpd_dns3server);
        }
        else
        {
        ##if $dhcpd_dns1server or $dhcpd_dns2server or $dhcpd_dns3server are not valid ip then display an error
        Main_Display($q, $fm->localise('DNS_SERVER_WITH_BAD_IP') . ' (' . $dhcpd_dns1server . '/' . $dhcpd_dns2server . '/' . $dhcpd_dns3server .')');
        }
    }

    #checkip to the gateway_custom perform the save in DB configuration or display an error if value != of a valid ip
    if ($dhcpd_gatewaycustom eq "enabled") 
    {
        if ( isValidIP ($dhcpd_gateway) )
        {
        #set value
        my $dhcpd_gateway = cleanIP($dhcpd_gateway);
        $sme_record->set_prop('gateway' , $dhcpd_gateway);
        }  
        else
        {        
        #if $dhcpd_gateway is not valid ip then display an error
        Main_Display($q, $fm->localise('GATEWAY_BAD_IP') . ' (' . $dhcpd_gateway .')');
        }
    }    
     

    # - 4 expand templates
    # changed to new sme standard signal-event
    system ("/sbin/e-smith/signal-event","workgroup-update") == 0
                or die "Error while saving settings: $!"; 
   Main_Display($q, $fm->localise('SUCCESSFULLY_SAVED_SETTINGS') );
    exit;
}

#
#===============================================================================
#SUBROUTINE: procedure qui supprime un bail dans le dhcpd.leases
#===============================================================================
sub Del_Lease ($){
    ###Pull CGI object from parameters array
    $q = shift;

    ###Start Panel.
    esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('REMOVE_A_DHCP_LEASE_TITLE'));
    print $q->h3($fm->localise('REMOVE_A_DHCP_LEASE'));

    print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1));

    my $ip = $q->param ('host');
    my $name = $q->param ('name');

    print $q->p ($fm->localise('REMOVE_A_DHCP_LEASE_ACTION') . ' (' . $name .'/' . $ip .')');
    print $q->p ($q->b ($fm->localise('ARE_YOU_SURE')));
    print $q->submit (-name => 'action', -value => $fm->localise('REMOVE'));
    print $q->hidden (-name => 'host',
                      -override => 1,
                      -default => $ip
                      );
    print $q->hidden (-name => 'name',
                      -override => 1,
                      -default => $name
                      );

    print $q->hidden (-name     => 'state',
                      -override => 1,
                      -default  => 'perform_del_lease');

    print $q->endform;
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));
    esmith::cgi::genFooter ($q);
    return;

}

#===============================================================================
#SUBROUTINE: Perform delete lease
#===============================================================================
sub Perform_Del_Lease($){

    ###Pull CGI object from parameters array
    $q = shift;

    ###Pull entry to delete
    my $ip = $q->param('host');
    my $name = $q->param('name');
	my $name_in_file = '/var/lib/dhcpd/dhcpd.leases'  ;
	my $name_tmp_file = '/var/lib/dhcpd/dhcpd.leases.tmp'  ;
	my $name_out_file = '/var/lib/dhcpd/dhcpd.leases~'  ;
	my $del_current = "0" ;

	open(INFILE,"<$name_in_file") || die "Read Error $name_in_file, Read: $!";
	open(OUTFILE,">$name_tmp_file") || die "Write error $name_in_file, Write: $!";
	while (<INFILE>) {
        	if ( "$_" =~ /lease $ip/ ) {
                	$del_current = "1" ;
        	}
        	if ( $del_current == "0" ) { print OUTFILE "$_" ; }
        	if ( "$_" =~ /}/ ) {
                	$del_current = "0" ;
        	}
	}
	rename ($name_tmp_file,$name_in_file) ;
	system ("/bin/cp","-f","$name_in_file","$name_out_file") ;
	close(INFILE);
	close(OUTFILE);

    # changed to new sme standard signal-event
    system ("/sbin/e-smith/signal-event","workgroup-update") == 0
                or die "Error while saving settings: $!"; 
    ###Return action message
    Table_IP($q, $fm->localise('SUCCESSFULLY_DELETED_THE_CLIENT') . ' (' . $name . '/' . $ip .')');
    exit;
}


#===============================================================================
#SUBROUTINE: procedure qui valide les parametres de l'host eteint 
#===============================================================================
sub Wake_Up ($){
    ###Pull CGI object from parameters array
    $q = shift;

    ###Start Panel.
    esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('WAKING_A_REMOTE_COMPUTER_TITLE'));
    print $q->h3($fm->localise('WAKING_A_REMOTE_COMPUTER'));

    print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1));

    my $mac = uc($q->param ('MAC'));
    my $name = uc($q->param ('name'));

    print $q->p ($q->b ($fm->localise('WAKING_A_REMOTE_COMPUTER_ACTION') . ' (' . $name . '/' . $mac . ')'));

    print $q->submit (-name => 'action', -value => $fm->localise('WAKE_UP') . " $name");
    print $q->hidden (-name => 'mac',
                      -override => 1,
                      -default => $mac
                      );
    print $q->hidden (-name => 'name',
                      -override => 1,
                      -default => $name
                      );

    print $q->hidden (-name     => 'state',
                      -override => 1,
                      -default  => 'perform_wake_up');

    print $q->endform;
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));
    esmith::cgi::genFooter ($q);
    return;
}
#===============================================================================
#SUBROUTINE: Perform wake UP
#===============================================================================
sub Perform_Wake_Up($){

    ###Pull CGI object from parameters array
    $q = shift;

    ###Get Mac Adress
    my $mac = uc($q->param('mac'));
    my $name = uc($q->param('name'));
	
	#Send Wake Up to the station
	#Old version obsolete since 1.5.0 - system ("/usr/bin/wol","$mac") ;
	system ("/sbin/ether-wake","$mac") ;
    ###Return action message
    Table_IP($q, $fm->localise('SUCCESSFULLY_CLIENT_WOL_REQUEST') . ' (' . $name . '/' . $mac . ')');
    exit;
}

#=========================================================================
# Procedure qui charge le dhcpd.conf
# retourne un tableau contenant les informations
#=========================================================================
sub Load_leases ($){

	#Definition de variable
	use vars qw/
		@detail $work_line $header /; 
	my $name_file = '/var/lib/dhcpd/dhcpd.leases'  ;
    @liste_computer = '' ;
	#Ouverture du fichier en lecture seule
	open(FILE,"<$name_file") || die "Read error $name_file, Error: $!" ;
	
	#Parcours du fichier dhcpd.leases
	while (<FILE>) { 
		# suppression des commentaires
		if ($_ =~ /^#/) { next; }
	
		#spurresion des lignes vides
		if ($_ =~ /^$/) { next; }
        #supression de la ligne uid de windows
		if ($_ =~ /uid/) { next; }
        #supression de la ligne tstp de XP
		if ($_ =~ /tstp/) { next; }
        #supression de la ligne "binding state active"
		if ($_ =~ /binding/) { next; }
        #supression de la ligne "next binding state"
		if ($_ =~ /next/) { next; }         
		#suprresion des commentaire et des ;
    	$_ =~ s/\s#.*$//;
    	$_ =~ s/(;|{) *$//;
	
		#supression des espace en debut de lignes
    	$_ =~ s/^ *\s//;
		
		#Suppression des retours chariot en fin de lignes.
		chomp $_ ;
        
		#Chargement d'un tableau avec le contenu de la ligne.
		(@detail) = split(/ /, $_) ;
		
		#initialisation d'un nouveau poste connect�
		if ($_ =~ /lease/) { 
			$work_line = "" ; 
		}
	
		$header = shift(@detail);
		$work_line = $work_line . ";" . join(" ",@detail) ;
	
		if ($header =~ /}/) { 
		    $work_line =~ s/ /;/g;
    		$work_line =~ s/^;//;
    		$work_line =~ s/"//g;
    		$work_line =~ s/;$//;         
                #we want the last entry is the first element of the array
		unshift(@liste_computer,$work_line) ;
		}
	}
	close(FILE); 
}

#===============================================================================
#SUBROUTINE: Message
#===============================================================================
sub Message($$){

    ###Pull CGI object from parameters array
    $q = shift;

    ###Pull entry to delete
    my $name = $q->param('name');
    my @liste_connected = $q->param('liste_connected');
	my $message2send ;

	if ( $name ) { 
		@liste_connected = () ; 
		push(@liste_connected,$name) ; }
	else {$name = $fm->localise('ALL_OF_THEM')}

    esmith::cgi::genHeaderNonCacheable ($q, \%conf,$fm->localise('SENDING_A_WINPOPUP'));
    print $q->h3($fm->localise('SENDING_A_WINPOPUP_TO') . " @liste_connected.");
    print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1));
    print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
    esmith::cgi::genNameValueRow ($q,$fm->localise('YOUR_MESSAGE'), 'message2send',
                                 $fm->localise('WRITE_YOUR_MESSAGE')) );
    print '</table>';
    print $q->hr;
    print $q->p ($q->p ($fm->localise('DO_YOU_WANT_TO_SENT') . " $name"));
    print $q->submit (-name => 'action', -value => $fm->localise('SEND_WINPOPUP_TO') . " $name");
    print $q->hidden (-name => 'liste_connected', -override => 1,
                      -default => @liste_connected);
    print $q->hidden (-name => 'message2send', -override => 1, -default => $message2send);
    print $q->hidden (-name     => 'state', -override => 1, -default  => 'perform_message');
    print $q->endform;
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));
    esmith::cgi::genFooter ($q);
    return;
}
#===============================================================================
#SUBROUTINE: Perform message
#===============================================================================
sub Perform_Message($){

    ###Pull CGI object from parameters array
    $q = shift;

    ###Get Mac Adress
    my @liste_connected = split(' ',$q->param('liste_connected'));
    my $message2send = $q->param('message2send');

    foreach (@liste_connected){
   	  system ("/etc/e-smith/events/actions/send-message","$_","$message2send") ;
	}
    Table_IP($q, $fm->localise('SUCCESSFULLY_SENT_MESSAGE') . " @liste_connected." . $fm->localise('WARNING_NO_WINPOPUP_GARANTY'));
    exit;
}

#===============================================================================
#SUBROUTINE: Win Popup for all connected hosts
#===============================================================================
sub Global_WinPopup($){

    my $q = shift;
    my @liste_connected = $q->param('liste_connected');
    Message($q,@liste_connected);
    exit;
}

#===============================================================================
#SUBROUTINE: Create Table_IP of dhcp server
#===============================================================================
sub Table_IP ($$) {
    ###Pull cgi object from parameters array
    my $q = shift;
	my @computer;
	my $status ;

    ###Pull action message, if any, from parameters array
    my $action_message = shift;

    ###Retrieve SME configuration entry for dhcpd
    my $dbh_sme = esmith::ConfigDB->open('/home/e-smith/db/configuration');
    my %sme_conf = $dbh_sme->get('dhcpd')->props;

       ###Display Main Panel Title
    esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('MANAGING_DHCP_CLIENT'));

    ###Check to see if we just processed a panel action.  If so, display
    ###action message and bail.
    if ($action_message) {
        print $q->h3 ($fm->localise('STATUS_REPORT') . " $action_message");
    }

    #------------------------------------------------------------
    # Start DHCP client Panel 
    #------------------------------------------------------------
    print $q->p ('');
    print $q->startform (-method => 'POST',
                         -action => $q->url (-absolute => 1));
#refresh the list
print esmith::cgi::genButtonRow ($q,$q->submit (-name => 'state',-value => $fm->localise('REFRESH'))); 
#Remove all dhcpd lease
print esmith::cgi::genButtonRow ($q,$q->submit (-name => 'state',-value => $fm->localise('REMOVE_ALL_LEASES'))); 
print $q->hr;
 
	print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
    esmith::cgi::genWidgetRow ($q, $fm->localise('CHECK_CLIENT_STATUS'),
      $q->popup_menu (-name    => 'dhcp_check',
                      -values  => ['disabled', 'enabled'],
                      -default => $sme_conf{'check'},
                      -labels  => \%check)) );
                      
     ##save checkip   ('Saving modification and restart the daemon...') and go to sub Save_checkip :) 
     print $q->table ({border => 0, cellspacing => 0, cellpadding => 4},
    esmith::cgi::genTextRow ($q,
     $q->p ($fm->localise('SAVE_TITLE'))));

    print $q->start_table ({width => "100%", -class => "sme-noborders"}),
                "\n";
    print esmith::cgi::genButtonRow ($q,
      $q->submit (-name => 'action', -value => $fm->localise('SAVE/RESTART')));

        print $q->end_table,"\n";
        print $q->hidden (
            -name => 'state',
            -override => 1,
            -default => 'Save_checkIP'
        ),"\n";

    print $q->endform;

    # Refresh Liste
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));
 
                
	&Load_leases ($q) ;
    if ( 2 > 1 ) {
    	print $q->p ($q->b (''));
    	print $q->table ({border => 1, cellspacing => 1, cellpadding => 4,nowarp => 1});
    	print $q->Tr (esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . 'IP')),
                  	esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . $fm->localise('NETWORK_NAME'))),
                  	esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . $fm->localise('STATUS_CLICK_FOR_WOL'))),
                  	esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . $fm->localise('START_DATE'))),
                  	esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . $fm->localise('END_DATE'))),
                  	esmith::cgi::genSmallCell ($q, $q->p ( '<center>' . $fm->localise('MAC_ADDRESS') . 
														   '</CENTER>')),
                 	);
##9(sme8)12(sme9)->netbios (ancien10)::8(sme8)11(sme9)->mac address (ancien8)::0->ip::
##it is possible you may adapt array number if more options/lines are added to the dhcpd.leases
##symptoms are a blank or wrong line in Table_IP
        my @mac = ();
        my @count = ();

        foreach (@liste_computer){
		@computer = split(/;/, $_) ;		

        #we want to sort elements the array by mac address

        $computer[11] =  uc($computer[11]) ;
        push @mac, ($computer[11]);
        my @count;
        push  @count , (grep /$computer[11]/ , @mac);
        next if (scalar @count > 1);


                    #we start the table if it is a valid IP   
		    if ( $computer[0] ) {
                                $computer[12] =  uc($computer[12]) ;
				my $datedeb = $computer[2] . "-" . $computer[3] ;
				my $datefin = $computer[5] . "-" . $computer[6] ;
					$status = $q->a ({href => $q->url (-absolute => 1) . 
							"?state=wake_up&MAC=" . $computer[11] . "&name=" . 
					  		$computer[12]}, $fm->localise('NOT_CHECKED')) ;
    		    if ( $sme_conf{'check'} =~ /enabled/ ) {
					use Net::Ping;
					my($ping_obj) = Net::Ping->new("icmp");
					# formatage des dates
					$computer[3] = substr($computer[3],0,5);
					$computer[6] = substr($computer[6],0,5);
					if ($ping_obj->ping("$computer[0]")) {
                		push(@liste_connected,$computer[12]) ;
				   		$status = $fm->localise('ACTIVE_DEVICE');
						#alimentation de la liste des connect�
					}
					else { $status = $q->a ({href => $q->url (-absolute => 1) . 
							"?state=wake_up&MAC=" . $computer[11] . "&name=" . 
					  		$computer[12]}, $fm->localise('WAKE_UP_ACTION')); 
					}
				}
				else {
                		push(@liste_connected,$computer[12]) ;

				}
                print $q->Tr (esmith::cgi::genSmallCell ($q, "$computer[0]"),
                          esmith::cgi::genSmallCell ($q, "$computer[12]"),
			  			  esmith::cgi::genSmallCell ($q, "<CENTER>" ."$status" ), 
                          esmith::cgi::genSmallCell ($q, "<CENTER>" . "$datedeb" . "</CENTER>"),
                          esmith::cgi::genSmallCell ($q, "<CENTER>" . "$datefin" . "</CENTER>"),
                          esmith::cgi::genSmallCell ($q, "$computer[11]"),
						  esmith::cgi::genSmallCell ($q,
                            $q->a ({href => $q->url (-absolute => 1)
                            . "?state=del_lease&host=" . $computer[0] . "&name=" . 
							$computer[12]}, $fm->localise('REMOVE_ACTION'))),
						  esmith::cgi::genSmallCell ($q,
                            $q->a ({href => $q->url (-absolute => 1)
                            . "?state=message&name=" . $computer[12]}, $fm->localise('WINPOPUP_ACTION')))
                          );
			}
    	}
    	print '</table>';
	}
    else{
        print $q->p ($q->b ($fm->localise('NO_CONNECTED_COMPUTERS')));
    }

    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));
	
     esmith::cgi::genFooter ($q);
        exit;
}
#
#===============================================================================
#SUBROUTINE: procedure qui sauve le checkip de la subroutine Table_ip
#===============================================================================
sub Save_checkip ($){
    
    ##Pull CGI object from parameters array
    my $q = shift;
    
    ###Build Hash of config parameters to update from cgi submit
    my $dhcpd_check     	= $q->param ('dhcp_check');
    
    ##Initiate get method --> create record object
    my $dbh_sme = esmith::ConfigDB->open('/home/e-smith/db/configuration');
    
    my $sme_record  = $dbh_sme->get('dhcpd');
    
    $sme_record->set_prop('check' , $dhcpd_check);
    
    system ("/sbin/e-smith/signal-event","workgroup-update") == 0
                or die "Error while saving settings: $!"; 
       Table_IP($q, $fm->localise('SUCCESSFULLY_SAVED_SETTINGS'));
    exit;
}     
#
#===============================================================================
#SUBROUTINE: procedure qui supprime tous les  bail dans le dhcpd.leases
#===============================================================================
sub Del_all_Lease ($){
    ###Pull CGI object from parameters array
    $q = shift;

    ###Start Panel.
    esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('REMOVE_DHCP_LEASE_TITLE'));
    print $q->h3($fm->localise('REMOVE_DHCP_LEASE_WARNING'));

    print $q->startform (-method => 'POST', -action => $q->url (-absolute => 1));
    
 
   
      print $q->p ( $fm->localise('REMOVE_DHCP_LEASE_WARNING2'));
                 
    print $q->p ($q->b ($fm->localise('ARE_YOU_SURE')));

    print $q->submit (-name => 'state', -value => $fm->localise('REMOVE_ALL_LEASES_ACTION'));
    
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));


    print $q->endform;
    esmith::cgi::genFooter ($q);
    return;

}    
#
#===============================================================================
#SUBROUTINE: supprime tous les  bail dans le dhcpd.leases
#===============================================================================   
sub Perform_del_all_Lease ($){

       system ('/bin/echo "" > /var/lib/dhcpd/dhcpd.leases') ==0
                or die "Error while removing all leases: $!";
       
       system ("/sbin/e-smith/signal-event","workgroup-update") == 0
                or die "Error while saving settings: $!"; 
                   
     Table_IP($q, $fm->localise('SUCCESSFULLY_REMOVED_ALL_LEASES'));
    exit;
}                  

#===============================================================================
#SUBROUTINE: Scan The Local Network
#===============================================================================
sub Scan_Local_Network ($) {           
    
        esmith::cgi::genHeaderNonCacheable ($q, \%conf, $fm->localise('SCANNING_NETWORK_TITLE'));
        my $nmap_sme = esmith::ConfigDB->open('/home/e-smith/db/configuration');
        my $mask = $nmap_sme->get_value('LocalNetmask');
        my $network = $nmap_sme->get_prop('InternalInterface','Network');

#we start to calculate the method to find the cidr (we want to use network/cidr with nmap)   

   sub dec2bin {
  my $str = unpack("B32", pack("N", shift));
  return $str;
}
 
sub netmask2cidr {
    my ($mask, $network) = @_;
    my @octet = split (/\./, $mask);
    my @bits;
    my $binmask;
    my $binoct;
    my $bitcount=0;
 
    foreach (@octet) {
      $binoct = dec2bin($_);
      $binmask = $binmask . substr $binoct, -8;
    }
 
    # let's count the 1s
    @bits = split (//,$binmask);
    foreach (@bits) {
      if ($_ eq "1") {
        $bitcount++;
      }
    }
 
    my $cidr = $network . "/" . $bitcount;
    return $cidr;
}
   
#Then lets go to calculate the cidr    
   my $cidr = netmask2cidr($mask, $network);

#ok go to use nmap with nmap -T4 -sP network/cidr
            print $q->p ;
            print $q->h3($fm->localise('NETWORK_VALUES_FOUND') . " $cidr  \($mask\)"); 
            print $q->p ;
    print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));

         foreach  (`/usr/bin/nmap --script smb-os-discovery.nse -p U:137,T:139 $cidr|
            /bin/grep -Ev "MAC|NetBIOS|OS CPE"| /bin/grep -E "scan|done|Computer|OS"|
            /bin/sed -e 's/Nmap scan/-- Scan/g'|/bin/sed -e 's/done/Done/g'|
            /bin/sed -e 's/Nmap//g'|/bin/sed -e 's/|/  /g'`) {
            print $q->br($_);}

            print $q->p ;

            print $q->p($fm->localise('CLICK_HERE_TO_MAIN_PANEL'));

        esmith::cgi::genFooter ($q);
        exit;    
        }

__DATA__
<form>
</form>
