]>
Commit | Line | Data |
---|---|---|
1 | #!/usr/bin/perl | |
2 | ############################################################################### | |
3 | # # | |
4 | # IPFire.org - A linux based firewall # | |
5 | # Copyright (C) 2007-2022 IPFire Team <info@ipfire.org> # | |
6 | # # | |
7 | # This program is free software: you can redistribute it and/or modify # | |
8 | # it under the terms of the GNU General Public License as published by # | |
9 | # the Free Software Foundation, either version 3 of the License, or # | |
10 | # (at your option) any later version. # | |
11 | # # | |
12 | # This program is distributed in the hope that it will be useful, # | |
13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of # | |
14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # | |
15 | # GNU General Public License for more details. # | |
16 | # # | |
17 | # You should have received a copy of the GNU General Public License # | |
18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. # | |
19 | # # | |
20 | ############################################################################### | |
21 | ||
22 | use strict; | |
23 | use List::Util qw(any); | |
24 | use URI; | |
25 | ||
26 | # enable only the following on debugging purpose | |
27 | #use warnings; | |
28 | #use CGI::Carp 'fatalsToBrowser'; | |
29 | ||
30 | require '/var/ipfire/general-functions.pl'; | |
31 | require "${General::swroot}/lang.pl"; | |
32 | require "${General::swroot}/header.pl"; | |
33 | require "/opt/pakfire/lib/functions.pl"; | |
34 | ||
35 | my %cgiparams=(); | |
36 | my $errormessage = ''; | |
37 | my %color = (); | |
38 | my %pakfiresettings = (); | |
39 | my %mainsettings = (); | |
40 | ||
41 | # The page mode is used to explictly switch between user interface functions: | |
42 | my $PM_DEFAULT = 'default'; # Default user interface with command processing | |
43 | my $PM_LOGREAD = 'logread'; # Log messages viewer (ignores all commands) | |
44 | my $pagemode = $PM_DEFAULT; | |
45 | ||
46 | # Get Pakfire status | |
47 | my %pakfire_status = &Pakfire::status(); | |
48 | ||
49 | # Load general settings | |
50 | &General::readhash("${General::swroot}/main/settings", \%mainsettings); | |
51 | &General::readhash("${General::swroot}/pakfire/settings", \%pakfiresettings); | |
52 | &General::readhash("/srv/web/ipfire/html/themes/ipfire/include/colors.txt", \%color); | |
53 | ||
54 | # Get CGI POST request data | |
55 | $cgiparams{'ACTION'} = ''; | |
56 | $cgiparams{'FORCE'} = ''; | |
57 | ||
58 | $cgiparams{'INSPAKS'} = ''; | |
59 | $cgiparams{'DELPAKS'} = ''; | |
60 | ||
61 | &Header::getcgihash(\%cgiparams); | |
62 | ||
63 | # Get CGI GET request data (if available) | |
64 | if($ENV{'QUERY_STRING'}) { | |
65 | my $uri = URI->new($ENV{'REQUEST_URI'}); | |
66 | my %query = $uri->query_form; | |
67 | ||
68 | my $mode = lc($query{'mode'} // ''); | |
69 | if(($mode eq $PM_DEFAULT) || ($mode eq $PM_LOGREAD)) { | |
70 | $pagemode = $mode; # Limit to existing modes | |
71 | } | |
72 | } | |
73 | ||
74 | ### Process AJAX/JSON request ### | |
75 | if($cgiparams{'ACTION'} eq 'json-getstatus') { | |
76 | # Send HTTP headers | |
77 | _start_json_output(); | |
78 | ||
79 | # Read /var/log/messages backwards until a "Pakfire started" header is found, | |
80 | # to capture all messages of the last (i.e. current) Pakfire run | |
81 | my @messages = `tac /var/log/messages 2>/dev/null | sed -n '/pakfire:/{p;/Pakfire.*started/q}'`; | |
82 | ||
83 | # Test if the log contains an error message (fastest implementation, stops at first match) | |
84 | my $failure = any{ index($_, 'ERROR') != -1 } @messages; | |
85 | ||
86 | # Collect Pakfire status | |
87 | my %status = ( | |
88 | 'running' => &_is_pakfire_busy() || "0", | |
89 | 'running_since' => &General::age("$Pakfire::lockfile") || "0s", | |
90 | 'reboot' => ("$pakfire_status{'RebootRequired'}" eq "yes") || "0", | |
91 | 'failure' => $failure || "0" | |
92 | ); | |
93 | ||
94 | # Start JSON file | |
95 | print "{\n"; | |
96 | ||
97 | foreach my $key (keys %status) { | |
98 | my $value = $status{$key}; | |
99 | print qq{\t"$key": "$value",\n}; | |
100 | } | |
101 | ||
102 | # Print sanitized messages in reverse order to undo previous "tac" | |
103 | print qq{\t"messages": [\n}; | |
104 | for my $index (reverse (0 .. $#messages)) { | |
105 | my $line = $messages[$index]; | |
106 | $line =~ s/[[:cntrl:]<>&\\]+//g; | |
107 | ||
108 | print qq{\t\t"$line"}; | |
109 | print ",\n" unless $index < 1; | |
110 | } | |
111 | print "\n\t]\n"; | |
112 | ||
113 | # Finalize JSON file & stop | |
114 | print "}"; | |
115 | exit; | |
116 | } | |
117 | ||
118 | ### Process Pakfire install/update commands ### | |
119 | if(($cgiparams{'ACTION'} ne '') && ($pagemode eq $PM_DEFAULT)) { | |
120 | if(&_is_pakfire_busy()) { | |
121 | $errormessage = $Lang::tr{'pakfire already busy'}; | |
122 | $pagemode = $PM_LOGREAD; # Running Pakfire instance found, switch to log viewer mode | |
123 | } elsif(($cgiparams{'ACTION'} eq 'install') && ($cgiparams{'FORCE'} eq 'on')) { | |
124 | my @pkgs = split(/\|/, $cgiparams{'INSPAKS'}); | |
125 | &General::system_background("/usr/local/bin/pakfire", "install", "--non-interactive", "--no-colors", @pkgs); | |
126 | &_http_pagemode_redirect($PM_LOGREAD, 1); | |
127 | } elsif(($cgiparams{'ACTION'} eq 'remove') && ($cgiparams{'FORCE'} eq 'on')) { | |
128 | my @pkgs = split(/\|/, $cgiparams{'DELPAKS'}); | |
129 | &General::system_background("/usr/local/bin/pakfire", "remove", "--non-interactive", "--no-colors", @pkgs); | |
130 | &_http_pagemode_redirect($PM_LOGREAD, 1); | |
131 | } elsif($cgiparams{'ACTION'} eq 'update') { | |
132 | &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors"); | |
133 | &_http_pagemode_redirect($PM_LOGREAD, 1); | |
134 | } elsif($cgiparams{'ACTION'} eq 'upgrade') { | |
135 | &General::system_background("/usr/local/bin/pakfire", "upgrade", "-y", "--no-colors"); | |
136 | &_http_pagemode_redirect($PM_LOGREAD, 1); | |
137 | } elsif($cgiparams{'ACTION'} eq $Lang::tr{'save'}) { | |
138 | $pakfiresettings{"TREE"} = $cgiparams{"TREE"}; | |
139 | ||
140 | # Check for valid input | |
141 | if ($pakfiresettings{"TREE"} !~ m/^(stable|testing|unstable)$/) { | |
142 | $errormessage .= $Lang::tr{'pakfire invalid tree'}; | |
143 | } | |
144 | ||
145 | unless ($errormessage) { | |
146 | &General::writehash("${General::swroot}/pakfire/settings", \%pakfiresettings); | |
147 | ||
148 | # Update lists | |
149 | &General::system_background("/usr/local/bin/pakfire", "update", "--force", "--no-colors"); | |
150 | &_http_pagemode_redirect($PM_LOGREAD, 1); | |
151 | } | |
152 | } | |
153 | } | |
154 | ||
155 | ### Start pakfire page ### | |
156 | &Header::showhttpheaders(); | |
157 | ||
158 | ###--- HTML HEAD ---### | |
159 | my $extraHead = <<END | |
160 | <style> | |
161 | /* Main screen */ | |
162 | table#pfmain { | |
163 | width: 100%; | |
164 | border-style: hidden; | |
165 | table-layout: fixed; | |
166 | } | |
167 | ||
168 | #pfmain td { | |
169 | padding: 5px 20px 0; | |
170 | text-align: center; | |
171 | } | |
172 | #pfmain tr:not(:last-child) > td { | |
173 | padding-bottom: 1.5em; | |
174 | } | |
175 | #pfmain tr > td.heading { | |
176 | padding: 0; | |
177 | font-weight: bold; | |
178 | background-color: $color{'color20'}; | |
179 | } | |
180 | ||
181 | .pflist { | |
182 | width: 100%; | |
183 | text-align: left; | |
184 | margin-bottom: 0.8em; | |
185 | } | |
186 | ||
187 | /* Pakfire log viewer */ | |
188 | section#pflog-header { | |
189 | width: 100%; | |
190 | display: flex; | |
191 | text-align: left; | |
192 | align-items: center; | |
193 | column-gap: 20px; | |
194 | } | |
195 | #pflog-header > div:last-child { | |
196 | margin-left: auto; | |
197 | margin-right: 20px; | |
198 | } | |
199 | #pflog-header span { | |
200 | line-height: 1.3em; | |
201 | } | |
202 | #pflog-header span:empty::before { | |
203 | content: "\\200b"; /* zero width space */ | |
204 | } | |
205 | ||
206 | pre#pflog-messages { | |
207 | margin-top: 0.7em; | |
208 | padding-top: 0.7em; | |
209 | border-top: 0.5px solid $Header::bordercolour; | |
210 | ||
211 | text-align: left; | |
212 | min-height: 15em; | |
213 | overflow-x: auto; | |
214 | } | |
215 | </style> | |
216 | ||
217 | <script src="/include/pakfire.js"></script> | |
218 | <script> | |
219 | // Translations | |
220 | pakfire.i18n.load({ | |
221 | 'working': '$Lang::tr{'pakfire working'}', | |
222 | 'finished': '$Lang::tr{'pakfire finished'}', | |
223 | 'finished error': '$Lang::tr{'pakfire finished error'}', | |
224 | 'since': '$Lang::tr{'since'}', | |
225 | ||
226 | 'link_return': '<a href="$ENV{'SCRIPT_NAME'}">$Lang::tr{'pakfire return'}</a>', | |
227 | 'link_reboot': '<a href="/cgi-bin/shutdown.cgi">$Lang::tr{'needreboot'}</a>' | |
228 | }); | |
229 | ||
230 | // AJAX auto refresh interval (in ms, default: 1000) | |
231 | //pakfire.refreshInterval = 1000; | |
232 | ||
233 | // Enable returning to main screen (delay in ms) | |
234 | pakfire.setupPageReload(true, 3000); | |
235 | </script> | |
236 | END | |
237 | ; | |
238 | ###--- END HTML HEAD ---### | |
239 | ||
240 | &Header::openpage($Lang::tr{'pakfire configuration'}, 1, $extraHead); | |
241 | &Header::openbigbox('100%', 'left', '', $errormessage); | |
242 | ||
243 | # Show error message | |
244 | if ($errormessage) { | |
245 | &Header::openbox('100%', 'left', $Lang::tr{'error messages'}); | |
246 | print "<font class='base'>$errormessage </font>\n"; | |
247 | &Header::closebox(); | |
248 | } | |
249 | ||
250 | # Show only log output while Pakfire is running and stop afterwards | |
251 | if(($pagemode eq $PM_LOGREAD) || (&_is_pakfire_busy())) { | |
252 | &Header::openbox("100%", "center", "Pakfire"); | |
253 | ||
254 | print <<END | |
255 | <section id="pflog-header"> | |
256 | <div><img src="/images/indicator.gif" alt="$Lang::tr{'active'}" title="$Lang::tr{'pagerefresh'}"></div> | |
257 | <div> | |
258 | <span id="pflog-status">$Lang::tr{'pakfire working'}</span><br> | |
259 | <span id="pflog-time"></span><br> | |
260 | <span id="pflog-action"></span> | |
261 | </div> | |
262 | <div><a href="$ENV{'SCRIPT_NAME'}"><img src="/images/view-refresh.png" alt="$Lang::tr{'refresh'}" title="$Lang::tr{'refresh'}"></a></div> | |
263 | </section> | |
264 | ||
265 | <!-- Pakfire log messages --> | |
266 | <pre id="pflog-messages"></pre> | |
267 | <script> | |
268 | // Start automatic log refresh | |
269 | pakfire.running = true; | |
270 | </script> | |
271 | ||
272 | END | |
273 | ; | |
274 | ||
275 | &Header::closebox(); | |
276 | &Header::closebigbox(); | |
277 | &Header::closepage(); | |
278 | exit; | |
279 | } | |
280 | ||
281 | # Show Pakfire install/remove dependencies and confirm form | |
282 | # (_is_pakfire_busy status was checked before and can be omitted) | |
283 | if (($cgiparams{'ACTION'} eq 'install') && ($pagemode eq $PM_DEFAULT)) { | |
284 | &Header::openbox("100%", "center", $Lang::tr{'request'}); | |
285 | ||
286 | my @pkgs = split(/\|/, $cgiparams{'INSPAKS'}); | |
287 | my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs); | |
288 | print <<END; | |
289 | <table style="width: 100%"><tr><td colspan='2'><p>$Lang::tr{'pakfire install package'} <strong>@{pkgs}</strong><br> | |
290 | $Lang::tr{'pakfire possible dependency'}</p> | |
291 | <pre> | |
292 | END | |
293 | foreach (@output) { | |
294 | $_ =~ s/\\e\[[0-1]\;[0-9]+m//g; | |
295 | print "$_\n"; | |
296 | } | |
297 | print <<END; | |
298 | </pre></td></tr> | |
299 | <tr><td colspan='2'>$Lang::tr{'pakfire accept all'}</td></tr> | |
300 | <tr><td colspan='2'> </td></tr> | |
301 | <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
302 | <input type='hidden' name='INSPAKS' value='$cgiparams{'INSPAKS'}' /> | |
303 | <input type='hidden' name='FORCE' value='on' /> | |
304 | <input type='hidden' name='ACTION' value='install' /> | |
305 | <input type='image' alt='$Lang::tr{'install'}' title='$Lang::tr{'install'}' src='/images/go-next.png' /> | |
306 | </form> | |
307 | </td> | |
308 | <td align='left'> | |
309 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
310 | <input type='hidden' name='ACTION' value='' /> | |
311 | <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' /> | |
312 | </form> | |
313 | </td> | |
314 | </tr> | |
315 | </table> | |
316 | END | |
317 | &Header::closebox(); | |
318 | &Header::closebigbox(); | |
319 | &Header::closepage(); | |
320 | exit; | |
321 | ||
322 | } elsif (($cgiparams{'ACTION'} eq 'remove') && ($pagemode eq $PM_DEFAULT)) { | |
323 | &Header::openbox("100%", "center", $Lang::tr{'request'}); | |
324 | ||
325 | my @pkgs = split(/\|/, $cgiparams{'DELPAKS'}); | |
326 | my @output = &General::system_output("/usr/local/bin/pakfire", "resolvedeps", "--no-colors", @pkgs); | |
327 | print <<END; | |
328 | <table style="width: 100%"><tr><td colspan='2'><p>$Lang::tr{'pakfire uninstall package'} <strong>@{pkgs}</strong><br> | |
329 | $Lang::tr{'pakfire possible dependency'}</p> | |
330 | <pre> | |
331 | END | |
332 | foreach (@output) { | |
333 | $_ =~ s/\\e\[[0-1]\;[0-9]+m//g; | |
334 | print "$_\n"; | |
335 | } | |
336 | print <<END; | |
337 | </pre></td></tr> | |
338 | <tr><td colspan='2'>$Lang::tr{'pakfire uninstall all'}</td></tr> | |
339 | <tr><td colspan='2'> </td></tr> | |
340 | <tr><td align='right'><form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
341 | <input type='hidden' name='DELPAKS' value='$cgiparams{'DELPAKS'}' /> | |
342 | <input type='hidden' name='FORCE' value='on' /> | |
343 | <input type='hidden' name='ACTION' value='remove' /> | |
344 | <input type='image' alt='$Lang::tr{'uninstall'}' title='$Lang::tr{'uninstall'}' src='/images/go-next.png' /> | |
345 | </form> | |
346 | </td> | |
347 | <td align='left'> | |
348 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
349 | <input type='hidden' name='ACTION' value='' /> | |
350 | <input type='image' alt='$Lang::tr{'abort'}' title='$Lang::tr{'abort'}' src='/images/dialog-error.png' /> | |
351 | </form> | |
352 | </td> | |
353 | </tr> | |
354 | </table> | |
355 | END | |
356 | &Header::closebox(); | |
357 | &Header::closebigbox(); | |
358 | &Header::closepage(); | |
359 | exit; | |
360 | } | |
361 | ||
362 | # Show Pakfire main page | |
363 | my %selected=(); | |
364 | my %checked=(); | |
365 | ||
366 | $selected{"TREE"} = (); | |
367 | $selected{"TREE"}{"stable"} = ""; | |
368 | $selected{"TREE"}{"testing"} = ""; | |
369 | $selected{"TREE"}{"unstable"} = ""; | |
370 | $selected{"TREE"}{$pakfiresettings{"TREE"}} = "selected"; | |
371 | ||
372 | &Header::openbox("100%", "center", "Pakfire"); | |
373 | ||
374 | print <<END; | |
375 | <table id="pfmain"> | |
376 | END | |
377 | if ("$pakfire_status{'RebootRequired'}" eq "yes") { | |
378 | print "\t\t<tr><td colspan='2'><a href='/cgi-bin/shutdown.cgi'>$Lang::tr{'needreboot'}!</a></td></tr>\n"; | |
379 | } | |
380 | ||
381 | print <<END; | |
382 | <tr><td class="heading">$Lang::tr{'pakfire system state'}:</td> | |
383 | <td class="heading">$Lang::tr{'available updates'}:</td></tr> | |
384 | ||
385 | <tr><td><strong>$Lang::tr{'pakfire core update level'}: $pakfire_status{'Release'}</strong> | |
386 | <hr> | |
387 | <div class="pflist"> | |
388 | $Lang::tr{'pakfire last update'} $pakfire_status{'LastUpdate'} $Lang::tr{'pakfire ago'}<br> | |
389 | $Lang::tr{'pakfire last serverlist update'} $pakfire_status{'LastServerListUpdate'} $Lang::tr{'pakfire ago'}<br> | |
390 | $Lang::tr{'pakfire last core list update'} $pakfire_status{'LastCoreListUpdate'} $Lang::tr{'pakfire ago'}<br> | |
391 | $Lang::tr{'pakfire last package update'} $pakfire_status{'LastPakListUpdate'} $Lang::tr{'pakfire ago'} | |
392 | </div> | |
393 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
394 | <input type='hidden' name='ACTION' value='update' /> | |
395 | <input type='submit' value='$Lang::tr{'calamaris refresh list'}' /> | |
396 | </form> | |
397 | </td> | |
398 | <td> | |
399 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
400 | <select name="UPDPAKS" class="pflist" size="5" disabled> | |
401 | END | |
402 | ||
403 | if ("$pakfire_status{'CoreUpdateAvailable'}" eq "yes") { | |
404 | print "<option value=\"core\">$Lang::tr{'core update'} -- $pakfire_status{'CoreVersion'} -- $Lang::tr{'release'}: $pakfire_status{'Release'} -> $pakfire_status{'AvailableRelease'}</option>\n"; | |
405 | } | |
406 | ||
407 | if ($pakfire_status{'PakUpdatesAvailable'} > 0) { | |
408 | my %upgradelist = &Pakfire::dblist("upgrade"); | |
409 | foreach my $pak (sort keys %upgradelist) { | |
410 | 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"; | |
411 | } | |
412 | } | |
413 | ||
414 | print <<END; | |
415 | </select> | |
416 | <input type='hidden' name='ACTION' value='upgrade' /> | |
417 | <input type='image' alt='$Lang::tr{'upgrade'}' title='$Lang::tr{'upgrade'}' src='/images/document-save.png' /> | |
418 | </form> | |
419 | </td> | |
420 | </tr> | |
421 | <tr><td class="heading">$Lang::tr{'pakfire available addons'}</td> | |
422 | <td class="heading">$Lang::tr{'pakfire installed addons'}</td></tr> | |
423 | ||
424 | <tr><td style="padding:5px 10px 20px 20px" align="center"><p>$Lang::tr{'pakfire install description'}</p> | |
425 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
426 | <select name="INSPAKS" class="pflist" size="10" multiple> | |
427 | END | |
428 | ||
429 | my %notinstalledlist = &Pakfire::dblist("notinstalled"); | |
430 | foreach my $pak (sort keys %notinstalledlist) { | |
431 | print "<option value=\"$pak\">$pak-$notinstalledlist{$pak}{'ProgVersion'}-$notinstalledlist{$pak}{'Release'}</option>\n"; | |
432 | } | |
433 | ||
434 | print <<END; | |
435 | </select> | |
436 | <input type='hidden' name='ACTION' value='install' /> | |
437 | <input type='image' alt='$Lang::tr{'install'}' title='$Lang::tr{'install'}' src='/images/list-add.png' /> | |
438 | </form> | |
439 | </td> | |
440 | <td style="padding:5px 10px 20px 20px" align="center"><p>$Lang::tr{'pakfire uninstall description'}</p> | |
441 | <form method='post' action='$ENV{'SCRIPT_NAME'}'> | |
442 | <select name="DELPAKS" class="pflist" size="10" multiple> | |
443 | END | |
444 | ||
445 | my %installedlist = &Pakfire::dblist("installed"); | |
446 | foreach my $pak (sort keys %installedlist) { | |
447 | print "<option value=\"$pak\">$pak-$installedlist{$pak}{'ProgVersion'}-$installedlist{$pak}{'Release'}</option>\n"; | |
448 | } | |
449 | ||
450 | print <<END; | |
451 | </select> | |
452 | <input type='hidden' name='ACTION' value='remove' /> | |
453 | <input type='image' alt='$Lang::tr{'remove'}' title='$Lang::tr{'remove'}' src='/images/list-remove.png' /> | |
454 | </form> | |
455 | </td> | |
456 | </tr> | |
457 | </table> | |
458 | END | |
459 | ||
460 | &Header::closebox(); | |
461 | &Header::openbox("100%", "center", "$Lang::tr{'settings'}"); | |
462 | ||
463 | print <<END; | |
464 | <form method='POST' action='$ENV{'SCRIPT_NAME'}'> | |
465 | <table width='95%'> | |
466 | <tr> | |
467 | <td align='left' width='45%'>$Lang::tr{'pakfire tree'}</td> | |
468 | <td width="55%" align="left"> | |
469 | <select name="TREE"> | |
470 | <option value="stable" $selected{"TREE"}{"stable"}>$Lang::tr{'pakfire tree stable'}</option> | |
471 | <option value="testing" $selected{"TREE"}{"testing"}>$Lang::tr{'pakfire tree testing'}</option> | |
472 | <option value="unstable" $selected{"TREE"}{"unstable"}>$Lang::tr{'pakfire tree unstable'}</option> | |
473 | </select> | |
474 | </td> | |
475 | </tr> | |
476 | <tr> | |
477 | <td colspan="2"> </td> | |
478 | </tr> | |
479 | <tr> | |
480 | <td colspan="2" align="center"> | |
481 | <input type="submit" name="ACTION" value="$Lang::tr{'save'}" /> | |
482 | </td> | |
483 | </tr> | |
484 | </table> | |
485 | </form> | |
486 | END | |
487 | ||
488 | &Header::closebox(); | |
489 | &Header::closebigbox(); | |
490 | &Header::closepage(); | |
491 | ||
492 | ###--- Internal functions ---### | |
493 | ||
494 | # Check if pakfire is already running (extend test here if necessary) | |
495 | sub _is_pakfire_busy { | |
496 | # Return immediately if lockfile is present | |
497 | if(-e "$Pakfire::lockfile") { | |
498 | return 1; | |
499 | } | |
500 | ||
501 | # Check if a PID of a running pakfire instance is found | |
502 | # (The system backpipe command is safe, because no user input is computed.) | |
503 | my $pakfire_pid = `pidof -s /usr/local/bin/pakfire`; | |
504 | chomp($pakfire_pid); | |
505 | ||
506 | if($pakfire_pid) { | |
507 | return 1; | |
508 | } | |
509 | ||
510 | # Pakfire isn't running | |
511 | return 0; | |
512 | } | |
513 | ||
514 | # Send HTTP headers | |
515 | sub _start_json_output { | |
516 | print "Cache-Control: no-cache, no-store\n"; | |
517 | print "Content-Type: application/json\n"; | |
518 | print "\n"; # End of HTTP headers | |
519 | } | |
520 | ||
521 | # Send HTTP 303 redirect headers to change page mode | |
522 | # GET is always used to display the redirected page, which will remove already processed POST form data. | |
523 | # Note: Custom headers must be sent before the HTML output is started by &Header::showhttpheaders(). | |
524 | # If switch_mode is set to true, the global page mode variable ("$pagemode") is also updated immediately. | |
525 | sub _http_pagemode_redirect { | |
526 | my ($mode, $switch_mode) = @_; | |
527 | $mode //= $PM_DEFAULT; | |
528 | $switch_mode //= 0; | |
529 | ||
530 | # Send HTTP redirect with GET parameter | |
531 | my $location = "https://$ENV{'SERVER_NAME'}:$ENV{'SERVER_PORT'}$ENV{'SCRIPT_NAME'}?mode=${mode}"; | |
532 | print "Status: 303 See Other\n"; | |
533 | print "Location: $location\n"; | |
534 | ||
535 | # Change global page mode | |
536 | if($switch_mode) { | |
537 | $pagemode = $mode; | |
538 | } | |
539 | } |