mirror of
https://github.com/vincentmli/bpfire.git
synced 2026-04-28 11:43:25 +02:00
pakfire.cgi: Implement Post/Redirect/Get pattern
Refreshing the Pakfire page may cause a command to be executed multiple times and induce odd errors. This patch implements a HTTP 303 redirect after form processing, which causes the browser to discard the POST form data. Navigating backward or reloading the page now does not trigger multiple executions anymore. Fixes: #12781 Signed-off-by: Leo-Andres Hofmann <hofmann@leo-andres.de> Acked-by: Peter Müller <peter.muelle@ipfire.org>
This commit is contained in:
committed by
Peter Müller
parent
3cdb83939b
commit
85d570843e
@@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
use strict;
|
use strict;
|
||||||
use List::Util qw(any);
|
use List::Util qw(any);
|
||||||
|
use URI;
|
||||||
|
|
||||||
# enable only the following on debugging purpose
|
# enable only the following on debugging purpose
|
||||||
#use warnings;
|
#use warnings;
|
||||||
@@ -37,12 +38,17 @@ my %color = ();
|
|||||||
my %pakfiresettings = ();
|
my %pakfiresettings = ();
|
||||||
my %mainsettings = ();
|
my %mainsettings = ();
|
||||||
|
|
||||||
|
# The page mode is used to explictly switch between user interface functions:
|
||||||
|
my $PM_DEFAULT = 'default'; # Default user interface with command processing
|
||||||
|
my $PM_LOGREAD = 'logread'; # Log messages viewer (ignores all commands)
|
||||||
|
my $pagemode = $PM_DEFAULT;
|
||||||
|
|
||||||
# Load general settings
|
# Load general settings
|
||||||
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
&General::readhash("${General::swroot}/main/settings", \%mainsettings);
|
||||||
&General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings);
|
&General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings);
|
||||||
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
&General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
|
||||||
|
|
||||||
# Get CGI request data
|
# Get CGI POST request data
|
||||||
$cgiparams{'ACTION'} = '';
|
$cgiparams{'ACTION'} = '';
|
||||||
$cgiparams{'FORCE'} = '';
|
$cgiparams{'FORCE'} = '';
|
||||||
|
|
||||||
@@ -51,6 +57,17 @@ $cgiparams{'DELPAKS'} = '';
|
|||||||
|
|
||||||
&Header::getcgihash(\%cgiparams);
|
&Header::getcgihash(\%cgiparams);
|
||||||
|
|
||||||
|
# Get CGI GET request data (if available)
|
||||||
|
if($ENV{'QUERY_STRING'}) {
|
||||||
|
my $uri = URI->new($ENV{'REQUEST_URI'});
|
||||||
|
my %query = $uri->query_form;
|
||||||
|
|
||||||
|
my $mode = lc($query{'mode'} // '');
|
||||||
|
if(($mode eq $PM_DEFAULT) || ($mode eq $PM_LOGREAD)) {
|
||||||
|
$pagemode = $mode; # Limit to existing modes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
### Process AJAX/JSON request ###
|
### Process AJAX/JSON request ###
|
||||||
if($cgiparams{'ACTION'} eq 'json-getstatus') {
|
if($cgiparams{'ACTION'} eq 'json-getstatus') {
|
||||||
# Send HTTP headers
|
# Send HTTP headers
|
||||||
@@ -96,19 +113,24 @@ if($cgiparams{'ACTION'} eq 'json-getstatus') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
### Process Pakfire install/update commands ###
|
### Process Pakfire install/update commands ###
|
||||||
if($cgiparams{'ACTION'} ne '') {
|
if(($cgiparams{'ACTION'} ne '') && ($pagemode eq $PM_DEFAULT)) {
|
||||||
if(&_is_pakfire_busy()) {
|
if(&_is_pakfire_busy()) {
|
||||||
$errormessage = $Lang::tr{'pakfire already busy'};
|
$errormessage = $Lang::tr{'pakfire already busy'};
|
||||||
|
$pagemode = $PM_LOGREAD; # Running Pakfire instance found, switch to log viewer mode
|
||||||
} elsif(($cgiparams{'ACTION'} eq 'install') && ($cgiparams{'FORCE'} eq 'on')) {
|
} elsif(($cgiparams{'ACTION'} eq 'install') && ($cgiparams{'FORCE'} eq 'on')) {
|
||||||
my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
|
my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
|
||||||
&General::system_background("/usr/local/bin/pakfire", "install", "--non-interactive", "--no-colors", @pkgs);
|
&General::system_background("/usr/local/bin/pakfire", "install", "--non-interactive", "--no-colors", @pkgs);
|
||||||
|
&_http_pagemode_redirect($PM_LOGREAD, 1);
|
||||||
} elsif(($cgiparams{'ACTION'} eq 'remove') && ($cgiparams{'FORCE'} eq 'on')) {
|
} elsif(($cgiparams{'ACTION'} eq 'remove') && ($cgiparams{'FORCE'} eq 'on')) {
|
||||||
my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
|
my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
|
||||||
&General::system_background("/usr/local/bin/pakfire", "remove", "--non-interactive", "--no-colors", @pkgs);
|
&General::system_background("/usr/local/bin/pakfire", "remove", "--non-interactive", "--no-colors", @pkgs);
|
||||||
|
&_http_pagemode_redirect($PM_LOGREAD, 1);
|
||||||
} elsif($cgiparams{'ACTION'} eq 'update') {
|
} elsif($cgiparams{'ACTION'} eq 'update') {
|
||||||
&General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
|
&General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
|
||||||
|
&_http_pagemode_redirect($PM_LOGREAD, 1);
|
||||||
} elsif($cgiparams{'ACTION'} eq 'upgrade') {
|
} elsif($cgiparams{'ACTION'} eq 'upgrade') {
|
||||||
&General::system_background("/usr/local/bin/pakfire", "upgrade", "-y", "--no-colors");
|
&General::system_background("/usr/local/bin/pakfire", "upgrade", "-y", "--no-colors");
|
||||||
|
&_http_pagemode_redirect($PM_LOGREAD, 1);
|
||||||
} elsif($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
|
} elsif($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
|
||||||
$pakfiresettings{"TREE"} = $cgiparams{"TREE"};
|
$pakfiresettings{"TREE"} = $cgiparams{"TREE"};
|
||||||
|
|
||||||
@@ -122,6 +144,7 @@ if($cgiparams{'ACTION'} ne '') {
|
|||||||
|
|
||||||
# Update lists
|
# Update lists
|
||||||
&General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
|
&General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
|
||||||
|
&_http_pagemode_redirect($PM_LOGREAD, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,8 +244,8 @@ if ($errormessage) {
|
|||||||
&Header::closebox();
|
&Header::closebox();
|
||||||
}
|
}
|
||||||
|
|
||||||
# Show log output while Pakfire is running
|
# Show only log output while Pakfire is running and stop afterwards
|
||||||
if(&_is_pakfire_busy()) {
|
if(($pagemode eq $PM_LOGREAD) || (&_is_pakfire_busy())) {
|
||||||
&Header::openbox("100%", "center", "Pakfire");
|
&Header::openbox("100%", "center", "Pakfire");
|
||||||
|
|
||||||
print <<END
|
print <<END
|
||||||
@@ -253,7 +276,8 @@ END
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Show Pakfire install/remove dependencies and confirm form
|
# Show Pakfire install/remove dependencies and confirm form
|
||||||
if (($cgiparams{'ACTION'} eq 'install') && (! &_is_pakfire_busy())) {
|
# (_is_pakfire_busy status was checked before and can be omitted)
|
||||||
|
if (($cgiparams{'ACTION'} eq 'install') && ($pagemode eq $PM_DEFAULT)) {
|
||||||
&Header::openbox("100%", "center", $Lang::tr{'request'});
|
&Header::openbox("100%", "center", $Lang::tr{'request'});
|
||||||
|
|
||||||
my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
|
my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
|
||||||
@@ -291,7 +315,7 @@ END
|
|||||||
&Header::closepage();
|
&Header::closepage();
|
||||||
exit;
|
exit;
|
||||||
|
|
||||||
} elsif (($cgiparams{'ACTION'} eq 'remove') && (! &_is_pakfire_busy())) {
|
} elsif (($cgiparams{'ACTION'} eq 'remove') && ($pagemode eq $PM_DEFAULT)) {
|
||||||
&Header::openbox("100%", "center", $Lang::tr{'request'});
|
&Header::openbox("100%", "center", $Lang::tr{'request'});
|
||||||
|
|
||||||
my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
|
my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
|
||||||
@@ -476,3 +500,23 @@ sub _start_json_output {
|
|||||||
print "Content-Type: application/json\n";
|
print "Content-Type: application/json\n";
|
||||||
print "\n"; # End of HTTP headers
|
print "\n"; # End of HTTP headers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Send HTTP 303 redirect headers to change page mode
|
||||||
|
# GET is always used to display the redirected page, which will remove already processed POST form data.
|
||||||
|
# Note: Custom headers must be sent before the HTML output is started by &Header::showhttpheaders().
|
||||||
|
# If switch_mode is set to true, the global page mode variable ("$pagemode") is also updated immediately.
|
||||||
|
sub _http_pagemode_redirect {
|
||||||
|
my ($mode, $switch_mode) = @_;
|
||||||
|
$mode //= $PM_DEFAULT;
|
||||||
|
$switch_mode //= 0;
|
||||||
|
|
||||||
|
# Send HTTP redirect with GET parameter
|
||||||
|
my $location = "https://$ENV{'SERVER_NAME'}:$ENV{'SERVER_PORT'}$ENV{'SCRIPT_NAME'}?mode=${mode}";
|
||||||
|
print "Status: 303 See Other\n";
|
||||||
|
print "Location: $location\n";
|
||||||
|
|
||||||
|
# Change global page mode
|
||||||
|
if($switch_mode) {
|
||||||
|
$pagemode = $mode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user