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 (file_put_contents($confPath, implode('', $lines)) === false) { echo json_encode(['ok' => false, 'error' => 'Write failed']); exit; } echo json_encode(['ok' => true]);