<?php
/**
 * SVG_Analyzer - Phát hiện mã độc trong file SVG
 */
if (!defined('ABSPATH')) exit;

class Foxblock_SVG_Analyzer
{
    private string $rel_path;
    private string $source;
    private array  $findings = array();

    public function __construct(string $rel_path, string $source)
    {
        $this->rel_path = $rel_path;
        $this->source   = $source;
    }

    public function analyze(): array
    {
        $this->findings = array();
        $this->detect_dangerous_events();
        return $this->deduplicate($this->findings);
    }

    private function detect_dangerous_events(): void
    {
        $lines = explode("\n", $this->source);
        
        foreach ($lines as $line_no => $line) {
            // onload=
            if (preg_match('/onload\s*=\s*[\'"]([^\'"]+)[\'"]/i', $line, $match)) {
                $this->add_finding(
                    $line_no + 1,
                    9,
                    'SVG onload event - có thể thực thi JavaScript: ' . substr($match[1], 0, 50),
                    'high',
                    trim($line),
                    'heuristic'
                );
            }

            // onerror=
            if (preg_match('/onerror\s*=\s*[\'"]([^\'"]+)[\'"]/i', $line, $match)) {
                $this->add_finding(
                    $line_no + 1,
                    9,
                    'SVG onerror event - có thể thực thi JavaScript: ' . substr($match[1], 0, 50),
                    'high',
                    trim($line),
                    'heuristic'
                );
            }

            // onclick, onmouseover, etc.
            if (preg_match('/on(?:click|mouseover|mouseout|focus|blur)\s*=\s*[\'"]([^\'"]+)[\'"]/i', $line, $match)) {
                $this->add_finding(
                    $line_no + 1,
                    7,
                    'SVG event handler - có thể thực thi JavaScript: ' . substr($match[1], 0, 50),
                    'high',
                    trim($line),
                    'heuristic'
                );
            }

            // javascript: protocol
            if (preg_match('/(?:href|xlink:href)\s*=\s*[\'"]javascript:([^\'"]+)[\'"]/i', $line, $match)) {
                $this->add_finding(
                    $line_no + 1,
                    10,
                    'SVG javascript: protocol - thực thi code: ' . substr($match[1], 0, 50),
                    'high',
                    trim($line),
                    'heuristic'
                );
            }

            // <script> tag trong SVG
            if (preg_match('/<script[^>]*>/i', $line)) {
                $this->add_finding(
                    $line_no + 1,
                    10,
                    'SVG chứa <script> tag - rất nguy hiểm',
                    'high',
                    trim($line),
                    'heuristic'
                );
            }

            // data: URI với script
            if (preg_match('/data:text\/html[^>]*base64/i', $line)) {
                $this->add_finding(
                    $line_no + 1,
                    8,
                    'SVG chứa data URI với HTML/base64 - có thể chứa mã độc',
                    'high',
                    trim($line),
                    'heuristic'
                );
            }
        }
    }

    private function add_finding(int $line, int $score, string $label, string $risk, string $code, string $method): void
    {
        $this->findings[] = array(
            'line'   => $line,
            'score'  => $score,
            'label'  => $label,
            'risk'   => $risk,
            'code'   => substr($code, 0, 200),
            'method' => $method,
        );
    }

    private function deduplicate(array $findings): array
    {
        $seen = array();
        $result = array();
        foreach ($findings as $f) {
            $key = $f['line'] . '|' . $f['label'];
            if (!isset($seen[$key])) {
                $seen[$key] = true;
                $result[] = $f;
            }
        }
        usort($result, fn($a, $b) => $b['score'] - $a['score']);
        return $result;
    }
}
