main
This commit is contained in:
@@ -1,29 +1,4 @@
|
||||
<?php
|
||||
/**
|
||||
* Expert editor for /etc/dstarrepeater (D-Star modem driver config).
|
||||
*
|
||||
* The on-disk file is a flat key=value (no [section] header), but the
|
||||
* editor parses it via parse_ini_file() — so we synthesise a temporary
|
||||
* `[dstarrepeater]` header on read and `sed -i` it back out before the
|
||||
* file is committed. Otherwise follows the standard Pi-Star
|
||||
* copy-via-/tmp / mount-rw / restart pattern; daemon:
|
||||
* dstarrepeater.service.
|
||||
*/
|
||||
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.
|
||||
// Must run BEFORE any output: bootstraps the session on GET (so
|
||||
// Set-Cookie ships) and rejects forged POSTs cleanly with 403
|
||||
// before any state change (sed-i, fopen+fwrite, sudo cp, etc.).
|
||||
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
|
||||
@@ -42,34 +17,28 @@ require_once('../config/version.php');
|
||||
<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 Expert Editor" />
|
||||
<meta name="KeyWords" content="Pi-Star" />
|
||||
<meta name="Description" content="CDN Expert Editor" />
|
||||
<meta name="KeyWords" content="CDN" />
|
||||
<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 - Digital Voice Dashboard - Expert Editor</title>
|
||||
<title>CDN - Digital Voice Dashboard - Expert Editor</title>
|
||||
<link rel="stylesheet" type="text/css" href="../css/pistar-css.php" />
|
||||
</head>
|
||||
<body>
|
||||
<?php pistar_warnings_render(); ?>
|
||||
<div class="container">
|
||||
<?php include './header-menu.inc'; ?>
|
||||
<div class="contentwide">
|
||||
|
||||
<?php
|
||||
// Do some file wrangling...
|
||||
// A3-3 — see edit_ircddbgateway.php for the full TOCTOU rationale.
|
||||
// tempnam() creates the staging file mode 600 owned by www-data
|
||||
// with an unguessable random suffix; cleanup is registered up
|
||||
// front so the file never persists past script exit.
|
||||
$filepath = tempnam('/tmp', 'pistar-edit-');
|
||||
register_shutdown_function(function() use ($filepath) { @unlink($filepath); });
|
||||
exec('sudo cp /etc/dstarrepeater ' . escapeshellarg($filepath));
|
||||
// Defensive re-assert; tempnam already 600 www-data and `sudo cp`
|
||||
// preserves it, but match the surrounding pattern as belt-and-braces.
|
||||
exec('sudo chown www-data:www-data ' . escapeshellarg($filepath));
|
||||
exec('sudo chmod 600 ' . escapeshellarg($filepath));
|
||||
exec('sudo cp /etc/dstarrepeater /tmp/ZHN0YXJyZXBlYXRlcg.tmp');
|
||||
exec('sudo chown www-data:www-data /tmp/ZHN0YXJyZXBlYXRlcg.tmp');
|
||||
exec('sudo chmod 664 /tmp/ZHN0YXJyZXBlYXRlcg.tmp');
|
||||
|
||||
// ini file to open
|
||||
$filepath = '/tmp/ZHN0YXJyZXBlYXRlcg.tmp';
|
||||
|
||||
// Mangle the input
|
||||
$file_content = "[dstarrepeater]\n".preg_replace('~\r\n?~', "\n", file_get_contents($filepath));
|
||||
@@ -77,105 +46,77 @@ file_put_contents($filepath, $file_content);
|
||||
|
||||
// after the form submit
|
||||
if($_POST) {
|
||||
$data = $_POST;
|
||||
//update ini file, call function
|
||||
update_ini_file($data, $filepath);
|
||||
$data = $_POST;
|
||||
//update ini file, call function
|
||||
update_ini_file($data, $filepath);
|
||||
}
|
||||
|
||||
// this is the function going to update your ini file
|
||||
function update_ini_file($data, $filepath)
|
||||
{
|
||||
$content = "";
|
||||
function update_ini_file($data, $filepath) {
|
||||
$content = "";
|
||||
|
||||
// parse the ini file to get the sections
|
||||
// parse the ini file using default parse_ini_file() PHP function
|
||||
$parsed_ini = parse_ini_file($filepath, true);
|
||||
// parse the ini file to get the sections
|
||||
// parse the ini file using default parse_ini_file() PHP function
|
||||
$parsed_ini = parse_ini_file($filepath, true);
|
||||
|
||||
foreach($data as $section=>$values) {
|
||||
// UnBreak special cases
|
||||
$section = str_replace("_", " ", $section);
|
||||
$content .= "[".$section."]\n";
|
||||
foreach($data as $section=>$values) {
|
||||
// UnBreak special cases
|
||||
$section = str_replace("_", " ", $section);
|
||||
$content .= "[".$section."]\n";
|
||||
//append the values
|
||||
foreach($values as $key=>$value) {
|
||||
if ($value == '') {
|
||||
$content .= $key."= \n";
|
||||
if ($value == '') {
|
||||
$content .= $key."= \n";
|
||||
}
|
||||
else {
|
||||
$content .= $key."=".$value."\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// write it into file
|
||||
if (!$handle = fopen($filepath, 'w')) {
|
||||
return false;
|
||||
}
|
||||
// write it into file
|
||||
if (!$handle = fopen($filepath, 'w')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$success = fwrite($handle, $content);
|
||||
fclose($handle);
|
||||
$success = fwrite($handle, $content);
|
||||
fclose($handle);
|
||||
|
||||
// /etc/dstarrepeater is a FLAT key=value file on disk — the
|
||||
// synthetic [dstarrepeater] header is injected only for
|
||||
// parse_ini_file()'s benefit. Strip it via PHP and install
|
||||
// the cleaned content directly (L-7: drops sudo sed -i;
|
||||
// L-5: collapses cp + chmod + chown into one atomic install).
|
||||
// See edit_ircddbgateway.php for the full rationale.
|
||||
$etcContent = preg_replace('/^\[dstarrepeater\]\r?\n/m', '', $content);
|
||||
// A3-3: per-request random staging — see edit_ircddbgateway.php
|
||||
$etcStaging = tempnam('/tmp', 'pistar-edit-etc-');
|
||||
file_put_contents($etcStaging, $etcContent);
|
||||
// Updates complete - copy the working file back to the proper location
|
||||
exec('sudo mount -o remount,rw /'); // Make rootfs writable
|
||||
exec('sudo cp /tmp/ZHN0YXJyZXBlYXRlcg.tmp /etc/dstarrepeater'); // Move the file back
|
||||
exec('sudo sed -i \'/\\[dstarrepeater\\]/d\' /etc/dstarrepeater'); // Clean up file mangling
|
||||
exec('sudo chmod 644 /etc/dstarrepeater'); // Set the correct runtime permissions
|
||||
exec('sudo chown root:root /etc/dstarrepeater'); // Set the owner
|
||||
exec('sudo mount -o remount,ro /'); // Make rootfs read-only
|
||||
|
||||
exec('sudo mount -o remount,rw /');
|
||||
exec('sudo install -m 644 -o root -g root '
|
||||
. escapeshellarg($etcStaging) . ' /etc/dstarrepeater');
|
||||
exec('sudo mount -o remount,ro /');
|
||||
@unlink($etcStaging);
|
||||
|
||||
// Reload the affected daemon
|
||||
exec('sudo systemctl restart dstarrepeater.service'); // Reload the daemon
|
||||
return $success;
|
||||
}
|
||||
// Reload the affected daemon
|
||||
exec('sudo systemctl restart dstarrepeater.service'); // Reload the daemon
|
||||
return $success;
|
||||
}
|
||||
|
||||
// parse the ini file using default parse_ini_file() PHP function
|
||||
$parsed_ini = parse_ini_file($filepath, true);
|
||||
|
||||
echo '<form action="" method="post">'."\n";
|
||||
echo csrf_field_html()."\n";
|
||||
foreach($parsed_ini as $section=>$values) {
|
||||
// keep the section as hidden text so we can update once the form submitted
|
||||
// INI section / key / value all come from the underlying
|
||||
// /etc/<gateway> file. Same hardening as edit_mmdvmhost.php
|
||||
// (#23): htmlspecialchars(ENT_QUOTES) on display so a value
|
||||
// with a literal `"` or `<` (e.g. an Options string) can't
|
||||
// break out of the `value="…"` attribute. The save handler
|
||||
// writes the POST bytes verbatim, so legitimate quoted
|
||||
// values round-trip byte-identically.
|
||||
$sectionHtml = htmlspecialchars((string)$section, ENT_QUOTES, 'UTF-8');
|
||||
echo "<input type=\"hidden\" value=\"$sectionHtml\" name=\"$sectionHtml\" />\n";
|
||||
echo "<table>\n";
|
||||
echo "<tr><th colspan=\"2\">$sectionHtml</th></tr>\n";
|
||||
// print all other values as input fields, so can edit.
|
||||
// note the name='' attribute it has both section and key
|
||||
foreach($values as $key=>$value) {
|
||||
$keyHtml = htmlspecialchars((string)$key, ENT_QUOTES, 'UTF-8');
|
||||
$valueHtml = htmlspecialchars((string)$value, ENT_QUOTES, 'UTF-8');
|
||||
echo "<tr><td align=\"right\" width=\"30%\">$keyHtml</td><td align=\"left\"><input type=\"text\" name=\"{$sectionHtml}[$keyHtml]\" value=\"$valueHtml\" /></td></tr>\n";
|
||||
}
|
||||
echo "</table>\n";
|
||||
echo '<input type="submit" value="'.$lang['apply'].'" />'."\n";
|
||||
echo "<br />\n";
|
||||
}
|
||||
foreach($parsed_ini as $section=>$values) {
|
||||
// keep the section as hidden text so we can update once the form submitted
|
||||
echo "<input type=\"hidden\" value=\"$section\" name=\"$section\" />\n";
|
||||
echo "<div class=\"settings-card\">\n";
|
||||
echo "<h3>$section</h3>\n";
|
||||
// print all other values as input fields, so can edit.
|
||||
// note the name='' attribute it has both section and key
|
||||
foreach($values as $key=>$value) {
|
||||
echo "<div class=\"field-row\"><div>$key</div><div><input type=\"text\" name=\"{$section}[$key]\" value=\"$value\" /></div></div>\n";
|
||||
}
|
||||
echo "</div>\n";
|
||||
echo '<div class="field-actions"><input type="submit" value="'.$lang['apply'].'" /></div>'."\n";
|
||||
}
|
||||
echo "</form>";
|
||||
?>
|
||||
</div>
|
||||
|
||||
<div class="footer">
|
||||
Pi-Star / Pi-Star Dashboard, © 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="_new">here</a>.<br />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user