Files
Varaverk/Plugin/unraid/api/reorderarray.php
T
Gmer4Lfe ce0b3fb74b PHP app layer: consolidate common functions, fix critical bugs, standardize patterns
Consolidations (config.php gains 5 shared utilities):
- vv_format_uptime() replaces 4 inline uptime-formatting blocks
- vv_parse_conf_scalar() replaces vv_arr_scalar/vv_wd_scalar/vv_fb_scalar/vv_media_conf_scalar
- vv_known_hosts() replaces vv_arr_known_hosts/vv_fb_known_hosts + inline parser in watchdog
- vv_parse_kv_db() replaces inline key=value parsing in snapshot and monitor
- vv_local_ip() replaces duplicate in docker_folders.php and inline in docker.php
All module-level function names kept as thin aliases so call sites unchanged.

Critical bug fixes:
- api/system.php: added require_once config.php and POST-only guard (no auth on shutdown)
- api/movescript.php + reorderarray.php: use vv_write_conf_raw (atomic) + vv_push_master_conf
- api/snapshot.php: share /tmp/vv_cpu_stat.json with vv_cpu_per_core() instead of own state file

Correctness:
- vv_cpu_per_core() and vv_network_stats(): atomic tmp+rename for state files (concurrent poll safety)
- ext_ip curl cache moved from /tmp/vv_ext_ip.cache to vv_cache_read/write (canonical cache dir)
- monitor_remote.php + board.php + snapshot.php: all use vv_cache_read/write instead of ad-hoc /tmp files

HTTP method guards added to write-only APIs that were missing them:
- api/scheduler.php, conf_toggle.php, flag_toggle.php
2026-06-04 16:44:16 -04:00

111 lines
3.5 KiB
PHP

<?php
// Rewrite a *_SCRIPTS array in master.conf with a new script order.
// POST: array_name (e.g. "DAILY_SCRIPTS"), scripts (JSON: [{"id":"rel/path.sh","enabled":true}, ...])
// Preserves original entry lines (including inline flags/args) where possible.
// Scripts absent from the new list are dropped; new scripts are added as fresh entries.
header('Content-Type: application/json');
require_once dirname(__DIR__) . '/include/config.php';
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
echo json_encode(['ok' => false, 'error' => 'POST only']);
exit;
}
$arrayName = trim($_POST['array_name'] ?? '');
$raw = $_POST['scripts'] ?? '';
$decoded = json_decode($raw, true);
if (!$arrayName || !preg_match('/^[A-Z_]+_SCRIPTS$/', $arrayName)) {
echo json_encode(['ok' => false, 'error' => 'Invalid array_name']);
exit;
}
if (!is_array($decoded)) {
echo json_encode(['ok' => false, 'error' => 'Invalid scripts JSON']);
exit;
}
// Validate each entry
$order = [];
foreach ($decoded as $item) {
$id = trim((string)($item['id'] ?? ''));
$enabled = (bool)($item['enabled'] ?? true);
if (!$id || str_contains($id, '..') || !preg_match('/^[A-Za-z0-9_.\-\/]+\.sh$/', $id)) continue;
$order[] = ['id' => $id, 'enabled' => $enabled];
}
$confPath = CONF_DIR . '/master.conf';
if (!file_exists($confPath)) {
echo json_encode(['ok' => false, 'error' => 'master.conf not found']);
exit;
}
$lines = file($confPath, FILE_KEEP_BLANK_LINES);
if (!$lines) {
echo json_encode(['ok' => false, 'error' => 'Could not read master.conf']);
exit;
}
// Find the array block and extract original entry lines keyed by script path.
$arrayEsc = preg_quote($arrayName, '/');
$blockStart = null;
$blockEnd = null;
$depth = 0;
$origEntries = []; // path → original trimmed content line (e.g. '"Daily/script.sh --flag"')
foreach ($lines as $i => $line) {
if ($blockStart === null) {
if (preg_match('/^\s*' . $arrayEsc . '\s*=\s*\(/', $line)) {
$blockStart = $i;
$depth = 1;
}
continue;
}
$depth += substr_count($line, '(');
$depth -= substr_count($line, ')');
if ($depth <= 0) {
$blockEnd = $i;
break;
}
// Collect entries (enabled and commented)
if (preg_match('/^\s*(?:#\s*)?"([^"]+)"/', $line, $m)) {
$parts = preg_split('/\s+/', trim($m[1]));
$path = $parts[0] ?? '';
if (substr($path, -3) === '.sh' && !isset($origEntries[$path])) {
// Store the full quoted expression (may include flags after the path)
$origEntries[$path] = '"' . $m[1] . '"';
}
}
}
if ($blockStart === null || $blockEnd === null) {
echo json_encode(['ok' => false, 'error' => "Array $arrayName not found in master.conf"]);
exit;
}
// Build replacement block lines
$newBlockLines = [];
// Preserve the opening line exactly (e.g. "DAILY_SCRIPTS=(")
$newBlockLines[] = $lines[$blockStart];
foreach ($order as $item) {
$id = $item['id'];
$enabled = $item['enabled'];
$entry = $origEntries[$id] ?? '"' . $id . '"';
$prefix = $enabled ? ' ' : ' # ';
$newBlockLines[] = $prefix . $entry . "\n";
}
// Preserve the closing line exactly
$newBlockLines[] = $lines[$blockEnd];
// Replace the original block in $lines
array_splice($lines, $blockStart, $blockEnd - $blockStart + 1, $newBlockLines);
if (!vv_write_conf_raw('master.conf', implode('', $lines))) {
echo json_encode(['ok' => false, 'error' => 'Write failed']);
exit;
}
vv_push_master_conf();
echo json_encode(['ok' => true]);