<?php
/**
 * VMPFence File Type Handler
 * 
 * Advanced file type detection and type-specific scanning rules
 * 
 * @package VMPFence
 * @subpackage Security
 * @since 1.0.0
 */

// Prevent direct access
if (!defined('ABSPATH')) {
    exit;
}

/**
 * Class VMPFence_File_Type_Handler
 * 
 */
class VMPFence_File_Type_Handler {
    
    /**
     * Supported file types for scanning
     */
    const TYPE_PHP = 'php';
    const TYPE_JAVASCRIPT = 'javascript';
    const TYPE_HTML = 'html';
    const TYPE_CSS = 'css';
    const TYPE_SVG = 'svg';
    const TYPE_XML = 'xml';
    const TYPE_JSON = 'json';
    const TYPE_IMAGE = 'image';
    const TYPE_BINARY = 'binary';
    const TYPE_ARCHIVE = 'archive';
    const TYPE_DOCUMENT = 'document';
    const TYPE_FONT = 'font';
    const TYPE_VIDEO = 'video';
    const TYPE_AUDIO = 'audio';
    const TYPE_UNKNOWN = 'unknown';
    
    /**
     * File extension to type mapping
     * 
     * @var array
     */
    private $extension_mapping = [
        // PHP files
        'php' => self::TYPE_PHP,
        'php3' => self::TYPE_PHP,
        'php4' => self::TYPE_PHP,
        'php5' => self::TYPE_PHP,
        'php7' => self::TYPE_PHP,
        'php8' => self::TYPE_PHP,
        'phtml' => self::TYPE_PHP,
        'phps' => self::TYPE_PHP,
        'pht' => self::TYPE_PHP,
        'phpt' => self::TYPE_PHP,
        
        // Web files
        'js' => self::TYPE_JAVASCRIPT,
        'mjs' => self::TYPE_JAVASCRIPT,
        'html' => self::TYPE_HTML,
        'htm' => self::TYPE_HTML,
        'xhtml' => self::TYPE_HTML,
        'css' => self::TYPE_CSS,
        'svg' => self::TYPE_SVG,
        'xml' => self::TYPE_XML,
        'json' => self::TYPE_JSON,
        
        // Image files
        'jpg' => self::TYPE_IMAGE,
        'jpeg' => self::TYPE_IMAGE,
        'png' => self::TYPE_IMAGE,
        'gif' => self::TYPE_IMAGE,
        'bmp' => self::TYPE_IMAGE,
        'webp' => self::TYPE_IMAGE,
        'ico' => self::TYPE_IMAGE,
        'tiff' => self::TYPE_IMAGE,
        'tif' => self::TYPE_IMAGE,
        
        // Archive files
        'zip' => self::TYPE_ARCHIVE,
        'tar' => self::TYPE_ARCHIVE,
        'gz' => self::TYPE_ARCHIVE,
        'rar' => self::TYPE_ARCHIVE,
        '7z' => self::TYPE_ARCHIVE,
        
        // Document files
        'pdf' => self::TYPE_DOCUMENT,
        'doc' => self::TYPE_DOCUMENT,
        'docx' => self::TYPE_DOCUMENT,
        'xls' => self::TYPE_DOCUMENT,
        'xlsx' => self::TYPE_DOCUMENT,
        'ppt' => self::TYPE_DOCUMENT,
        'pptx' => self::TYPE_DOCUMENT,
        
        // Font files
        'woff' => self::TYPE_FONT,
        'woff2' => self::TYPE_FONT,
        'ttf' => self::TYPE_FONT,
        'otf' => self::TYPE_FONT,
        'eot' => self::TYPE_FONT,
        
        // Video files
        'mp4' => self::TYPE_VIDEO,
        'avi' => self::TYPE_VIDEO,
        'mov' => self::TYPE_VIDEO,
        'wmv' => self::TYPE_VIDEO,
        'flv' => self::TYPE_VIDEO,
        'webm' => self::TYPE_VIDEO,
        'mkv' => self::TYPE_VIDEO,
        
        // Audio files
        'mp3' => self::TYPE_AUDIO,
        'wav' => self::TYPE_AUDIO,
        'ogg' => self::TYPE_AUDIO,
        'flac' => self::TYPE_AUDIO,
        'aac' => self::TYPE_AUDIO,
        
        // Translation files
        'mo' => self::TYPE_BINARY, // WordPress translation files
        'po' => self::TYPE_DOCUMENT,
    ];
    
    /**
     * MIME type to file type mapping
     * 
     * @var array
     */
    private $mime_type_mapping = [
        // PHP
        'application/x-httpd-php' => self::TYPE_PHP,
        'text/x-php' => self::TYPE_PHP,
        
        // Web files
        'application/javascript' => self::TYPE_JAVASCRIPT,
        'text/javascript' => self::TYPE_JAVASCRIPT,
        'text/html' => self::TYPE_HTML,
        'application/xhtml+xml' => self::TYPE_HTML,
        'text/css' => self::TYPE_CSS,
        'image/svg+xml' => self::TYPE_SVG,
        'application/xml' => self::TYPE_XML,
        'text/xml' => self::TYPE_XML,
        'application/json' => self::TYPE_JSON,
        
        // Images
        'image/jpeg' => self::TYPE_IMAGE,
        'image/png' => self::TYPE_IMAGE,
        'image/gif' => self::TYPE_IMAGE,
        'image/bmp' => self::TYPE_IMAGE,
        'image/webp' => self::TYPE_IMAGE,
        'image/x-icon' => self::TYPE_IMAGE,
        'image/tiff' => self::TYPE_IMAGE,
        
        // Archives
        'application/zip' => self::TYPE_ARCHIVE,
        'application/x-tar' => self::TYPE_ARCHIVE,
        'application/gzip' => self::TYPE_ARCHIVE,
        'application/x-rar' => self::TYPE_ARCHIVE,
        'application/x-7z-compressed' => self::TYPE_ARCHIVE,
        
        // Documents
        'application/pdf' => self::TYPE_DOCUMENT,
        'application/msword' => self::TYPE_DOCUMENT,
        'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => self::TYPE_DOCUMENT,
        
        // Fonts
        'font/woff' => self::TYPE_FONT,
        'font/woff2' => self::TYPE_FONT,
        'font/ttf' => self::TYPE_FONT,
        'font/otf' => self::TYPE_FONT,
        'application/vnd.ms-fontobject' => self::TYPE_FONT,
        'application/font-woff' => self::TYPE_FONT,
        'application/font-woff2' => self::TYPE_FONT,
        
        // Video
        'video/mp4' => self::TYPE_VIDEO,
        'video/avi' => self::TYPE_VIDEO,
        'video/quicktime' => self::TYPE_VIDEO,
        'video/x-ms-wmv' => self::TYPE_VIDEO,
        'video/webm' => self::TYPE_VIDEO,
        
        // Audio
        'audio/mpeg' => self::TYPE_AUDIO,
        'audio/wav' => self::TYPE_AUDIO,
        'audio/ogg' => self::TYPE_AUDIO,
        'audio/flac' => self::TYPE_AUDIO,
    ];
    
    /**
     * Binary file signatures (magic numbers)
     * 
     * @var array
     */
    private $binary_signatures = [
        // Images
        'ffd8ff' => self::TYPE_IMAGE, // JPEG
        '89504e47' => self::TYPE_IMAGE, // PNG
        '47494638' => self::TYPE_IMAGE, // GIF
        '424d' => self::TYPE_IMAGE, // BMP
        '52494646' => self::TYPE_IMAGE, // WEBP
        
        // Archives
        '504b0304' => self::TYPE_ARCHIVE, // ZIP
        '504b0506' => self::TYPE_ARCHIVE, // ZIP (empty)
        '504b0708' => self::TYPE_ARCHIVE, // ZIP (spanned)
        '1f8b08' => self::TYPE_ARCHIVE, // GZIP
        '425a68' => self::TYPE_ARCHIVE, // BZIP2
        '377abcaf271c' => self::TYPE_ARCHIVE, // 7Z
        '526172211a07' => self::TYPE_ARCHIVE, // RAR
        
        // Documents
        '25504446' => self::TYPE_DOCUMENT, // PDF
        'd0cf11e0a1b11ae1' => self::TYPE_DOCUMENT, // MS Office
        '504b030414000600' => self::TYPE_DOCUMENT, // Modern Office (DOCX, XLSX, etc.)
        
        // Executables (should be treated as binary)
        '4d5a' => self::TYPE_BINARY, // Windows PE
        '7f454c46' => self::TYPE_BINARY, // Linux ELF
        'cafebabe' => self::TYPE_BINARY, // Java CLASS
    ];
    
    /**
     * Type-specific scanning rules
     * 
     * @var array
     */
    private $type_scanning_rules = [
        self::TYPE_PHP => [
            'scan_content' => true,
            'check_php_tags' => true,
            'apply_php_patterns' => true,
            'check_obfuscation' => true,
            'scan_includes' => true,
        ],
        self::TYPE_JAVASCRIPT => [
            'scan_content' => true,
            'check_eval' => true,
            'check_document_write' => true,
            'check_obfuscation' => true,
            'check_base64' => true,
        ],
        self::TYPE_HTML => [
            'scan_content' => true,
            'check_script_tags' => true,
            'check_iframe_tags' => true,
            'check_form_actions' => true,
            'scan_embedded_js' => true,
        ],
        self::TYPE_SVG => [
            'scan_content' => true,
            'treat_as_javascript' => true, // SVG can contain JavaScript
            'check_script_tags' => true,
            'check_event_handlers' => true,
            'check_external_refs' => true,
            'check_embedded_files' => true,
        ],
        self::TYPE_CSS => [
            'scan_content' => true,
            'check_imports' => true,
            'check_expressions' => true,
            'check_data_urls' => true,
        ],
        self::TYPE_XML => [
            'scan_content' => true,
            'check_external_entities' => true,
            'check_cdata_sections' => true,
            'validate_structure' => true,
        ],
        self::TYPE_JSON => [
            'scan_content' => true,
            'validate_syntax' => true,
            'check_eval_data' => true,
        ],
        self::TYPE_IMAGE => [
            'scan_content' => false,
            'check_metadata' => true,
            'check_embedded_files' => true,
            'scan_for_php' => true, // Check for PHP code in images
        ],
        self::TYPE_ARCHIVE => [
            'scan_content' => false,
            'extract_and_scan' => true,
            'check_file_list' => true,
            'limit_extraction' => true,
        ],
        self::TYPE_DOCUMENT => [
            'scan_content' => false,
            'check_macros' => true,
            'check_embedded_objects' => true,
            'scan_metadata' => true,
        ],
        self::TYPE_BINARY => [
            'scan_content' => false,
            'check_signatures' => true,
            'scan_strings' => true,
        ],
        self::TYPE_FONT => [
            'scan_content' => false,
            'check_metadata' => false,
            'skip_scanning' => true, // Fonts are safe binary files
        ],
        self::TYPE_VIDEO => [
            'scan_content' => false,
            'check_metadata' => false,
            'skip_scanning' => true, // Videos are safe binary files
        ],
        self::TYPE_AUDIO => [
            'scan_content' => false,
            'check_metadata' => false,
            'skip_scanning' => true, // Audio files are safe binary files
        ],
    ];
    
    /**
     * Content patterns for type detection
     * 
     * @var array
     */
    private $content_patterns = [
        self::TYPE_PHP => [
            '/<\?(?:php|=|\s)/',
            '/namespace\s+\w+;/',
            '/class\s+\w+\s*{/',
            '/function\s+\w+\s*\(/',
        ],
        self::TYPE_JAVASCRIPT => [
            '/function\s*\w*\s*\(/i',
            '/var\s+\w+\s*=/i',
            '/let\s+\w+\s*=/i',
            '/const\s+\w+\s*=/i',
            '/console\.log\s*\(/i',
            '/document\./i',
            '/window\./i',
        ],
        self::TYPE_HTML => [
            '/<!doctype\s+html/i',
            '/<html[^>]*>/i',
            '/<head[^>]*>/i',
            '/<body[^>]*>/i',
            '/<div[^>]*>/i',
            '/<script[^>]*>/i',
        ],
        self::TYPE_CSS => [
            '/\w+\s*{[^}]*}/s',
            '/@import\s+/i',
            '/@media\s+/i',
            '/:\s*[^;]+;/s',
        ],
        self::TYPE_SVG => [
            '/<svg[^>]*>/i',
            '/<path[^>]*>/i',
            '/<circle[^>]*>/i',
            '/<rect[^>]*>/i',
            '/xmlns[^>]*svg/i',
        ],
        self::TYPE_XML => [
            '/<\?xml[^>]*>/i',
            '/xmlns[^>]*=/i',
            '/<[a-zA-Z_:][\w:.-]*[^>]*>/s',
        ],
    ];
    
    /**
     * Initialize the file type handler
     */
    public function __construct() {
        // Initialize any required resources
        $this->init_file_functions();
    }
    
    /**
     * Initialize file-related functions
     */
    private function init_file_functions() {
        // Ensure required PHP extensions are available
        if (!extension_loaded('fileinfo')) {
            if (defined('WP_DEBUG') && WP_DEBUG) {
                // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- Intentional for debugging
                // error_log('VMPFence File Type Handler: fileinfo extension not available, falling back to basic detection');
            }
        }
    }
    
    /**
     * Detect file type using advanced methods
     * 
     * @param string $file_path Path to the file
     * @param string $content Optional file content
     * @return string Detected file type
     */
    public function detect_file_type_advanced($file_path, $content = null) {
        if (!file_exists($file_path)) {
            return self::TYPE_UNKNOWN;
        }
        
        $detected_type = self::TYPE_UNKNOWN;
        
        // Method 1: Check file signature (magic numbers) - most reliable
        $signature_type = $this->detect_by_signature($file_path);
        if ($signature_type !== self::TYPE_UNKNOWN) {
            $detected_type = $signature_type;
        }
        
        // Method 2: Check MIME type using fileinfo
        if ($detected_type === self::TYPE_UNKNOWN) {
            $mime_type = $this->detect_by_mime_type($file_path);
            if ($mime_type !== self::TYPE_UNKNOWN) {
                $detected_type = $mime_type;
            }
        }
        
        // Method 3: Check file extension
        if ($detected_type === self::TYPE_UNKNOWN) {
            $extension_type = $this->detect_by_extension($file_path);
            if ($extension_type !== self::TYPE_UNKNOWN) {
                $detected_type = $extension_type;
            }
        }
        
        // Method 4: Content analysis (if content provided or file is small enough)
        if ($detected_type === self::TYPE_UNKNOWN || $this->needs_content_verification($detected_type)) {
            if ($content === null && filesize($file_path) < 1048576) { // 1MB limit for content analysis
                $content = file_get_contents($file_path);
            }
            
            if ($content !== null) {
                $content_type = $this->detect_by_content($content, $detected_type);
                if ($content_type !== self::TYPE_UNKNOWN) {
                    $detected_type = $content_type;
                }
            }
        }
        
        // Special handling for SVG files (treat as both image and potentially JavaScript)
        if ($detected_type === self::TYPE_SVG) {
            // SVG files can contain JavaScript, so we need special handling
            $detected_type = $this->analyze_svg_content($file_path, $content);
        }
        
        return $detected_type;
    }
    
    /**
     * Determine if a file should be scanned as PHP
     * 
     * @param string $file_path Path to the file
     * @param string $detected_type Already detected type
     * @param string $content Optional file content
     * @return bool True if should be scanned as PHP
     */
    public function should_scan_as_php($file_path, $detected_type = null, $content = null) {
        // If type not provided, detect it
        if ($detected_type === null) {
            $detected_type = $this->detect_file_type_advanced($file_path, $content);
        }
        
        // Obviously PHP files should be scanned as PHP
        if ($detected_type === self::TYPE_PHP) {
            return true;
        }
        
        // Check for PHP code in other file types
        if ($content === null && file_exists($file_path)) {
            // Only read small files for content analysis
            if (filesize($file_path) < 1048576) { // 1MB limit
                $content = file_get_contents($file_path);
            }
        }
        
        if ($content !== null) {
            // Check for PHP opening tags
            if (preg_match('/<\?(?:php|=|\s)/', $content)) {
                return true;
            }
            
            // Check for PHP functions/constructs in non-PHP files
            $php_indicators = [
                '/\$_(?:GET|POST|REQUEST|SESSION|COOKIE)\s*\[/i',
                '/(?:include|require)(?:_once)?\s*\(/i',
                '/(?:echo|print)\s+/i',
                '/function\s+\w+\s*\([^)]*\)\s*\{/',
                '/class\s+\w+\s*\{/',
            ];
            
            foreach ($php_indicators as $pattern) {
                if (preg_match($pattern, $content)) {
                    return true;
                }
            }
        }
        
        return false;
    }
    
    /**
     * Apply type-specific scanning rules
     * 
     * @param string $file_path Path to the file
     * @param string $detected_type Detected file type
     * @param string $content File content
     * @return array Applied rules and their results
     */
    public function apply_type_specific_rules($file_path, $detected_type, $content = '') {
        $rules = isset($this->type_scanning_rules[$detected_type]) 
                 ? $this->type_scanning_rules[$detected_type] 
                 : [];
        
        $results = [
            'type' => $detected_type,
            'rules_applied' => [],
            'scan_recommendations' => [],
            'security_concerns' => [],
            'should_scan_content' => false,
            'special_handling' => []
        ];
        
        foreach ($rules as $rule => $enabled) {
            if (!$enabled) continue;
            
            $results['rules_applied'][] = $rule;
            
            switch ($rule) {
                case 'scan_content':
                    $results['should_scan_content'] = true;
                    $results['scan_recommendations'][] = 'Full content scan recommended';
                    break;
                    
                case 'treat_as_javascript':
                    $results['special_handling'][] = 'Treat as JavaScript for security scanning';
                    $results['security_concerns'][] = 'May contain executable JavaScript code';
                    break;
                    
                case 'check_php_tags':
                    if (!empty($content) && preg_match('/<\?(?:php|=|\s)/', $content)) {
                        $results['security_concerns'][] = 'Contains PHP opening tags';
                    }
                    break;
                    
                case 'check_script_tags':
                    if (!empty($content) && preg_match('/<script[^>]*>/i', $content)) {
                        $results['security_concerns'][] = 'Contains script tags';
                    }
                    break;
                    
                case 'check_eval':
                    if (!empty($content) && stripos($content, 'eval(') !== false) {
                        $results['security_concerns'][] = 'Contains eval() function';
                    }
                    break;
                    
                case 'check_base64':
                    if (!empty($content) && preg_match('/base64_decode\s*\(/i', $content)) {
                        $results['security_concerns'][] = 'Contains base64 decoding';
                    }
                    break;
                    
                case 'check_external_refs':
                    if (!empty($content) && preg_match('/(?:src|href)\s*=\s*["\']https?:/i', $content)) {
                        $results['security_concerns'][] = 'Contains external references';
                    }
                    break;
                    
                case 'scan_for_php':
                    if ($this->should_scan_as_php($file_path, $detected_type, $content)) {
                        $results['security_concerns'][] = 'May contain embedded PHP code';
                        $results['special_handling'][] = 'Scan as PHP despite file type';
                    }
                    break;
                    
                case 'check_metadata':
                    $metadata_concerns = $this->check_file_metadata($file_path);
                    if (!empty($metadata_concerns)) {
                        $results['security_concerns'] = array_merge($results['security_concerns'], $metadata_concerns);
                    }
                    break;
                    
                case 'check_embedded_files':
                    // Check for binary data in text-based files (like SVG with JPEG headers)
                    if (!empty($content) && $detected_type === self::TYPE_SVG) {
                        // Look for binary file signatures in SVG content
                        if (preg_match('/[\xFF\xFE\xFD]/', $content) || 
                            strpos($content, "\xFF\xD8\xFF") !== false) { // JPEG signature
                            $results['security_concerns'][] = 'Contains suspicious binary data mixed with SVG';
                            $results['should_scan_content'] = true;
                        }
                    }
                    break;
                    break;
            }
        }
        
        return $results;
    }
    
    /**
     * Detect file type by binary signature
     * 
     * @param string $file_path Path to the file
     * @return string Detected type or TYPE_UNKNOWN
     */
    private function detect_by_signature($file_path) {
        if (!file_exists($file_path) || filesize($file_path) < 4) {
            return self::TYPE_UNKNOWN;
        }
        
        // phpcs:disable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.WP.AlternativeFunctions.file_system_operations_fclose -- Binary file signature detection requires direct file operations
        $handle = fopen($file_path, 'rb');
        if (!$handle) {
            return self::TYPE_UNKNOWN;
        }
        
        $header = fread($handle, 16); // Read first 16 bytes
        fclose($handle);
        // phpcs:enable WordPress.WP.AlternativeFunctions.file_system_operations_fopen, WordPress.WP.AlternativeFunctions.file_system_operations_fread, WordPress.WP.AlternativeFunctions.file_system_operations_fclose
        
        $hex_header = bin2hex($header);
        
        // Check against known signatures
        foreach ($this->binary_signatures as $signature => $type) {
            $signature_length = strlen($signature);
            if (substr($hex_header, 0, $signature_length) === $signature) {
                return $type;
            }
        }
        
        return self::TYPE_UNKNOWN;
    }
    
    /**
     * Detect file type by MIME type
     * 
     * @param string $file_path Path to the file
     * @return string Detected type or TYPE_UNKNOWN
     */
    private function detect_by_mime_type($file_path) {
        if (!extension_loaded('fileinfo')) {
            return self::TYPE_UNKNOWN;
        }
        
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        if (!$finfo) {
            return self::TYPE_UNKNOWN;
        }
        
        $mime_type = finfo_file($finfo, $file_path);
        finfo_close($finfo);
        
        if (!$mime_type) {
            return self::TYPE_UNKNOWN;
        }
        
        return isset($this->mime_type_mapping[$mime_type]) 
               ? $this->mime_type_mapping[$mime_type] 
               : self::TYPE_UNKNOWN;
    }
    
    /**
     * Detect file type by extension
     * 
     * @param string $file_path Path to the file
     * @return string Detected type or TYPE_UNKNOWN
     */
    private function detect_by_extension($file_path) {
        $extension = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
        
        return isset($this->extension_mapping[$extension]) 
               ? $this->extension_mapping[$extension] 
               : self::TYPE_UNKNOWN;
    }
    
    /**
     * Detect file type by content analysis
     * 
     * @param string $content File content
     * @param string $current_type Currently detected type
     * @return string Detected type or TYPE_UNKNOWN
     */
    private function detect_by_content($content, $current_type = self::TYPE_UNKNOWN) {
        if (empty($content)) {
            return self::TYPE_UNKNOWN;
        }
        
        // Check content patterns
        foreach ($this->content_patterns as $type => $patterns) {
            $matches = 0;
            foreach ($patterns as $pattern) {
                if (preg_match($pattern, $content)) {
                    $matches++;
                }
            }
            
            // If we have multiple pattern matches, this is likely the correct type
            if ($matches >= 2) {
                return $type;
            }
        }
        
        // Special content-based detection
        
        // Check for PHP content
        if (preg_match('/<\?(?:php|=|\s)/', $content)) {
            return self::TYPE_PHP;
        }
        
        // Check for HTML content
        if (preg_match('/<!doctype\s+html/i', $content) || 
            preg_match('/<html[^>]*>/i', $content)) {
            return self::TYPE_HTML;
        }
        
        // Check for SVG content
        if (preg_match('/<svg[^>]*>/i', $content)) {
            return self::TYPE_SVG;
        }
        
        // Check for XML content
        if (preg_match('/<\?xml[^>]*>/i', $content)) {
            return self::TYPE_XML;
        }
        
        // Check for JSON content
        if ($this->is_valid_json($content)) {
            return self::TYPE_JSON;
        }
        
        return self::TYPE_UNKNOWN;
    }
    
    /**
     * Check if content verification is needed
     * 
     * @param string $detected_type Detected type
     * @return bool True if content verification needed
     */
    private function needs_content_verification($detected_type) {
        $types_needing_verification = [
            self::TYPE_UNKNOWN,
            self::TYPE_BINARY, // Sometimes text files are detected as binary
        ];
        
        return in_array($detected_type, $types_needing_verification);
    }
    
    /**
     * Analyze SVG content for security concerns
     * 
     * @param string $file_path Path to SVG file
     * @param string $content SVG content
     * @return string Appropriate type classification
     */
    private function analyze_svg_content($file_path, $content = null) {
        if ($content === null && file_exists($file_path)) {
            $content = file_get_contents($file_path);
        }
        
        if (empty($content)) {
            return self::TYPE_SVG;
        }
        
        // Check if SVG contains JavaScript
        $js_patterns = [
            '/<script[^>]*>/i',
            '/on\w+\s*=\s*["\'][^"\']*["\']/',
            '/javascript:/i',
            '/eval\s*\(/i',
        ];
        
        foreach ($js_patterns as $pattern) {
            if (preg_match($pattern, $content)) {
                // SVG with JavaScript - treat with high caution
                return self::TYPE_SVG; // Keep as SVG but flag for JavaScript scanning
            }
        }
        
        return self::TYPE_SVG;
    }
    
    /**
     * Check file metadata for security concerns
     * 
     * @param string $file_path Path to the file
     * @return array Array of security concerns found
     */
    private function check_file_metadata($file_path) {
        $concerns = [];
        
        if (!file_exists($file_path)) {
            return $concerns;
        }
        
        // Check file permissions
        $perms = fileperms($file_path);
        if ($perms & 0111) { // Executable permissions
            $concerns[] = 'File has executable permissions';
        }
        
        // Check file size anomalies
        $size = filesize($file_path);
        $extension = strtolower(pathinfo($file_path, PATHINFO_EXTENSION));
        
        // Unusually large image files might contain hidden data
        if (in_array($extension, ['jpg', 'jpeg', 'png', 'gif']) && $size > 10485760) { // 10MB
            $concerns[] = 'Image file is unusually large';
        }
        
        // Very small files with executable extensions
        if (in_array($extension, ['php', 'js', 'html']) && $size < 10) {
            $concerns[] = 'Executable file type is unusually small';
        }
        
        return $concerns;
    }
    
    /**
     * Check if content is valid JSON
     * 
     * @param string $content Content to check
     * @return bool True if valid JSON
     */
    private function is_valid_json($content) {
        json_decode($content);
        return json_last_error() === JSON_ERROR_NONE;
    }
    
    /**
     * Detect embedded binary data in text files
     * 
     * @param string $content File content
     * @return bool True if binary data found
     */
    private function detect_embedded_binary_in_text($content) {
        // Check for common binary file signatures in text content
        $binary_signatures = [
            "\xFF\xD8\xFF",     // JPEG signature
            "\x89PNG\r\n",      // PNG signature  
            "GIF89a",           // GIF89a signature
            "GIF87a",           // GIF87a signature
            "\x00\x00\x01\x00", // ICO signature
            "PK\x03\x04",       // ZIP signature
            "%PDF-",            // PDF signature
            "\x50\x4B",         // Generic ZIP/Office
        ];
        
        foreach ($binary_signatures as $signature) {
            if (strpos($content, $signature) !== false) {
                return true;
            }
        }
        
        // Check for high concentration of non-printable characters
        $content_length = strlen($content);
        if ($content_length > 100) {
            $binary_chars = 0;
            for ($i = 0; $i < $content_length; $i++) {
                $char = ord($content[$i]);
                // Count non-printable chars (except common whitespace)
                if ($char < 32 && !in_array($char, [9, 10, 13])) {
                    $binary_chars++;
                }
            }
            
            // If more than 10% non-printable chars, likely binary
            if (($binary_chars / $content_length) > 0.1) {
                return true;
            }
        }
        
        return false;
    }
    
    /**
     * Get scanning recommendations for a file type
     * 
     * @param string $file_type File type
     * @return array Scanning recommendations
     */
    public function get_scanning_recommendations($file_type) {
        $rules = isset($this->type_scanning_rules[$file_type]) 
                 ? $this->type_scanning_rules[$file_type] 
                 : [];
        
        $recommendations = [
            'scan_content' => $rules['scan_content'] ?? false,
            'priority' => $this->get_type_priority($file_type),
            'security_risk' => $this->get_type_risk_level($file_type),
            'special_considerations' => $this->get_special_considerations($file_type),
        ];
        
        return $recommendations;
    }
    
    /**
     * Get priority level for file type scanning
     * 
     * @param string $file_type File type
     * @return string Priority level (high/medium/low)
     */
    private function get_type_priority($file_type) {
        $high_priority_types = [self::TYPE_PHP, self::TYPE_JAVASCRIPT, self::TYPE_HTML, self::TYPE_SVG];
        $medium_priority_types = [self::TYPE_CSS, self::TYPE_XML, self::TYPE_JSON];
        
        if (in_array($file_type, $high_priority_types)) {
            return 'high';
        } elseif (in_array($file_type, $medium_priority_types)) {
            return 'medium';
        } else {
            return 'low';
        }
    }
    
    /**
     * Get security risk level for file type
     * 
     * @param string $file_type File type
     * @return string Risk level (high/medium/low)
     */
    private function get_type_risk_level($file_type) {
        $high_risk_types = [self::TYPE_PHP, self::TYPE_JAVASCRIPT, self::TYPE_SVG, self::TYPE_BINARY];
        $medium_risk_types = [self::TYPE_HTML, self::TYPE_XML];
        
        if (in_array($file_type, $high_risk_types)) {
            return 'high';
        } elseif (in_array($file_type, $medium_risk_types)) {
            return 'medium';
        } else {
            return 'low';
        }
    }
    
    /**
     * Get special considerations for file type
     * 
     * @param string $file_type File type
     * @return array Special considerations
     */
    private function get_special_considerations($file_type) {
        $considerations = [];
        
        switch ($file_type) {
            case self::TYPE_SVG:
                $considerations[] = 'SVG files can contain executable JavaScript';
                $considerations[] = 'Should be scanned with JavaScript patterns';
                break;
                
            case self::TYPE_IMAGE:
                $considerations[] = 'Check for embedded PHP code';
                $considerations[] = 'Analyze EXIF data for malicious content';
                break;
                
            case self::TYPE_CSS:
                $considerations[] = 'CSS can contain data URLs with encoded content';
                $considerations[] = 'Check for expression() functions (IE specific)';
                break;
                
            case self::TYPE_XML:
                $considerations[] = 'Check for external entity references (XXE attacks)';
                $considerations[] = 'Validate XML structure';
                break;
                
            case self::TYPE_ARCHIVE:
                $considerations[] = 'Extract and scan contents (with limits)';
                $considerations[] = 'Check for zip bombs and path traversal';
                break;
                
            case self::TYPE_DOCUMENT:
                $considerations[] = 'Check for embedded macros';
                $considerations[] = 'Scan metadata for malicious content';
                break;
        }
        
        return $considerations;
    }
    
    /**
     * Get all supported file types
     * 
     * @return array Array of supported file types
     */
    public function get_supported_types() {
        return [
            self::TYPE_PHP,
            self::TYPE_JAVASCRIPT,
            self::TYPE_HTML,
            self::TYPE_CSS,
            self::TYPE_SVG,
            self::TYPE_XML,
            self::TYPE_JSON,
            self::TYPE_IMAGE,
            self::TYPE_BINARY,
            self::TYPE_ARCHIVE,
            self::TYPE_DOCUMENT,
        ];
    }
    
    /**
     * Get scanning rules for a file type
     * 
     * @param string $file_type File type
     * @return array Scanning rules
     */
    public function get_scanning_rules($file_type) {
        return isset($this->type_scanning_rules[$file_type]) 
               ? $this->type_scanning_rules[$file_type] 
               : [];
    }
    
    /**
     * Check if file type should be scanned
     * 
     * @param string $file_type File type
     * @return bool True if should be scanned
     */
    public function should_scan_file_type($file_type) {
        $scannable_types = [
            self::TYPE_PHP,
            self::TYPE_JAVASCRIPT,
            self::TYPE_HTML,
            self::TYPE_CSS,
            self::TYPE_SVG,
            self::TYPE_XML,
            self::TYPE_JSON,
        ];
        
        return in_array($file_type, $scannable_types);
    }
    
    /**
     * Get file type description
     * 
     * @param string $file_type File type
     * @return string Human-readable description
     */
    public function get_type_description($file_type) {
        $descriptions = [
            self::TYPE_PHP => 'PHP Script File',
            self::TYPE_JAVASCRIPT => 'JavaScript File',
            self::TYPE_HTML => 'HTML Document',
            self::TYPE_CSS => 'Cascading Style Sheet',
            self::TYPE_SVG => 'Scalable Vector Graphics',
            self::TYPE_XML => 'XML Document',
            self::TYPE_JSON => 'JSON Data File',
            self::TYPE_IMAGE => 'Image File',
            self::TYPE_BINARY => 'Binary File',
            self::TYPE_ARCHIVE => 'Archive File',
            self::TYPE_DOCUMENT => 'Document File',
            self::TYPE_FONT => 'Font File',
            self::TYPE_VIDEO => 'Video File',
            self::TYPE_AUDIO => 'Audio File',
            self::TYPE_UNKNOWN => 'Unknown File Type',
        ];
        
        return isset($descriptions[$file_type]) ? $descriptions[$file_type] : 'Unknown File Type';
    }
}
