$values) {
// UnBreak special cases
$section = str_replace("_", " ", $section);
$content .= "[".$section."]\n";
//append the values
foreach($values as $key=>$value) {
if ($value == '') {
$content .= $key."= \n";
}
else {
$content .= $key."=".$value."\n";
}
}
}
// write it into file
if (!$handle = fopen($filepath, 'w')) {
return false;
}
$success = fwrite($handle, $content);
fclose($handle);
// /etc/ircddbgateway is a FLAT key=value file on disk — the
// synthetic [ircddbgateway] header was injected at line ~75
// only to satisfy parse_ini_file()'s section model. The /tmp
// staging file keeps the header (so the form re-render via
// parse_ini_file at the bottom of this script still finds
// sections); the on-disk version must not. Strip via PHP's
// preg_replace and install the cleaned content directly —
// drops the prior `sudo sed -i` from this code path (L-7).
$etcContent = preg_replace('/^\[ircddbgateway\]\r?\n/m', '', $content);
// A3-3: per-request random staging file rather than a
// predictable hardcoded /tmp/
.tmp path. tempnam() also
// creates the file mode 600 — and since this is a freshly
// created file (not yet referenced anywhere), there's no
// race for an attacker to swap in a symlink before our write.
$etcStaging = tempnam('/tmp', 'pistar-edit-etc-');
file_put_contents($etcStaging, $etcContent);
// Atomic install: content + mode + owner set in one syscall
// sequence (B5 / L-5 pattern). Replaces the prior cp +
// chmod + chown trio so an interrupted RW window can't leave
// /etc/ircddbgateway in a transient state.
exec('sudo mount -o remount,rw /');
exec('sudo install -m 644 -o root -g root '
. escapeshellarg($etcStaging) . ' /etc/ircddbgateway');
exec('sudo mount -o remount,ro /');
@unlink($etcStaging);
// Reload the affected daemon
exec('sudo systemctl restart ircddbgateway.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 '";
?>