false, 'error' => 'POST only']); exit; } $flagName = trim($_POST['flag_name'] ?? ''); $orchId = trim($_POST['orch_id'] ?? ''); $location = trim($_POST['location'] ?? ''); $cron = trim($_POST['cron'] ?? ''); if (!$flagName || !preg_match('/^[A-Z_]+_RSYNC_ENABLED$/', $flagName)) { echo json_encode(['ok' => false, 'error' => 'Invalid flag_name']); exit; } if ($orchId && (str_contains($orchId, '..') || !preg_match('/^[A-Za-z0-9_.\-\/]+\.sh$/', $orchId))) { echo json_encode(['ok' => false, 'error' => 'Invalid orch_id']); exit; } if ($location && (!str_starts_with($location, '/') || str_contains($location, '..') || preg_match('/[\x00\n\r]/', $location))) { echo json_encode(['ok' => false, 'error' => 'Invalid location']); exit; } $key = '__rsync_' . $flagName; $schedule = vv_schedule_load(); $schedule[$key] = [ 'flag_name' => $flagName, 'orch_id' => $orchId, 'location' => $location, 'cron' => $cron, ]; if (!vv_schedule_save($schedule)) { echo json_encode(['ok' => false, 'error' => 'Write failed']); exit; } vv_cron_rebuild($schedule); echo json_encode(['ok' => true]);