--- rpms/smeserver-dhcpmanager/contribs10/smeserver-dhcpmanager-2.0.4-Yet-more-changes-for-SM2-panels.patch 2024/01/16 12:41:01 1.3 +++ rpms/smeserver-dhcpmanager/contribs10/smeserver-dhcpmanager-2.0.4-Yet-more-changes-for-SM2-panels.patch 2024/01/20 14:09:56 1.4 @@ -1,16 +1,28 @@ diff -urN smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/lib/SrvMngr/Controller/Dhcpd.pm smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/lib/SrvMngr/Controller/Dhcpd.pm --- smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/lib/SrvMngr/Controller/Dhcpd.pm 2023-12-19 09:44:56.678590486 +0000 -+++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/lib/SrvMngr/Controller/Dhcpd.pm 2024-01-16 08:38:00.000000000 +0000 -@@ -144,7 +144,7 @@ ++++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/lib/SrvMngr/Controller/Dhcpd.pm 2024-01-20 13:24:00.000000000 +0000 +@@ -137,15 +137,16 @@ + # + # call to show scan results + # ++ my $y = 1/0; + my $c = shift; + my $title = $c->l("dhcpd_SCANNING_NETWORK_TITLE"); + my $modul = ''; +- my $trt = "NETSCAN"; ++ my $trt = "SCAN"; $dhcp_data{trt} = $trt; $dhcp_data{"first"} = ''; - # ..... get scan results into dhcp_data +- # ..... get scan results into dhcp_data - dhcp_data{"scanresults"} = get_scan_results($c); -+ $dhcp_data{"scanresults"} = get_scan_results($c); - $c->stash( title => $title, modul => $modul, dhcp_data => \%dhcp_data ); +- $c->stash( title => $title, modul => $modul, dhcp_data => \%dhcp_data ); ++ # ..... get scan results into stash for passing to html template ++ my $dhcp_scanresults = get_scan_results($c); ++ $c->stash( title => $title, modul => $modul, "dhcp_data" => \%dhcp_data, "scanresults" => $dhcp_scanresults); $c->render( template => 'dhcpd' ); } -@@ -332,10 +332,10 @@ + +@@ -332,10 +333,10 @@ my $c = shift; my $ret = delete_all_leases($c); if ($ret == 'ok') { @@ -23,7 +35,7 @@ diff -urN smeserver-dhcpmanager-2.0.4.ol return ; } -@@ -352,10 +352,10 @@ +@@ -352,17 +353,17 @@ # else return "ok" my $ret = delete_lease($c); if ($ret == 'ok') { @@ -36,34 +48,373 @@ diff -urN smeserver-dhcpmanager-2.0.4.ol return ; } -@@ -536,4 +536,4 @@ + sub get_scan_results { + my $c = shift; + #...do it +- return "results"; ++ return Scan_Local_Network($c); + } + + +@@ -374,13 +375,13 @@ + + sub delete_one_lease { + my $c = shift; +- # ...do it ++ Perform_Del_Lease($c); + return "ok"; + } + + sub delete_all_leases { + my $c = shift; +- # ...do it ++ Perform_del_all_Lease($c); + return "ok"; + } + +@@ -391,6 +392,118 @@ + return @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: $!"; ++ ++ return 'ok'; ++ exit; ++} ++ ++#=============================================================================== ++#SUBROUTINE: Perform delete lease ++#=============================================================================== ++sub Perform_Del_Lease($){ ++ ++ ###Pull CGI object from parameters array ++ my $c = shift; ++ ++ ###Pull entry to delete ++ my $ip = $c->param('host'); ++ my $name = $c->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 () { ++ 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 ++ return $c->l('SUCCESSFULLY_DELETED_THE_CLIENT') . ' (' . $name . '/' . $ip .')'; ++} ++ ++#=============================================================================== ++#SUBROUTINE: Scan The Local Network ++#=============================================================================== ++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; ++} ++ ++sub Scan_Local_Network ($) { ++ ++ 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) ++ my $cidr = netmask2cidr($mask, $network); ++ ++#ok go to use nmap with nmap -T4 -sP network/cidr ++ my @nmap_output= `/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'`; ++ ++ my @extracted_output; ++ foreach my $line (@nmap_output) { ++ if ($line =~ m/Scan report for ([\w\.-]+) \(([\d\.\:]+)\)/) { ++ my %pair = ('Network' => $1, 'ip' => $2); # $1 => PC Name, $2 => IP Address ++ push @extracted_output, \%pair; ++ } ++ } ++ return \@extracted_output; ++} ++ ++ ++ + #========================================================================= + # Procedure qui charge le dhcpd.conf + # retourne un tableau contenant les informations +@@ -536,4 +649,4 @@ 1; - \ No newline at end of file + +diff -urN smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Dhcpd/en.pm smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Dhcpd/en.pm +--- smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Dhcpd/en.pm 1970-01-01 01:00:00.000000000 +0100 ++++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/lib/SrvMngr/I18N/Modules/Dhcpd/en.pm 2024-01-20 08:46:00.000000000 +0000 +@@ -0,0 +1,109 @@ ++package SrvMngr::I18N::Modules::Dhcpd::en; ++use strict; ++use warnings; ++use utf8; ++use Mojo::Base 'SrvMngr::I18N'; ++ ++use SrvMngr::I18N::Modules::General::en; ++ ++my %lexicon = ( ++ 'dhcpd_ACTION' => 'Action', ++ 'dhcpd_ACTIVE_DEVICE' => 'Active Device', ++ 'dhcpd_ALL_OF_THEM' => 'All of them', ++ 'dhcpd_CHECK_CLIENT_STATUS' => 'Always check the status of computers (Disabled is much faster)', ++ 'dhcpd_CLEAN_ALL_DHCPLEASES' => 'You may want to clean the dhcpd.leases', ++ 'dhcpd_CLICK_HERE_TO_MAIN_PANEL' => 'Return to the main panel', ++ 'dhcpd_CONNECTED_IP' => 'Show DHCP Clients', ++ 'dhcpd_CUSTOM_DNS_STATUS' => 'Custom DNS', ++ 'dhcpd_CUSTOM_DNS_TITLE' => 'Enable custom DNS servers.', ++ 'dhcpd_CUSTOM_GATEWAY_ADDRESS' => 'Gateway address', ++ 'dhcpd_CUSTOM_GATEWAY_STATUS' => 'Custom gateway', ++ 'dhcpd_CUSTOM_GATEWAY_TITLE' => 'Enable a custom gateway address.', ++ 'dhcpd_CUSTOM_LEASETIME' => 'Custom lease time', ++ 'dhcpd_CUSTOM_LEASETIME_TITLE' => 'Set the lease time (default is 86400 seconds).', ++ 'dhcpd_CUSTOM_WINSERVER_ADDRESS' => 'WINS Server address', ++ 'dhcpd_CUSTOM_WINSERVER_STATUS' => 'WINS Server', ++ 'dhcpd_CUSTOM_WINSERVER_TITLE' => 'Enable a WINS Server.', ++ 'dhcpd_DHCPD_SETTING_ERRORS' => 'DHCPd Settings ERRORS', ++ 'dhcpd_DHCPD_SETTINGS_TITLE' => 'DHCP server settings', ++ 'dhcpd_DHCPD_TITLE' => 'DHCP Manager', ++ 'dhcpd_DHCP_END' => 'DHCP End', ++ 'dhcpd_DHCP manager' => 'DHCP Manager', ++ 'dhcpd_DHCP_RANGE_MUST_NOT_INCLUDE_SERVER_IP' =>'Incorrect range of IPs, the range of IP address allocation must not include the server address, Update unsuccessfull', ++ 'dhcpd_DHCP_RANGE_WITH_BAD_IP' => 'Incorrect IP in the DHCP range, Update unsuccessfull', ++ 'dhcpd_DHCP_START' => 'DHCP Start', ++ 'dhcpd_DHCP_START_GREATER_DHCP_END_ERRORS' =>'Incorrect range of IPs, the DHCP Start is greater than the DHCP End , Update unsuccessfull', ++ 'dhcpd_DISABLED' => 'Disabled', ++ 'dhcpd_DNS_SERVER_WITH_BAD_IP' => 'Incorrect IP for DNS servers, Update unsuccessfull', ++ 'dhcpd_DO_YOU_WANT_TO_SENT' => 'Do you want to send this message to', ++ 'dhcpd_ENABLED' => 'Enabled', ++ 'dhcpd_END_DATE' => 'End Date', ++ 'dhcpd_ERROR_WHILE_REMOVING_ALL_LEASES' => 'Error while removing all dhcpd Leases', ++ 'dhcpd_ERROR_WHILE_SAVING_SETTINGS' => 'Error while saving settings', ++ 'dhcpd_GATEWAY_BAD_IP' => 'Incorrect IP for Gateway, Update unsuccessfull', ++ 'dhcpd_GLOBAL_WINPOPUP' => 'Send Global Netsend WinPopup', ++ 'dhcpd_GLOBAL_WINPOPUP_TITLE' => 'Send a global WinPopup with the Net send protocol', ++ 'dhcpd_IP' => 'Ip Address', ++ 'dhcpd_MAC_ADDRESS' => 'MAC Address', ++ 'dhcpd_MANAGING_DHCP_CLIENT' => 'Managing DHCP clients', ++ 'dhcpd_NETWORK_NAME' => 'Network Name', ++ 'dhcpd_NETWORK_VALUES_FOUND' => 'Please wait .... Your subnet and your netmask appear to be :', ++ 'dhcpd_NO_CONNECTED_COMPUTERS' => 'There are no connected computers', ++ 'dhcpd_NOT_CHECKED' => 'Not Checked...', ++ 'dhcpd_PRIMARY_DNS_ADDRESS' => 'Primary DNS', ++ 'dhcpd_REFRESH_CONNECTED_IP_LIST' => 'You may want to refresh this list ?', ++ 'dhcpd_REFRESH' => 'Refresh the list', ++ 'dhcpd_REMOVE_ACTION' => 'Remove...', ++ 'dhcpd_REMOVE_A_DHCP_LEASE_ACTION' => 'You are about to remove a client from the dhcpd.leases file.', ++ 'dhcpd_REMOVE_A_DHCP_LEASE' => 'Remove a DHCP lease', ++ 'dhcpd_ARE_YOU_SURE' => 'are you sure ?', ++ 'dhcpd_REMOVE_A_DHCP_LEASE_TITLE' => 'Removing a DHCP Lease', ++ 'dhcpd_REMOVE_ALL_LEASES_ACTION' => 'Remove all dhcpd leases', ++ 'dhcpd_REMOVE_ALL_LEASES' => 'Remove all leases', ++ 'dhcpd_REMOVE_DHCP_LEASE_TITLE' => 'Removing all DHCP Lease', ++ 'dhcpd_REMOVE_DHCP_LEASE_WARNING' => 'Remove all entries in dhcpd.leases may cause issues', ++ 'dhcpd_REMOVE' => 'Remove', ++ 'dhcpd_SAVE/RESTART' => 'Save/Restart', ++ 'dhcpd_SAVE_TITLE' => 'After changing settings above, you must save and restart dhcpd.', ++ 'dhcpd_SCANNING_NETWORK_TITLE' => 'Scanning your network, the time needed depends on your subnet mask', ++ 'dhcpd_SCAN_YOUR_NETWORK' => 'Scan your network', ++ 'dhcpd_SCAN_YOUR_NETWORK_TITLE' => 'Scan your network to show active devices :', ++ 'dhcpd_SECONDARY_DNS_ADDRESS' => 'Secondary DNS', ++ 'dhcpd_SENDING_A_WINPOPUP' => 'Sending a WinPopup', ++ 'dhcpd_SENDING_A_WINPOPUP_TO' => 'You are about to send a WinPopup to ', ++ 'dhcpd_SEND_WINPOPUP_TO' => 'Send a WinPopup to', ++ 'dhcpd_SHOW_CONNECTED_IP_TITLE' => 'Show all devices connected to the dhcpd server :', ++ 'dhcpd_START_DATE' => 'Start Date', ++ 'dhcpd_STATUS_CLICK_FOR_WOL' => 'Status - click for WOL', ++ 'dhcpd_STATUS_DHCP_SERVER' => 'State of DHCPD', ++ 'dhcpd_STATUS_REPORT' => 'Operation status report :', ++ 'dhcpd_SUCCESSFULLY_CLIENT_WOL_REQUEST' =>'Successfull request to wake up the client. The computer may take time to wake up.', ++ 'dhcpd_SUCCESSFULLY_DELETED_THE_CLIENT' => 'Successfully deleted the client in dhcpd.leases : ', ++ 'dhcpd_SUCCESSFULLY_REMOVED_ALL_LEASES' => 'Successfully deleted all leases.', ++ 'dhcpd_SUCCESSFULLY_SAVED_SETTINGS' => 'Successfully saved settings', ++ 'dhcpd_SUCCESSFULLY_SENT_MESSAGE' => 'Successfully sent message popup to', ++ 'dhcpd_TERTIARY_DNS_ADDRESS' => 'Tertiary DNS', ++ 'dhcpd_WAKE_UP_ACTION' => 'Wake-Up...', ++ 'dhcpd_WAKE_UP' => 'Wake UP', ++ 'dhcpd_WAKING_A_REMOTE_COMPUTER_ACTION' => 'Are you sure you want to wake on lan the client : ', ++ 'dhcpd_WAKING_A_REMOTE_COMPUTER_TITLE' => 'Waking Up a remote computer', ++ 'dhcpd_WAKING_A_REMOTE_COMPUTER' => 'You are about to wake up a remote computer.', ++ 'dhcpd_WARNING_NO_WINPOPUP_GARANTY' =>'Warning, there is no guarantee that the popup will appear on the remote computer.', ++ 'dhcpd_WINPOPUP_ACTION' => 'WinPopup...', ++ 'dhcpd_WINSSERVER_BAD_IP' => 'Incorrect IP for WINS Server, Update unsuccessfull', ++ 'dhcpd_WRITE_YOUR_MESSAGE' => 'Write your message here', ++ 'dhcpd_YOUR_MESSAGE' => 'Your message', ++ 'dhcpd_REMOVE_DHCP_LEASE_WARNING2' => 'The lease file is a log-structured file - whenever a lease changes, the ++ contents of that lease are written to the end of the file. This means that it is entirely possible for there to be two ++ or more declarations of the same lease in the lease file at the same ++ time. In that case, the instance of that particular lease that ++ appears last in the file is the one that is in effect.', ++); ++ ++our %Lexicon = ( ++ %{ SrvMngr::I18N::Modules::General::en::Lexicon }, ++ %lexicon ++); ++ ++ ++1; diff -urN smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/dhcpd.html.ep smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/dhcpd.html.ep --- smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/dhcpd.html.ep 2023-12-19 09:44:56.680590493 +0000 -+++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/dhcpd.html.ep 2023-12-19 11:12:00.000000000 +0000 -@@ -63,9 +63,12 @@ - - - %= button_to $c->l('dhcpd_SCAN_YOUR_NETWORK') => '/dhcpd3' ++++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/dhcpd.html.ep 2024-01-20 13:44:00.000000000 +0000 +@@ -49,24 +49,26 @@ + + % if ($dhcp_data->{trt} eq 'LEASES') { + %= include 'partials/_dhcpd_leases' +- %} elsif ($dhcp_data->{trt} eq 'WINPOPUP') { +- %= include 'partials/_dhcpd_winpopup' + %} elsif ($dhcp_data->{trt} eq 'SCAN') { + %= include 'partials/_dhcpd_scan' + %} else { #PARAMS + % my $ip_regex = '^((\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$'; +- -+ - +- ++
+- %= button_to $c->l('dhcpd_CONNECTED_IP') => '/dhcpd1', onclick=>"showSpinner()", id=>"scanLeases" +- +- +- %= button_to $c->l('dhcpd_SCAN_YOUR_NETWORK') => '/dhcpd3' - - %= button_to $c->l('dhcpd_GLOBAL_WINPOPUP') => '/dhcpd2' -+
+-
++ ++ ++
++ %= button_to $c->l('dhcpd_CONNECTED_IP') => '/dhcpd1', onclick=>"showSpinnerLeases()", id=>"scanLeases" ++ ++ ++ %= button_to $c->l('dhcpd_SCAN_YOUR_NETWORK') => '/dhcpd3, onclick=>"showSpinnerNetwork()", id=>"scanNetwork' ++ ++

+

+@@ -180,10 +182,17 @@ + + %= javascript begin + document.getElementById("load").style.display="none"; +- function showSpinner(){ ++ document.getElementById("loadingNetwork").style.display="none"; ++ ++ function showSpinnerLeases(){ + document.getElementById("scanLeases").style.display="none"; + document.getElementById("load").style.display="inline"; + } ++ ++ function showSpinnerNetwork(){ ++ document.getElementById("scanNetwork").style.display="none"; ++ document.getElementById("loadingNetwork").style.display="inline"; ++ } + %end + + %= stylesheet begin +@@ -205,7 +214,6 @@ + border-color: darkgrey; + border-image: initial; + } +- + %end +- + %end ++1; diff -urN smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_leases.html.ep smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_leases.html.ep --- smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_leases.html.ep 2023-12-19 09:44:56.681590497 +0000 -+++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_leases.html.ep 2024-01-16 12:32:00.000000000 +0000 ++++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_leases.html.ep 2024-01-20 11:29:00.000000000 +0000 +@@ -1,17 +1,17 @@ +
+ +- ++ %= button_to $c->l('dhcpd_REFRESH') => '/dhcpd1', onclick=>"showSpinnerLeases()", id=>"scanLeases" ++ ++ ++ ++ +
+- %= button_to $c->l('dhcpd_REFRESH') => '/dhcpd1', onclick=>"showSpinner()", id=>"scanLeases" +- +- +- +- %= button_to $c->l('dhcpd_REMOVE_ALL_LEASES') => '/dhcpd4' +-
++ %= button_to $c->l('dhcpd_REMOVE_ALL_LEASES') => '/dhcpd4' ++
+-
++ + % my $btn = l('dhcpd_SAVE/RESTART'); + %= form_for '/dhcpd10' => (method => 'POST') => begin + @@ -26,7 +26,7 @@ %= submit_button "$btn", class => 'action' % end @@ -103,3 +454,56 @@ diff -urN smeserver-dhcpmanager-2.0.4.ol -
\ No newline at end of file + +diff -urN smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_scan.html.ep smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_scan.html.ep +--- smeserver-dhcpmanager-2.0.4.old/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_scan.html.ep 1970-01-01 01:00:00.000000000 +0100 ++++ smeserver-dhcpmanager-2.0.4/root/usr/share/smanager/themes/default/templates/partials/_dhcpd_scan.html.ep 2024-01-20 11:34:00.000000000 +0000 +@@ -0,0 +1,49 @@ ++
++ ++ ++ ++
++ %= button_to $c->l('dhcpd_REFRESH') => '/dhcpd3', onclick=>"showSpinnerNetwork()", id=>"scanNetwork" ++ ++ ++
++ ++ ++ ++ ++ ++ ++ ++ % foreach my $ip (@$scanresults) { ++ ++ %= t td => (class => 'sme-border') => $ip->{Network} ++ %= t td => (class => 'sme-border') => $ip->{ip} ++ ++ %} ++ ++
++ %=l 'dhcpd_NETWORK_NAME' ++ ++ %=l 'dhcpd_IP' ++
++ %= hidden_field "hiddenmsg"=>"", id=>"hiddenmsg" ++
++ %= button_to $c->l('dhcpd_CLICK_HERE_TO_MAIN_PANEL') => '/dhcpd' ++ ++ %= javascript begin ++ function Wol_confirm(event,msg,current){ ++ const getMAC = /.*MAC\=(.*)\&name.*/; ++ var MAC = current.href.match(getMAC)[1]; ++ if (confirm(msg+": MAC: "+MAC)) ++ { return true;} ++ else {event.preventDefault();return false;} ++ } ++ ++ ++ %end ++ ++ ++