content= // // RESPONSE // {"ok":true,"error":null} // {"ok":false,"error":"POST only"|"File not permitted"|"Syntax error: …"|"Failed to write file"} // // DEPENDS ON // include/config.php vv_get_conf_files(), CONF_DIR // include/confform.php vv_conf_syntax_error(), vv_conf_edit() // ═══════════════════════════════════════════════════════════════════════════════════════════════ header('Content-Type: application/json'); require_once dirname(__DIR__) . '/include/config.php'; require_once dirname(__DIR__) . '/include/confform.php'; if ($_SERVER['REQUEST_METHOD'] !== 'POST') { echo json_encode(['ok' => false, 'error' => 'POST only']); exit; } $file = trim($_POST['file'] ?? ''); $content = $_POST['content'] ?? ''; // Must be an allowed file for this host $allowed = vv_get_conf_files(); if (!$file || !in_array($file, $allowed)) { echo json_encode(['ok' => false, 'error' => 'File not permitted']); exit; } // Every script sources these. A syntax error here takes the whole system down, so the // candidate is parsed before it is allowed to replace a working file. Checked here as well as // inside vv_conf_edit() so the editor can show bash's own complaint; the write path only knows // whether to proceed, not what to tell the person typing. $syntax = vv_conf_syntax_error($content, $file); if ($syntax !== null) { echo json_encode(['ok' => false, 'error' => 'Syntax error: ' . $syntax]); exit; } $ok = vv_conf_edit($file, fn() => $content, [], ['whole-file']); echo json_encode(['ok' => $ok, 'error' => $ok ? null : 'Failed to write file']);