$|=1; # line buffering
-require "/var/ipfire/aws-functions.pl";
-
$Header::revision = 'final';
$Header::swroot = '/var/ipfire';
$Header::graphdir='/srv/web/ipfire/html/graphs';
%settings = ();
%ethsettings = ();
%pppsettings = ();
-@URI = ();
+my @URI = split('\?', $ENV{'REQUEST_URI'});
### Make sure this is an SSL request
if ($ENV{'SERVER_ADDR'} && $ENV{'HTTPS'} ne 'on') {
};
};
-our $THEME_NAME = $settings{'THEME'};
+### Initialize user manual
+my %manualpages = ();
+&_read_manualpage_hash("${General::swroot}/main/manualpages");
+### Load selected language and theme functions
require "${swroot}/langs/en.pl";
require "${swroot}/langs/${language}.pl";
-eval `/bin/cat /srv/web/ipfire/html/themes/$THEME_NAME/include/functions.pl`;
+eval `/bin/cat /srv/web/ipfire/html/themes/ipfire/include/functions.pl`;
sub green_used() {
if ($ethsettings{'GREEN_DEV'} && $ethsettings{'GREEN_DEV'} ne "") {
$menu->{'02.status'}{'subMenu'}->{'74.modem-status'}{'enabled'} = 1;
}
- # Disbale unusable things on EC2
- if (&AWS::running_on_ec2()) {
+ # Disable the Dialup/PPPoE menu item when the RED interface is in IP mode
+ # (the "Network" module is loaded by general-functions.pl)
+ if(&Network::is_red_mode_ip()) {
+ $menu->{'01.system'}{'subMenu'}->{'20.dialup'}{'enabled'} = 0;
+ }
+
+ # Disbale unusable things in cloud environments
+ if (&General::running_in_cloud()) {
$menu->{'03.network'}{'subMenu'}->{'30.dhcp'}{'enabled'} = 0;
$menu->{'03.network'}{'subMenu'}->{'80.macadressmenu'}{'enabled'} = 0;
$menu->{'03.network'}{'subMenu'}->{'90.wakeonlan'}{'enabled'} = 0;
}
-
- # Disable proxy when no GREEN is available
- if (!&green_used()) {
- $menu->{'03.network'}{'subMenu'}->{'20.proxy'}{'enabled'} = 0;
- $menu->{'03.network'}{'subMenu'}->{'21.urlfilter'}{'enabled'} = 0;
- $menu->{'03.network'}{'subMenu'}->{'22.updxlrator'}{'enabled'} = 0;
- }
}
}
return;
}
-
-# Test if IP is within a subnet
-# Call: IpInSubnet (Addr, Subnet, Subnet Mask)
-# Subnet can be an IP of the subnet: 10.0.0.0 or 10.0.0.1
-# Everything in dottted notation
-# Return: TRUE/FALSE
-sub IpInSubnet
-{
- $ip = unpack('N', inet_aton(shift));
- $start = unpack('N', inet_aton(shift));
- $mask = unpack('N', inet_aton(shift));
- $start &= $mask; # base of subnet...
- $end = $start + ~$mask;
- return (($ip >= $start) && ($ip <= $end));
-}
-
sub escape($) {
my $s = shift;
return HTML::Entities::encode_entities($s);
sub PrintActualLeases
{
- &openbox('100%', 'left', $tr{'current dynamic leases'});
+ &openbox('100%', 'left', $Lang::tr{'current dynamic leases'});
print <<END
<table width='100%' class='tbl'>
<tr>
-<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?IPADDR'><b>$tr{'ip address'}</b></a></th>
-<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ETHER'><b>$tr{'mac address'}</b></a></th>
-<th width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?HOSTNAME'><b>$tr{'hostname'}</b></a></th>
-<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ENDTIME'><b>$tr{'lease expires'} (local time d/m/y)</b></a></th>
-<th width='5%' align='center'><b>Add to fix leases<b></th>
+<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?IPADDR'><b>$Lang::tr{'ip address'}</b></a></th>
+<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ETHER'><b>$Lang::tr{'mac address'}</b></a></th>
+<th width='20%' align='center'><a href='$ENV{'SCRIPT_NAME'}?HOSTNAME'><b>$Lang::tr{'hostname'}</b></a></th>
+<th width='25%' align='center'><a href='$ENV{'SCRIPT_NAME'}?ENDTIME'><b>$Lang::tr{'lease expires'} (local time d/m/y)</b></a></th>
+<th width='5%' align='center'><b>$Lang::tr{'dhcp make fixed lease'}</b></th>
</tr>
END
;
open(LEASES,"/var/state/dhcp/dhcpd.leases") or die "Can't open dhcpd.leases";
- while ($line = <LEASES>) {
- next if( $line =~ /^\s*#/ );
- chomp($line);
- @temp = split (' ', $line);
-
- if ($line =~ /^\s*lease/) {
- $ip = $temp[1];
- #All field are not necessarily read. Clear everything
- $endtime = 0;
- $ether = "";
- $hostname = "";
- }
+ while (my $line = <LEASES>) {
+ next if( $line =~ /^\s*#/ );
+ chomp($line);
+ @temp = split (' ', $line);
+
+ if ($line =~ /^\s*lease/) {
+ $ip = $temp[1];
+ #All field are not necessarily read. Clear everything
+ $endtime = 0;
+ $endtime_print = "";
+ $expired = 0;
+ $ether = "";
+ $hostname = "";
+ }
- if ($line =~ /^\s*ends/) {
- $line =~ /(\d+)\/(\d+)\/(\d+) (\d+):(\d+):(\d+)/;
- $endtime = timegm($6, $5, $4, $3, $2 - 1, $1 - 1900);
- }
+ if ($line =~ /^\s*ends/) {
+ $line =~ /(\d+)\/(\d+)\/(\d+) (\d+):(\d+):(\d+)/;
+ $endtime = timegm($6, $5, $4, $3, $2 - 1, $1 - 1900);
+ ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $dst) = localtime($endtime);
+ $endtime_print = sprintf ("%02d/%02d/%d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec);
+ $expired = $endtime < time();
+ }
- if ($line =~ /^\s*hardware ethernet/) {
- $ether = $temp[2];
- $ether =~ s/;//g;
- }
+ if ($line =~ /^\s*hardware ethernet/) {
+ $ether = $temp[2];
+ $ether =~ s/;//g;
+ }
- if ($line =~ /^\s*client-hostname/) {
- $hostname = "$temp[1] $temp[2] $temp[3]";
- $hostname =~ s/;//g;
- $hostname =~ s/\"//g;
- }
+ if ($line =~ /^\s*client-hostname/) {
+ $hostname = "$temp[1] $temp[2] $temp[3]";
+ $hostname =~ s/\"|[;\s]+?$//g; # remove quotes, trim semicolon and white space
+ }
- if ($line eq "}") {
- @record = ('IPADDR',$ip,'ENDTIME',$endtime,'ETHER',$ether,'HOSTNAME',$hostname);
- $record = {}; # create a reference to empty hash
- %{$record} = @record; # populate that hash with @record
- $entries{$record->{'IPADDR'}} = $record; # add this to a hash of hashes
- }
+ if ($line eq "}") {
+ @record = ('IPADDR',$ip,'ENDTIME',$endtime,'ETHER',$ether,'HOSTNAME',$hostname,'endtime_print',$endtime_print,'expired',$expired);
+ $record = {}; # create a reference to empty hash
+ %{$record} = @record; # populate that hash with @record
+ $entries{$record->{'IPADDR'}} = $record; # add this to a hash of hashes
+ }
}
close(LEASES);
my $id = 0;
- my $col="";
+ my $col = "";
+ my $divider_printed = 0;
foreach my $key (sort leasesort keys %entries) {
- print "<form method='post' action='/cgi-bin/dhcp.cgi'>\n";
- my $hostname = &cleanhtml($entries{$key}->{HOSTNAME},"y");
-
- if ($id % 2) {
- print "<tr>";
- $col="bgcolor='$table1colour'";
- }
- else {
- print "<tr>";
- $col="bgcolor='$table2colour'";
- }
-
- print <<END
+ my $hostname = &cleanhtml($entries{$key}->{HOSTNAME},"y");
+ my $hostname_print = $hostname;
+ if($hostname_print eq "") { #print blank space if no hostname is found
+ $hostname_print = " ";
+ }
+
+ # separate active and expired leases with a horizontal line
+ if(($entries{$key}->{expired}) && ($divider_printed == 0)) {
+ $divider_printed = 1;
+ if ($id % 2) {
+ print "<tr><td colspan='5' bgcolor='$table1colour'><hr size='1'></td></tr>\n";
+ } else {
+ print "<tr><td colspan='5' bgcolor='$table2colour'><hr size='1'></td></tr>\n";
+ }
+ $id++;
+ }
+
+ print "<form method='post' action='/cgi-bin/dhcp.cgi'><tr>\n";
+ if ($id % 2) {
+ $col="bgcolor='$table1colour'";
+ } else {
+ $col="bgcolor='$table2colour'";
+ }
+
+ if($entries{$key}->{expired}) {
+ print <<END
+<td align='center' $col><input type='hidden' name='FIX_ADDR' value='$entries{$key}->{IPADDR}' /><strike><i>$entries{$key}->{IPADDR}</i></strike></td>
+<td align='center' $col><input type='hidden' name='FIX_MAC' value='$entries{$key}->{ETHER}' /><strike><i>$entries{$key}->{ETHER}</i></strike></td>
+<td align='center' $col><input type='hidden' name='FIX_REMARK' value='$hostname' /><strike><i>$hostname_print<i><strike></td>
+<td align='center' $col><input type='hidden' name='FIX_ENABLED' value='on' /><strike><i>$entries{$key}->{endtime_print}</i></strike></td>
+END
+;
+ } else {
+ print <<END
<td align='center' $col><input type='hidden' name='FIX_ADDR' value='$entries{$key}->{IPADDR}' />$entries{$key}->{IPADDR}</td>
<td align='center' $col><input type='hidden' name='FIX_MAC' value='$entries{$key}->{ETHER}' />$entries{$key}->{ETHER}</td>
-<td align='center' $col><input type='hidden' name='FIX_REMARK' value='$hostname' /> $hostname</td>
-<td align='center' $col><input type='hidden' name='FIX_ENABLED' value='on' />
+<td align='center' $col><input type='hidden' name='FIX_REMARK' value='$hostname' />$hostname_print</td>
+<td align='center' $col><input type='hidden' name='FIX_ENABLED' value='on' />$entries{$key}->{endtime_print}</td>
END
;
+ }
- ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $dst) = localtime ($entries{$key}->{ENDTIME});
- $enddate = sprintf ("%02d/%02d/%d %02d:%02d:%02d",$mday,$mon+1,$year+1900,$hour,$min,$sec);
-
- if ($entries{$key}->{ENDTIME} < time() ){
- print "<strike>$enddate</strike>";
- } else {
- print "$enddate";
- }
- print <<END
-</td><td $col><input type='hidden' name='ACTION' value='$Lang::tr{'add'}2' /><input type='submit' name='SUBMIT' value='$Lang::tr{'add'}' />
-</td></tr></form>
+ print <<END
+<td $col><input type='hidden' name='ACTION' value='$Lang::tr{'add'}2' /><input type='submit' name='SUBMIT' value='$Lang::tr{'add'}' /></td>
+</tr></form>
END
;
- $id++;
+ $id++;
}
print "</table>";
# This sub is used during display of actives leases
sub leasesort {
- if (rindex ($dhcpsettings{'SORT_LEASELIST'},'Rev') != -1)
- {
- $qs=substr ($dhcpsettings{'SORT_LEASELIST'},0,length($dhcpsettings{'SORT_LEASELIST'})-3);
- if ($qs eq 'IPADDR') {
- @a = split(/\./,$entries{$a}->{$qs});
- @b = split(/\./,$entries{$b}->{$qs});
- ($b[0]<=>$a[0]) ||
- ($b[1]<=>$a[1]) ||
- ($b[2]<=>$a[2]) ||
- ($b[3]<=>$a[3]);
- }else {
- $entries{$b}->{$qs} cmp $entries{$a}->{$qs};
- }
- }
- else #not reverse
- {
- $qs=$dhcpsettings{'SORT_LEASELIST'};
- if ($qs eq 'IPADDR') {
- @a = split(/\./,$entries{$a}->{$qs});
- @b = split(/\./,$entries{$b}->{$qs});
- ($a[0]<=>$b[0]) ||
- ($a[1]<=>$b[1]) ||
- ($a[2]<=>$b[2]) ||
- ($a[3]<=>$b[3]);
- }else {
- $entries{$a}->{$qs} cmp $entries{$b}->{$qs};
+ if (rindex ($dhcpsettings{'SORT_LEASELIST'},'Rev') != -1)
+ {
+ $qs=substr ($dhcpsettings{'SORT_LEASELIST'},0,length($dhcpsettings{'SORT_LEASELIST'})-3);
+ if ($qs eq 'IPADDR') {
+ @a = split(/\./,$entries{$a}->{$qs});
+ @b = split(/\./,$entries{$b}->{$qs});
+ $entries{$a}->{'expired'} <=> $entries{$b}->{'expired'} || # always sort by expiration first
+ ($b[0]<=>$a[0]) ||
+ ($b[1]<=>$a[1]) ||
+ ($b[2]<=>$a[2]) ||
+ ($b[3]<=>$a[3]);
+ } else {
+ $entries{$a}->{'expired'} <=> $entries{$b}->{'expired'} ||
+ $entries{$b}->{$qs} cmp $entries{$a}->{$qs};
+ }
+ }
+ else #not reverse
+ {
+ $qs=$dhcpsettings{'SORT_LEASELIST'};
+ if ($qs eq 'IPADDR') {
+ @a = split(/\./,$entries{$a}->{$qs});
+ @b = split(/\./,$entries{$b}->{$qs});
+ $entries{$a}->{'expired'} <=> $entries{$b}->{'expired'} ||
+ ($a[0]<=>$b[0]) ||
+ ($a[1]<=>$b[1]) ||
+ ($a[2]<=>$b[2]) ||
+ ($a[3]<=>$b[3]);
+ } else {
+ $entries{$a}->{'expired'} <=> $entries{$b}->{'expired'} ||
+ $entries{$a}->{$qs} cmp $entries{$b}->{$qs};
+ }
}
- }
}
sub colorize {
return "<font color='".${Header::colourovpn}."'>".$string."</font>";
} elsif ( $string =~ "lo" or $string =~ "127.0.0.0" ){
return "<font color='".${Header::colourfw}."'>".$string."</font>";
- } elsif ( $string =~ $ethsettings{'GREEN_DEV'} or &IpInSubnet($string2,$ethsettings{'GREEN_NETADDRESS'},$ethsettings{'GREEN_NETMASK'}) ){
+ } elsif ( $string =~ $ethsettings{'GREEN_DEV'} or &General::IpInSubnet($string2,$ethsettings{'GREEN_NETADDRESS'},$ethsettings{'GREEN_NETMASK'}) ){
return "<font color='".${Header::colourgreen}."'>".$string."</font>";
} elsif ( $string =~ "ppp0" or $string =~ $ethsettings{'RED_DEV'} or $string =~ "0.0.0.0" or $string =~ $ethsettings{'RED_ADDRESS'} ){
return "<font color='".${Header::colourred}."'>".$string."</font>";
- } elsif ( $ethsettings{'CONFIG_TYPE'}>1 and ( $string =~ $ethsettings{'BLUE_DEV'} or &IpInSubnet($string2,$ethsettings{'BLUE_NETADDRESS'},$ethsettings{'BLUE_NETMASK'}) )){
+ } elsif ( $ethsettings{'CONFIG_TYPE'}>1 and ( $string =~ $ethsettings{'BLUE_DEV'} or &General::IpInSubnet($string2,$ethsettings{'BLUE_NETADDRESS'},$ethsettings{'BLUE_NETMASK'}) )){
return "<font color='".${Header::colourblue}."'>".$string."</font>";
- } elsif ( $ethsettings{'CONFIG_TYPE'}>2 and ( $string =~ $ethsettings{'ORANGE_DEV'} or &IpInSubnet($string2,$ethsettings{'ORANGE_NETADDRESS'},$ethsettings{'ORANGE_NETMASK'}) )){
+ } elsif ( $ethsettings{'CONFIG_TYPE'}>2 and ( $string =~ $ethsettings{'ORANGE_DEV'} or &General::IpInSubnet($string2,$ethsettings{'ORANGE_NETADDRESS'},$ethsettings{'ORANGE_NETMASK'}) )){
return "<font color='".${Header::colourorange}."'>".$string."</font>";
} else {
return $string;
}
}
+
+# Get user manual URL for a configuration page inside the "/cgi-bin/"
+# (reads current page from the environment variables unless defined)
+# Returns empty if no URL is available
+sub get_manualpage_url() {
+ my ($cgifile) = @_;
+ $cgifile //= substr($ENV{'SCRIPT_NAME'}, 9); # remove fixed "/cgi-bin/" path
+
+ # Ensure base url is configured
+ return unless($manualpages{'BASE_URL'});
+
+ # Return URL
+ if($cgifile && defined($manualpages{$cgifile})) {
+ return "$manualpages{'BASE_URL'}/$manualpages{$cgifile}";
+ }
+
+ # No manual page configured, return nothing
+ return;
+}
+
+# Private function to load a hash of configured user manual pages from file
+# (run check_manualpages.pl to make sure the file is correct)
+sub _read_manualpage_hash() {
+ my ($filename) = @_;
+
+ open(my $file, "<", $filename) or return; # Fail silent
+ while(my $line = <$file>) {
+ chomp($line);
+ next if(substr($line, 0, 1) eq '#'); # Skip comments
+ next if(index($line, '=', 1) == -1); # Skip incomplete lines
+
+ my($left, $value) = split(/=/, $line, 2);
+ if($left =~ /^([[:alnum:]\/._-]+)$/) {
+ my $key = $1;
+ $manualpages{$key} = $value;
+ }
+ }
+ close($file);
+}
+
+1; # End of package "Header"