'auth']); exit; } $action = $_GET['action'] ?? $_POST['action'] ?? ''; $file = $_GET['file'] ?? $_POST['file'] ?? ''; if ($file && !preg_match('#^[a-zA-Z0-9_-]+\.html$#', $file)) { echo json_encode(['error'=>'invalid_filename']); exit; } $path = $file ? '/var/www/html/' . $file : ''; $result = ['ok'=>true,'action'=>$action,'file'=>$file,'ts'=>date('c')]; if ($action === 'status' && file_exists($path)) { $result['size'] = filesize($path); $result['md5'] = md5_file($path); $result['has_drill'] = substr_count(file_get_contents($path), '__opusUniversalDrill'); } elseif ($action === 'sed_swap' && file_exists($path)) { $old = $_POST['old'] ?? ''; $new = $_POST['new'] ?? ''; if (strlen($old) < 3) { echo json_encode(['error'=>'old_too_short']); exit; } $content = file_get_contents($path); if (strpos($content, $old) === false) { echo json_encode(['error'=>'old_not_found']); exit; } $gold = '/opt/wevads/vault/' . basename($path) . '.GOLD-' . date('Ymd-His') . '-wevia'; copy($path, $gold); shell_exec('sudo -n chattr -i ' . escapeshellarg($path) . ' 2>&1'); file_put_contents($path, str_replace($old, $new, $content)); shell_exec('sudo -n chattr +i ' . escapeshellarg($path) . ' 2>&1'); $result['gold'] = $gold; $result['new_md5'] = md5_file($path); $result['replaced'] = substr_count($content, $old); } elseif ($action === 'list_no_drill') { $pages = []; foreach (glob('/var/www/html/*.html') as $f) { $c = @file_get_contents($f, false, null, 0, 500); if (strpos($c, 'meta http-equiv') !== false) continue; if (strpos(@file_get_contents($f), '__opusUniversalDrill') === false) { $pages[] = basename($f); } } $result['pages'] = $pages; $result['count'] = count($pages); } echo json_encode($result, JSON_PRETTY_PRINT);