[1/2] manualpages: Add path and file extension to the configuration

Message ID 20220406133940.803-1-hofmann@leo-andres.de
State Superseded
Headers
Series [1/2] manualpages: Add path and file extension to the configuration |

Commit Message

Leo-Andres Hofmann April 6, 2022, 1:39 p.m. UTC
  This allows to correctly assign an URL to a file without relying
on unique base names.
A custom read function is required because General::readhash()
doesn't allow paths as hash keys. Modifying the existing functions
could affect other CGIs and was therefore dismissed.

Fixes: #12806

Signed-off-by: Leo-Andres Hofmann <hofmann@leo-andres.de>
---
 config/cfgroot/header.pl                     |  33 ++++-
 config/cfgroot/manualpages                   | 144 +++++++++----------
 html/html/themes/ipfire/include/functions.pl |   4 +-
 tools/check_manualpages.pl                   |  17 +--
 4 files changed, 110 insertions(+), 88 deletions(-)
  

Patch

diff --git a/config/cfgroot/header.pl b/config/cfgroot/header.pl
index e97f90d67..e6d2b7c78 100644
--- a/config/cfgroot/header.pl
+++ b/config/cfgroot/header.pl
@@ -93,7 +93,7 @@  if ( -d "/var/ipfire/langs/${language}/" ) {
 
 ### Initialize user manual
 my %manualpages = ();
-&General::readhash("${General::swroot}/main/manualpages", \%manualpages);
+&_read_manualpage_hash("${General::swroot}/main/manualpages");
 
 ### Load selected language and theme functions
 require "${swroot}/langs/en.pl";
@@ -558,18 +558,41 @@  sub colorize {
 	}
 }
 
-# Get user manual URL for the specified configuration page, returns empty if no entry is configured
+# 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 ($cgi_page) = @_;
+	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($cgi_page && defined($manualpages{$cgi_page})) {
-		return "$manualpages{'BASE_URL'}/$manualpages{$cgi_page}";
+	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);
+}
diff --git a/config/cfgroot/manualpages b/config/cfgroot/manualpages
index 6c2e54b55..b92a81b56 100644
--- a/config/cfgroot/manualpages
+++ b/config/cfgroot/manualpages
@@ -1,88 +1,88 @@ 
-# Assign manual page URL path to CGI file ([cgi basename]=[path/to/page]) 
+# Assign manual page URL path to CGI file ([cgi file]=[path/to/page])
+# The CGI files are referenced relative to the "/cgi-bin/" path
 
-# Base URL (without trailing slash)
+# Fixed base URL (without trailing slash)
 BASE_URL=https://wiki.ipfire.org
-index=configuration/system/startpage
 
 #	System menu
-index=configuration/system/startpage
-mail=configuration/system/mail_service
-remote=configuration/system/ssh
-backup=configuration/system/backup
-gui=configuration/system/userinterface
-fireinfo=fireinfo
-vulnerabilities=configuration/system/vulnerabilities
-shutdown=configuration/system/shutdown
-credits=configuration/system/credits
+index.cgi=configuration/system/startpage
+mail.cgi=configuration/system/mail_service
+remote.cgi=configuration/system/ssh
+backup.cgi=configuration/system/backup
+gui.cgi=configuration/system/userinterface
+fireinfo.cgi=fireinfo
+vulnerabilities.cgi=configuration/system/vulnerabilities
+shutdown.cgi=configuration/system/shutdown
+credits.cgi=configuration/system/credits
 
 #	Status menu
-system=configuration/status/system
-memory=configuration/status/memory
-services=configuration/status/services
-media=configuration/status/drives
-netexternal=configuration/status/network_ext
-netinternal=configuration/status/network_int
-netother=configuration/status/network_int
-netovpnrw=configuration/status/network_ovpnrw
-#netovpnsrv=
-wio=addons/wio
-hardwaregraphs=configuration/status/hardware_diagrams
-entropy=configuration/status/entropy
-connections=configuration/status/connections
-traffic=configuration/status/nettraffic
-#mdstat=
+system.cgi=configuration/status/system
+memory.cgi=configuration/status/memory
+services.cgi=configuration/status/services
+media.cgi=configuration/status/drives
+netexternal.cgi=configuration/status/network_ext
+netinternal.cgi=configuration/status/network_int
+netother.cgi=configuration/status/network_int
+netovpnrw.cgi=configuration/status/network_ovpnrw
+#netovpnsrv.cgi=
+wio.cgi=addons/wio
+hardwaregraphs.cgi=configuration/status/hardware_diagrams
+entropy.cgi=configuration/status/entropy
+connections.cgi=configuration/status/connections
+traffic.cgi=configuration/status/nettraffic
+#mdstat.cgi=
 
 #	Network menu
-zoneconf=configuration/network/zoneconf
-dns=dns
-proxy=configuration/network/proxy
-urlfilter=configuration/network/proxy/url-filter
-#updatexlrator=configuration/network/proxy/update_accelerator
-dhcp=configuration/network/dhcp
-captive=configuration/network/captive
-connscheduler=configuration/network/connectionscheduler
-hosts=configuration/network/hosts
-dnsforward=configuration/network/dnsforward
-routing=configuration/network/static
-mac=configuration/network/mac-address
-wakeonlan=configuration/network/wake-on-lan
+zoneconf.cgi=configuration/network/zoneconf
+dns.cgi=dns
+proxy.cgi=configuration/network/proxy
+urlfilter.cgi=configuration/network/proxy/url-filter
+#updatexlrator.cgi=configuration/network/proxy/update_accelerator
+dhcp.cgi=configuration/network/dhcp
+captive.cgi=configuration/network/captive
+connscheduler.cgi=configuration/network/connectionscheduler
+hosts.cgi=configuration/network/hosts
+dnsforward.cgi=configuration/network/dnsforward
+routing.cgi=configuration/network/static
+mac.cgi=configuration/network/mac-address
+wakeonlan.cgi=configuration/network/wake-on-lan
 
 #	Services menu
-vpnmain=configuration/services/ipsec
-ovpnmain=configuration/services/openvpn
-ddns=configuration/services/dyndns
-time=configuration/services/ntp
-qos=configuration/services/qos
-guardian=addons/guardian
-extrahd=configuration/services/extrahd
+vpnmain.cgi=configuration/services/ipsec
+ovpnmain.cgi=configuration/services/openvpn
+ddns.cgi=configuration/services/dyndns
+time.cgi=configuration/services/ntp
+qos.cgi=configuration/services/qos
+guardian.cgi=addons/guardian
+extrahd.cgi=configuration/services/extrahd
 
 #	Firewall menu
-firewall=configuration/firewall
-fwhosts=configuration/firewall/fwgroups
-optionsfw=configuration/firewall/options
-ids=configuration/firewall/ips
-location-block=configuration/firewall/geoip-block
-wireless=configuration/firewall/accesstoblue
-iptables=configuration/firewall/iptables
+firewall.cgi=configuration/firewall
+fwhosts.cgi=configuration/firewall/fwgroups
+optionsfw.cgi=configuration/firewall/options
+ids.cgi=configuration/firewall/ips
+location-block.cgi=configuration/firewall/geoip-block
+wireless.cgi=configuration/firewall/accesstoblue
+iptables.cgi=configuration/firewall/iptables
 
 #	IPfire menu
-pakfire=configuration/ipfire/pakfire
-wlanap=addons/wireless
-tor=addons/tor
-mpfire=addons/mpfire
-samba=addons/samba
+pakfire.cgi=configuration/ipfire/pakfire
+wlanap.cgi=addons/wireless
+tor.cgi=addons/tor
+mpfire.cgi=addons/mpfire
+samba.cgi=addons/samba
 
 #	Logs menu
-summary=configuration/logs/summary
-config=configuration/logs/logsettings
-proxylog=configuration/logs/proxy
-calamaris=configuration/logs/proxyreports
-accounting=addons/squid-accounting
-firewalllog=configuration/logs/firewall
-firewalllogip=configuration/logs/firewall-ip
-firewalllogport=configuration/logs/firewall-port
-firewalllogcountry=configuration/logs/firewall-country
-ids=configuration/logs/ips
-#ovpnclients=
-urlfilter=configuration/logs/url-filter
-log=configuration/logs/system
+logs.cgi/summary.dat=configuration/logs/summary
+logs.cgi/config.dat=configuration/logs/logsettings
+logs.cgi/proxylog.dat=configuration/logs/proxy
+logs.cgi/calamaris.dat=configuration/logs/proxyreports
+logs.cgi/accounting.dat=addons/squid-accounting
+logs.cgi/firewalllog.dat=configuration/logs/firewall
+logs.cgi/firewalllogip.dat=configuration/logs/firewall-ip
+logs.cgi/firewalllogport.dat=configuration/logs/firewall-port
+logs.cgi/firewalllogcountry.dat=configuration/logs/firewall-country
+logs.cgi/ids.dat=configuration/logs/ips
+#logs.cgi/ovpnclients.dat=
+logs.cgi/urlfilter.dat=configuration/logs/url-filter
+logs.cgi/log.dat=configuration/logs/system
diff --git a/html/html/themes/ipfire/include/functions.pl b/html/html/themes/ipfire/include/functions.pl
index d74c962e4..40afb3ce3 100644
--- a/html/html/themes/ipfire/include/functions.pl
+++ b/html/html/themes/ipfire/include/functions.pl
@@ -102,8 +102,6 @@  sub openpage {
 	my $boh = shift;
 	my $extrahead = shift;
 	my $suppressMenu = shift;
-	my @tmp = split(/\./, basename($0));
-	my $scriptName = @tmp[0];
 
 	@URI=split ('\?',  $ENV{'REQUEST_URI'} );
 	&General::readhash("${swroot}/main/settings", \%settings);
@@ -176,7 +174,7 @@  END
 ;
 
 # Print user manual link
-my $manual_url = &Header::get_manualpage_url($scriptName);
+my $manual_url = &Header::get_manualpage_url();
 if($manual_url) {
 	print <<END
 				<span><a href="$manual_url" title="$Lang::tr{'online help en'}" target="_blank"><img src="/images/help-browser.png" alt="$Lang::tr{'online help en'}"></a></span>
diff --git a/tools/check_manualpages.pl b/tools/check_manualpages.pl
index 75a560560..446e94649 100644
--- a/tools/check_manualpages.pl
+++ b/tools/check_manualpages.pl
@@ -25,18 +25,19 @@  use strict;
 # Import make.sh environment
 my $basedir = $ENV{'BASEDIR'};
 
-# Load configuration file (General::readhash isn't available yet)
+# Load configuration file (Header::_read_manualpage_hash() isn't available yet)
 my $configfile = "${basedir}/config/cfgroot/manualpages";
 my %manualpages = ();
 
 open(my $file, "<", $configfile) or die "ERROR: Can't read from file '$configfile'!\n";
 while(my $line = <$file>) {
-	$line =~ s/\R//g;
-	next unless($line =~ /=/);
+	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 =~ /(^[A-Za-z0-9_-]+$)/) {
-		my $key = $1; # Got alphanumeric key
+	if($left =~ /^([[:alnum:]\/._-]+)$/) {
+		my $key = $1;
 		$manualpages{$key} = $value;
 	}
 }
@@ -55,11 +56,11 @@  if ($baseurl =~ /\/\s*$/) {
 
 # Loop trough configured manual pages
 foreach my $page (keys %manualpages) {
-	# Build absolute path and URL
-	my $cgifile = "${basedir}/html/cgi-bin/${page}.cgi";
+	# Build absolute path (inside cgi-bin) and URL
+	my $cgifile = "${basedir}/html/cgi-bin/${page}";
 	my $url = "${baseurl}/$manualpages{$page}";
 
-	print "${page}.cgi -> '$url'\n";
+	print "cgi-bin/${page} -> '$url'\n";
 
 	# Check CGI file exists
 	if(! -f $cgifile) {