This commit is contained in:
2026-07-19 18:01:05 +08:00
commit fe4b286ce1
132 changed files with 25378 additions and 0 deletions
+210
View File
@@ -0,0 +1,210 @@
<?php
/**
* Pi-Star software update runner.
*
* On confirmed POST, kicks off `sudo /usr/local/sbin/pistar-update`
* in the background and tails /var/log/pi-star/pi-star_update.log
* via AJAX (jquery-timing $.repeat) — same pattern used by
* admin/expert/upgrade.php for pistar-upgrade and
* admin/expert/jitter_test.php for pistar-jittertest.
*
* Forces the locale to a stock C / en_GB.UTF-8 mix for the duration
* of the update so any commands the script runs see consistent
* formatting (some tools change their output based on locale).
*/
require_once($_SERVER['DOCUMENT_ROOT'].'/config/security_headers.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/config/csrf.php');
require_once($_SERVER['DOCUMENT_ROOT'].'/config/banner_warnings.inc');
setSecurityHeaders();
// CSRF protection — see config/csrf.php for the full rationale.
// Critical here: line 42 below kicks off `sudo pistar-update` the
// moment a `confirm_update` POST lands. csrf_verify() MUST run
// before that, so a hostile cross-site POST can never start a
// long-running privileged update on the device. The helper emits
// 403 + exit() on mismatch, well before the system() call.
csrf_verify();
// Layer 2 of the default-password protection — see config/banner_warnings.inc.
// MUST run BEFORE any output so header('Location: ...') works.
pistar_warnings_enforce_redirect();
// Load the language support
require_once('config/language.php');
// Load the Pi-Star Release file
$pistarReleaseConfig = '/etc/pistar-release';
$configPistarRelease = array();
$configPistarRelease = parse_ini_file($pistarReleaseConfig, true);
// Load the Version Info
require_once('config/version.php');
// Force the Locale to the stock locale just while we run the update
setlocale(LC_ALL, "LC_CTYPE=en_GB.UTF-8;LC_NUMERIC=C;LC_TIME=C;LC_COLLATE=C;LC_MONETARY=C;LC_MESSAGES=C;LC_PAPER=C;LC_NAME=C;LC_ADDRESS=C;LC_TELEPHONE=C;LC_MEASUREMENT=C;LC_IDENTIFICATION=C");
// Sanity Check that this file has been opened correctly
if ($_SERVER["PHP_SELF"] == "/admin/update.php") {
// Only proceed with update if user has confirmed via POST submission
if (!isset($_GET['ajax']) && !empty($_POST) && isset($_POST['confirm_update'])) {
if (!file_exists('/var/log/pi-star')) {
system('sudo mkdir -p /var/log/pi-star/');
system('sudo chmod 775 /var/log/pi-star/');
system('sudo chown root:mmdvm /var/log/pi-star/');
}
// Truncate creates the file if missing and clears it if existing —
// does the work the prior `sudo touch` + `sudo echo "" > log` pair
// tried to do. The earlier echo was buggy (the `>` redirect was
// run as www-data, not under sudo, so it could only ever truncate
// a www-data-writable file — a silent no-op when the log was last
// touched as root). Run synchronously, BEFORE the backgrounded
// pistar-update spawn, so the script's first writes always land
// in a freshly cleared file regardless of `&` scheduling.
system('sudo truncate -s 0 /var/log/pi-star/pi-star_update.log');
system('sudo /usr/local/sbin/pistar-update > /dev/null 2>&1 &');
}
// Sanity Check Passed.
header('Cache-Control: no-cache');
// session_start() is no longer called here — csrf_verify() at
// the top of the file already started the session via
// csrf_session_start(). A second session_start() would emit a
// "session is already active" NOTICE on PHP 8.x. The existing
// $_SESSION['update_offset'] log-tail logic below works
// unchanged against the already-active session.
// Initialize session offset only if update has been confirmed
if (!isset($_GET['ajax']) && !empty($_POST) && isset($_POST['confirm_update'])) {
//unset($_SESSION['update_offset']);
if (file_exists('/var/log/pi-star/pi-star_update.log')) {
$_SESSION['update_offset'] = filesize('/var/log/pi-star/pi-star_update.log');
} else {
$_SESSION['update_offset'] = 0;
}
}
if (isset($_GET['ajax'])) {
//session_start();
if (!file_exists('/var/log/pi-star/pi-star_update.log')) {
exit();
}
$handle = fopen('/var/log/pi-star/pi-star_update.log', 'rb');
if (isset($_SESSION['update_offset'])) {
fseek($handle, 0, SEEK_END);
if ($_SESSION['update_offset'] > ftell($handle)) //log rotated/truncated
$_SESSION['update_offset'] = 0; //continue at beginning of the new log
$data = stream_get_contents($handle, -1, $_SESSION['update_offset']);
$_SESSION['update_offset'] += strlen($data);
echo nl2br($data);
}
else {
fseek($handle, 0, SEEK_END);
$_SESSION['update_offset'] = ftell($handle);
}
exit();
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" lang="en">
<head>
<meta name="robots" content="index" />
<meta name="robots" content="follow" />
<meta name="language" content="English" />
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
<meta name="Author" content="Andrew Taylor (MW0MWZ)" />
<meta name="Description" content="Pi-Star Update" />
<meta name="KeyWords" content="Pi-Star" />
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
<meta http-equiv="pragma" content="no-cache" />
<link rel="shortcut icon" href="images/favicon.ico" type="image/x-icon" />
<meta http-equiv="Expires" content="0" />
<title>Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?></title>
<link rel="stylesheet" type="text/css" href="css/pistar-css.php" />
<?php if (!empty($_POST) && isset($_POST['confirm_update'])) { ?>
<script type="text/javascript" src="/jquery.min.js"></script>
<script type="text/javascript" src="/jquery-timing.min.js"></script>
<script type="text/javascript">
$(function() {
$.repeat(1000, function() {
$.get('/admin/update.php?ajax', function(data) {
if (data.length < 1) return;
var objDiv = document.getElementById("tail");
var isScrolledToBottom = objDiv.scrollHeight - objDiv.clientHeight <= objDiv.scrollTop + 1;
$('#tail').append(data);
if (isScrolledToBottom)
objDiv.scrollTop = objDiv.scrollHeight;
});
});
});
</script>
<?php } ?>
</head>
<body>
<?php pistar_warnings_render(); ?>
<div class="container">
<header aria-label="header">
<div class="header">
<div style="font-size: 8px; text-align: right; padding-right: 8px;">
Pi-Star:<?php echo $configPistarRelease['Pi-Star']['Version']?> / Dashboard:<?php echo $version; ?>
</div>
<h1>Pi-Star - <?php echo $lang['digital_voice']." ".$lang['dashboard']." - ".$lang['update'];?></h1>
<nav aria-label="Menu">
<p style="padding-right: 5px; text-align: right; color: #ffffff;">
<a href="/" style="color: #ffffff;"><?php echo $lang['dashboard'];?></a> |
<a href="/admin/" style="color: #ffffff;"><?php echo $lang['admin'];?></a> |
<a href="/admin/power.php" style="color: #ffffff;"><?php echo $lang['power'];?></a> |
<a href="/admin/config_backup.php" style="color: #ffffff;"><?php echo $lang['backup_restore'];?></a> |
<a href="/admin/configure.php" style="color: #ffffff;"><?php echo $lang['configuration'];?></a>
</p>
</nav>
</div>
</header>
<main>
<div class="contentwide">
<?php if (!empty($_POST) && isset($_POST['confirm_update'])) { ?>
<table role="presentation" width="100%">
<tr><th>Update Running</th></tr>
<tr><td align="left"><div id="tail">Starting update, please wait...<br /></div></td></tr>
</table>
<?php } else { ?>
<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" method="post">
<?php csrf_field(); ?>
<table width="100%">
<tr>
<th><?php echo $lang['update'];?></th>
</tr>
<tr>
<td align="center" style="padding: 20px;">
<p style="margin-bottom: 20px;">
<strong>This will update your Pi-Star installation to the latest version.</strong><br />
<br />
The update process may take several minutes to complete.<br />
Please do not interrupt the process or power off your system during the update.
</p>
<button style="border: none; background: none; cursor: pointer;" type="submit" name="confirm_update" value="1">
<img src="/images/download.png" border="0" alt="Start Update" /><br />
<strong>Start Update</strong>
</button>
</td>
</tr>
</table>
</form>
<?php } ?>
</div>
</main>
<footer aria-label="Footer">
<div class="footer">
Pi-Star web config, &copy; Andy Taylor (MW0MWZ) 2014-<?php echo date("Y"); ?>.<br />
Need help? Click <a style="color: #ffffff;" href="https://www.facebook.com/groups/pistarusergroup/" target="_new">here for the Support Group</a><br />
Get your copy of Pi-Star from <a style="color: #ffffff;" href="http://www.pistar.uk/downloads/" target="_blank">here</a>.<br />
<br />
</div>
</footer>
</div>
</body>
</html>
<?php
}