]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blobdiff - html/cgi-bin/pakfire.cgi
suricata: Change midstream policy to "pass-flow"
[people/pmueller/ipfire-2.x.git] / html / cgi-bin / pakfire.cgi
index 65c67fb90c1fe0f47da3556bd7f0846460466359..42c603c6130d73547105ae4464b572510c9cc7db 100644 (file)
@@ -21,6 +21,7 @@
 
 use strict;
 use List::Util qw(any);
+use URI;
 
 # enable only the following on debugging purpose
 #use warnings;
@@ -37,19 +38,39 @@ my %color = ();
 my %pakfiresettings = ();
 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;
+
+# Get Pakfire status
+my %pakfire_status = &Pakfire::status();
+
 # Load general settings
 &General::readhash("${General::swroot}/main/settings", \%mainsettings);
+&General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings);
 &General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color);
 
-# Get CGI request data
+# Get CGI POST request data
 $cgiparams{'ACTION'} = '';
-$cgiparams{'VALID'} = '';
+$cgiparams{'FORCE'} = '';
 
 $cgiparams{'INSPAKS'} = '';
 $cgiparams{'DELPAKS'} = '';
 
 &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 ###
 if($cgiparams{'ACTION'} eq 'json-getstatus') {
        # Send HTTP headers
@@ -57,7 +78,7 @@ if($cgiparams{'ACTION'} eq 'json-getstatus') {
 
        # Read /var/log/messages backwards until a "Pakfire started" header is found,
        # to capture all messages of the last (i.e. current) Pakfire run
-       my @messages = `tac /var/log/messages | sed -n '/pakfire:/{p;/Pakfire.*started/q}'`;
+       my @messages = `tac /var/log/messages 2>/dev/null | sed -n '/pakfire:/{p;/Pakfire.*started/q}'`;
 
        # Test if the log contains an error message (fastest implementation, stops at first match)
        my $failure = any{ index($_, 'ERROR') != -1 } @messages;
@@ -66,7 +87,7 @@ if($cgiparams{'ACTION'} eq 'json-getstatus') {
        my %status = (
                'running' => &_is_pakfire_busy() || "0",
                'running_since' => &General::age("$Pakfire::lockfile") || "0s",
-               'reboot' => (-e "/var/run/need_reboot") || "0",
+               'reboot' => ("$pakfire_status{'RebootRequired'}" eq "yes") || "0",
                'failure' => $failure || "0"
        );
 
@@ -94,6 +115,43 @@ if($cgiparams{'ACTION'} eq 'json-getstatus') {
        exit;
 }
 
+### Process Pakfire install/update commands ###
+if(($cgiparams{'ACTION'} ne '') && ($pagemode eq $PM_DEFAULT)) {
+       if(&_is_pakfire_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')) {
+               my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
+               &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')) {
+               my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
+               &General::system_background("/usr/local/bin/pakfire", "remove", "--non-interactive", "--no-colors", @pkgs);
+               &_http_pagemode_redirect($PM_LOGREAD, 1);
+       } elsif($cgiparams{'ACTION'} eq 'update') {
+               &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
+               &_http_pagemode_redirect($PM_LOGREAD, 1);
+       } elsif($cgiparams{'ACTION'} eq 'upgrade') {
+               &General::system_background("/usr/local/bin/pakfire", "upgrade", "-y", "--no-colors");
+               &_http_pagemode_redirect($PM_LOGREAD, 1);
+       } elsif($cgiparams{'ACTION'} eq $Lang::tr{'save'}) {
+               $pakfiresettings{"TREE"} = $cgiparams{"TREE"};
+
+               # Check for valid input
+               if ($pakfiresettings{"TREE"} !~ m/^(stable|testing|unstable)$/) {
+                       $errormessage .= $Lang::tr{'pakfire invalid tree'};
+               }
+
+               unless ($errormessage) {
+                       &General::writehash("${General::swroot}/pakfire/settings", \%pakfiresettings);
+
+                       # Update lists
+                       &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
+                       &_http_pagemode_redirect($PM_LOGREAD, 1);
+               }
+       }
+}
+
 ### Start pakfire page ###
 &Header::showhttpheaders();
 
@@ -182,128 +240,15 @@ END
 &Header::openpage($Lang::tr{'pakfire configuration'}, 1, $extraHead);
 &Header::openbigbox('100%', 'left', '', $errormessage);
 
-# Process Pakfire commands
-if (($cgiparams{'ACTION'} eq 'install') && (! &_is_pakfire_busy())) {
-       my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
-       if ("$cgiparams{'FORCE'}" eq "on") {
-               &General::system_background("/usr/local/bin/pakfire", "install", "--non-interactive", "--no-colors", @pkgs);
-       } else {
-               &Header::openbox("100%", "center", $Lang::tr{'request'});
-               my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs);
-               print <<END;
-               <table><tr><td colspan='2'>$Lang::tr{'pakfire install package'} @pkgs $Lang::tr{'pakfire possible dependency'}
-               <pre>
-END
-               foreach (@output) {
-                 $_ =~ s/\\e\[[0-1]\;[0-9]+m//g;
-                       print "$_\n";
-               }
-               print <<END;
-               </pre></td></tr>
-               <tr><td colspan='2'>$Lang::tr{'pakfire accept all'}</td></tr>
-               <tr><td colspan='2'>&nbsp;</td></tr>
-               <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'>
-                                                       <input type='hidden' name='INSPAKS' value='$cgiparams{'INSPAKS'}' />
-                                                       <input type='hidden' name='FORCE' value='on' />
-                                                       <input type='hidden' name='ACTION' value='install' />
-                                                       <input type='image' alt='$Lang::tr{'install'}' title='$Lang::tr{'install'}' src='/images/go-next.png' />
-                                               </form>
-                               </td>
-                               <td align='left'>
-                                               <form method='post' action='$ENV{'SCRIPT_NAME'}'>
-                                                       <input type='hidden' name='ACTION' value='' />
-                                                       <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' />
-                                               </form>
-                               </td>
-                       </tr>
-               </table>
-END
-               &Header::closebox();
-               &Header::closebigbox();
-               &Header::closepage();
-               exit;
-       }
-} elsif (($cgiparams{'ACTION'} eq 'remove') && (! &_is_pakfire_busy())) {
-       my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
-       if ("$cgiparams{'FORCE'}" eq "on") {
-               &General::system_background("/usr/local/bin/pakfire", "remove", "--non-interactive", "--no-colors", @pkgs);
-       } else {
-               &Header::openbox("100%", "center", $Lang::tr{'request'});
-               my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs);
-               print <<END;
-               <table><tr><td colspan='2'>$Lang::tr{'pakfire uninstall package'} @pkgs $Lang::tr{'pakfire possible dependency'}
-               <pre>
-END
-               foreach (@output) {
-                 $_ =~ s/\\e\[[0-1]\;[0-9]+m//g;
-                       print "$_\n";
-               }
-               print <<END;
-               </pre></td></tr>
-               <tr><td colspan='2'>$Lang::tr{'pakfire uninstall all'}</td></tr>
-               <tr><td colspan='2'>&nbsp;</td></tr>
-               <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'>
-                                                       <input type='hidden' name='DELPAKS' value='$cgiparams{'DELPAKS'}' />
-                                                       <input type='hidden' name='FORCE' value='on' />
-                                                       <input type='hidden' name='ACTION' value='remove' />
-                                                       <input type='image' alt='$Lang::tr{'uninstall'}' title='$Lang::tr{'uninstall'}' src='/images/go-next.png' />
-                                               </form>
-                               </td>
-                               <td align='left'>
-                                               <form method='post' action='$ENV{'SCRIPT_NAME'}'>
-                                                       <input type='hidden' name='ACTION' value='' />
-                                                       <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' />
-                                               </form>
-                               </td>
-                       </tr>
-               </table>
-END
-               &Header::closebox();
-               &Header::closebigbox();
-               &Header::closepage();
-               exit;
-       }
-
-} elsif (($cgiparams{'ACTION'} eq 'update') && (! &_is_pakfire_busy())) {
-       &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
-} elsif (($cgiparams{'ACTION'} eq 'upgrade') && (! &_is_pakfire_busy())) {
-       &General::system_background("/usr/local/bin/pakfire", "upgrade", "-y", "--no-colors");
-} elsif ($cgiparams{'ACTION'} eq "$Lang::tr{'save'}") {
-       $pakfiresettings{"TREE"} = $cgiparams{"TREE"};
-
-       # Check for valid input
-       if ($pakfiresettings{"TREE"} !~ m/^(stable|testing|unstable)$/) {
-               $errormessage .= $Lang::tr{'pakfire invalid tree'};
-       }
-
-       unless ($errormessage) {
-               &General::writehash("${General::swroot}/pakfire/settings", \%pakfiresettings);
-
-               # Update lists
-               &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors");
-       }
-}
-
-&General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings);
-
-my %selected=();
-my %checked=();
-
-$selected{"TREE"} = ();
-$selected{"TREE"}{"stable"} = "";
-$selected{"TREE"}{"testing"} = "";
-$selected{"TREE"}{"unstable"} = "";
-$selected{"TREE"}{$pakfiresettings{"TREE"}} = "selected";
-
-# DPC move error message to top so it is seen!
+# Show error message
 if ($errormessage) {
        &Header::openbox('100%', 'left', $Lang::tr{'error messages'});
        print "<font class='base'>$errormessage&nbsp;</font>\n";
        &Header::closebox();
 }
 
-# Show log output while Pakfire is running
-if(&_is_pakfire_busy()) {
+# Show only log output while Pakfire is running and stop afterwards
+if(($pagemode eq $PM_LOGREAD) || (&_is_pakfire_busy())) {
        &Header::openbox("100%", "center", "Pakfire");
 
        print <<END
@@ -333,32 +278,117 @@ END
        exit;
 }
 
-my $core_release = `cat /opt/pakfire/db/core/mine 2>/dev/null`;
-chomp($core_release);
-my $core_update_age = &General::age("/opt/pakfire/db/core/mine");
-my $corelist_update_age = &General::age("/opt/pakfire/db/lists/core-list.db");
-my $server_update_age = &General::age("/opt/pakfire/db/lists/server-list.db");
-my $packages_update_age = &General::age("/opt/pakfire/db/lists/packages_list.db");
+# Show Pakfire install/remove dependencies and confirm form
+# (_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'});
+
+       my @pkgs = split(/\|/, $cgiparams{'INSPAKS'});
+       my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs);
+       print <<END;
+       <table style="width: 100%"><tr><td colspan='2'><p>$Lang::tr{'pakfire install package'} <strong>@{pkgs}</strong><br>
+               $Lang::tr{'pakfire possible dependency'}</p>
+               <pre>
+END
+       foreach (@output) {
+               $_ =~ s/\\e\[[0-1]\;[0-9]+m//g;
+               print "$_\n";
+       }
+       print <<END;
+               </pre></td></tr>
+               <tr><td colspan='2'>$Lang::tr{'pakfire accept all'}</td></tr>
+               <tr><td colspan='2'>&nbsp;</td></tr>
+               <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                       <input type='hidden' name='INSPAKS' value='$cgiparams{'INSPAKS'}' />
+                                       <input type='hidden' name='FORCE' value='on' />
+                                       <input type='hidden' name='ACTION' value='install' />
+                                       <input type='image' alt='$Lang::tr{'install'}' title='$Lang::tr{'install'}' src='/images/go-next.png' />
+                               </form>
+                       </td>
+                       <td align='left'>
+                               <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                       <input type='hidden' name='ACTION' value='' />
+                                       <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' />
+                               </form>
+                       </td>
+               </tr>
+       </table>
+END
+       &Header::closebox();
+       &Header::closebigbox();
+       &Header::closepage();
+       exit;
+
+} elsif (($cgiparams{'ACTION'} eq 'remove') && ($pagemode eq $PM_DEFAULT)) {
+       &Header::openbox("100%", "center", $Lang::tr{'request'});
+
+       my @pkgs = split(/\|/, $cgiparams{'DELPAKS'});
+       my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs);
+       print <<END;
+       <table style="width: 100%"><tr><td colspan='2'><p>$Lang::tr{'pakfire uninstall package'} <strong>@{pkgs}</strong><br>
+               $Lang::tr{'pakfire possible dependency'}</p>
+               <pre>
+END
+       foreach (@output) {
+               $_ =~ s/\\e\[[0-1]\;[0-9]+m//g;
+               print "$_\n";
+       }
+       print <<END;
+               </pre></td></tr>
+               <tr><td colspan='2'>$Lang::tr{'pakfire uninstall all'}</td></tr>
+               <tr><td colspan='2'>&nbsp;</td></tr>
+               <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                       <input type='hidden' name='DELPAKS' value='$cgiparams{'DELPAKS'}' />
+                                       <input type='hidden' name='FORCE' value='on' />
+                                       <input type='hidden' name='ACTION' value='remove' />
+                                       <input type='image' alt='$Lang::tr{'uninstall'}' title='$Lang::tr{'uninstall'}' src='/images/go-next.png' />
+                               </form>
+                       </td>
+                       <td align='left'>
+                               <form method='post' action='$ENV{'SCRIPT_NAME'}'>
+                                       <input type='hidden' name='ACTION' value='' />
+                                       <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' />
+                               </form>
+                       </td>
+               </tr>
+       </table>
+END
+       &Header::closebox();
+       &Header::closebigbox();
+       &Header::closepage();
+       exit;
+}
+
+# Show Pakfire main page
+my %selected=();
+my %checked=();
+
+$selected{"TREE"} = ();
+$selected{"TREE"}{"stable"} = "";
+$selected{"TREE"}{"testing"} = "";
+$selected{"TREE"}{"unstable"} = "";
+$selected{"TREE"}{$pakfiresettings{"TREE"}} = "selected";
 
 &Header::openbox("100%", "center", "Pakfire");
 
 print <<END;
        <table id="pfmain">
 END
-if ( -e "/var/run/need_reboot") {
+if ("$pakfire_status{'RebootRequired'}" eq "yes") {
        print "\t\t<tr><td colspan='2'><a href='/cgi-bin/shutdown.cgi'>$Lang::tr{'needreboot'}!</a></td></tr>\n";
 }
+
 print <<END;
                <tr><td class="heading">$Lang::tr{'pakfire system state'}:</td>
                        <td class="heading">$Lang::tr{'available updates'}:</td></tr>
 
-               <tr><td><strong>$Lang::tr{'pakfire core update level'}: $core_release</strong>
+               <tr><td><strong>$Lang::tr{'pakfire core update level'}: $pakfire_status{'Release'}</strong>
                                <hr>
                                <div class="pflist">
-                                       $Lang::tr{'pakfire last update'} $core_update_age $Lang::tr{'pakfire ago'}<br>
-                                       $Lang::tr{'pakfire last serverlist update'} $server_update_age $Lang::tr{'pakfire ago'}<br>
-                                       $Lang::tr{'pakfire last core list update'} $corelist_update_age $Lang::tr{'pakfire ago'}<br>
-                                       $Lang::tr{'pakfire last package update'} $packages_update_age $Lang::tr{'pakfire ago'}
+                                       $Lang::tr{'pakfire last update'} $pakfire_status{'LastUpdate'} $Lang::tr{'pakfire ago'}<br>
+                                       $Lang::tr{'pakfire last serverlist update'} $pakfire_status{'LastServerListUpdate'} $Lang::tr{'pakfire ago'}<br>
+                                       $Lang::tr{'pakfire last core list update'} $pakfire_status{'LastCoreListUpdate'} $Lang::tr{'pakfire ago'}<br>
+                                       $Lang::tr{'pakfire last package update'} $pakfire_status{'LastPakListUpdate'} $Lang::tr{'pakfire ago'}
                                </div>
                                <form method='post' action='$ENV{'SCRIPT_NAME'}'>
                                        <input type='hidden' name='ACTION' value='update' />
@@ -370,7 +400,17 @@ print <<END;
                                        <select name="UPDPAKS" class="pflist" size="5" disabled>
 END
 
-       &Pakfire::dblist("upgrade", "forweb");
+       if ("$pakfire_status{'CoreUpdateAvailable'}" eq "yes") {
+               print "<option value=\"core\">$Lang::tr{'core update'} -- $pakfire_status{'CoreVersion'} -- $Lang::tr{'release'}: $pakfire_status{'Release'} -> $pakfire_status{'AvailableRelease'}</option>\n";
+       }
+
+       if ($pakfire_status{'PakUpdatesAvailable'} > 0) {
+               my %upgradelist = &Pakfire::dblist("upgrade");
+               foreach my $pak (sort keys %upgradelist) {
+                       print "<option value=\"$pak\">$Lang::tr{'pak update'}: $pak -- $Lang::tr{'version'}: $upgradelist{$pak}{'ProgVersion'} -> $upgradelist{$pak}{'AvailableProgVersion'} -- $Lang::tr{'release'}: $upgradelist{$pak}{'Release'} -> $upgradelist{$pak}{'AvailableRelease'}</option>\n";
+               }
+       }
+
        print <<END;
                                        </select>
                                        <input type='hidden' name='ACTION' value='upgrade' />
@@ -386,7 +426,11 @@ END
                                        <select name="INSPAKS" class="pflist" size="10" multiple>
 END
 
-       &Pakfire::dblist("notinstalled", "forweb");
+       my %notinstalledlist = &Pakfire::dblist("notinstalled");
+       foreach my $pak (sort keys %notinstalledlist) {
+               print "<option value=\"$pak\">$pak-$notinstalledlist{$pak}{'ProgVersion'}-$notinstalledlist{$pak}{'Release'}</option>\n";
+       }
+
        print <<END;
                                        </select>
                                        <input type='hidden' name='ACTION' value='install' />
@@ -398,7 +442,11 @@ END
                                        <select name="DELPAKS" class="pflist" size="10" multiple>
 END
 
-       &Pakfire::dblist("installed", "forweb");
+       my %installedlist = &Pakfire::dblist("installed");
+       foreach my $pak (sort keys %installedlist) {
+               print "<option value=\"$pak\">$pak-$installedlist{$pak}{'ProgVersion'}-$installedlist{$pak}{'Release'}</option>\n";
+       }
+
        print <<END;
                                        </select>
                                        <input type='hidden' name='ACTION' value='remove' />
@@ -469,3 +517,23 @@ sub _start_json_output {
        print "Content-Type: application/json\n";
        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;
+       }
+}