<?php
/**
 * AR Display Security Enhancements
 * https://augmentedrealityplugins.com
**/

if (!defined('ABSPATH')) {
    exit; // Exit if accessed directly
}

/**
 * Enhanced security class for AR plugins
 */
class AR_Security_Enhancements {
    
    /**
     * Initialize security enhancements
     */
    public function __construct() {
        add_action('init', array($this, 'init_security'));
        add_filter('upload_mimes', array($this, 'restrict_upload_mimes'));
        add_action('wp_ajax_ar_upload_file', array($this, 'handle_secure_file_upload'));
        add_action('wp_ajax_nopriv_ar_upload_file', array($this, 'deny_unauthorized_upload'));
    }
    
    /**
     * Initialize security measures
     */
    public function init_security() {
        // Add security headers
        add_action('send_headers', array($this, 'add_security_headers'));
        
        // Validate file uploads
        add_filter('wp_handle_upload_prefilter', array($this, 'validate_file_upload'));
        
        // Sanitize REST API responses
        add_filter('rest_pre_serve_request', array($this, 'sanitize_rest_response'));
    }
    
    /**
     * Add security headers
     */
    public function add_security_headers() {
        if (!is_admin()) {
            header('X-Content-Type-Options: nosniff');
            header('X-Frame-Options: SAMEORIGIN');
            header('X-XSS-Protection: 1; mode=block');
            header('Referrer-Policy: strict-origin-when-cross-origin');
        }
    }
    
    /**
     * Restrict allowed file types for uploads
     */
    public function restrict_upload_mimes($mimes) {
        // Only allow specific file types for AR models
        $allowed_types = array(
            'glb' => 'model/gltf-binary',
            'gltf' => 'model/gltf+json',
            'usdz' => 'model/vnd.usdz+zip',
            'jpg|jpeg' => 'image/jpeg',
            'png' => 'image/png',
            'webp' => 'image/webp'
        );
        
        // If this is an AR-related upload, restrict to allowed types
        if (isset($_POST['ar_upload']) || 
            (isset($_POST['action']) && $_POST['action'] === 'ar_upload_file')) {
            return $allowed_types;
        }
        
        return $mimes;
    }
    
    /**
     * Validate file uploads
     */
    public function validate_file_upload($file) {
        // Only validate AR-related uploads
        // If this is not an AR-related upload, skip validation and allow WordPress defaults
        if (!isset($_POST['ar_upload']) && 
            (!isset($_POST['action']) || $_POST['action'] !== 'ar_upload_file')) {
            return $file;
        }
        
        // Skip validation for plugin/theme installations
        if (isset($_POST['action']) && in_array($_POST['action'], ['upload-plugin', 'upload-theme'])) {
            return $file;
        }
        
        // Skip validation for ZIP files (plugin/theme uploads)
        $file_extension = strtolower(pathinfo($file['name'], PATHINFO_EXTENSION));
        if ($file_extension === 'zip') {
            return $file;
        }
        
        // Check file size (max 50MB for 3D models)
        $max_size = 50 * 1024 * 1024; // 50MB in bytes
        if ($file['size'] > $max_size) {
            $file['error'] = sprintf(__('File size exceeds maximum allowed size of %s MB.', 'ar-for-wordpress'), 50);
            return $file;
        }
        
        // Validate file extension
        $allowed_extensions = array('glb', 'gltf', 'usdz', 'jpg', 'jpeg', 'png', 'webp');
        
        if (!in_array($file_extension, $allowed_extensions)) {
            $file['error'] = __('File type not allowed. Please upload only GLB, GLTF, USDZ, JPG, PNG, or WebP files.', 'ar-for-wordpress');
            return $file;
        }
        
        // Additional validation for 3D model files
        if (in_array($file_extension, array('glb', 'gltf', 'usdz'))) {
            // Check if file contains valid 3D model data
            if (!$this->validate_3d_model_file($file['tmp_name'], $file_extension)) {
                $file['error'] = __('Invalid 3D model file. Please ensure the file is not corrupted.', 'ar-for-wordpress');
                return $file;
            }
        }
        
        // Validate image files
        if (in_array($file_extension, array('jpg', 'jpeg', 'png', 'webp'))) {
            if (!$this->validate_image_file($file['tmp_name'])) {
                $file['error'] = __('Invalid image file. Please ensure the file is not corrupted.', 'ar-for-wordpress');
                return $file;
            }
        }
        
        return $file;
    }
    
    /**
     * Validate 3D model files
     */
    private function validate_3d_model_file($file_path, $extension) {
        if (!file_exists($file_path)) {
            return false;
        }
        
        $file_size = filesize($file_path);
        if ($file_size === 0) {
            return false;
        }
        
        // Read first few bytes to check file signature
        $handle = fopen($file_path, 'rb');
        if (!$handle) {
            return false;
        }
        
        $header = fread($handle, 16);
        fclose($handle);
        
        switch ($extension) {
            case 'glb':
                // GLB files start with "glTF" magic number
                return strpos($header, 'glTF') === 0;
                
            case 'gltf':
                // GLTF files are JSON, should start with {
                return strpos($header, '{') === 0;
                
            case 'usdz':
                // USDZ files are ZIP files with specific content
                return strpos($header, 'PK') === 0;
                
            default:
                return false;
        }
    }
    
    /**
     * Validate image files
     */
    private function validate_image_file($file_path) {
        if (!file_exists($file_path)) {
            return false;
        }
        
        // Use getimagesize to validate image
        $image_info = @getimagesize($file_path);
        if ($image_info === false) {
            return false;
        }
        
        // Check if it's a valid image type
        $allowed_types = array(IMAGETYPE_JPEG, IMAGETYPE_PNG, IMAGETYPE_WEBP);
        return in_array($image_info[2], $allowed_types);
    }
    
    /**
     * Handle secure file upload via AJAX
     */
    public function handle_secure_file_upload() {
        // Verify nonce
        if (!wp_verify_nonce($_POST['_wpnonce'], 'ar_secure_nonce')) {
            wp_die(__('Security check failed.', 'ar-for-wordpress'));
        }
        
        // Check user permissions
        if (!current_user_can('upload_files')) {
            wp_die(__('You do not have permission to upload files.', 'ar-for-wordpress'));
        }
        
        // Validate file upload
        if (!isset($_FILES['ar_file']) || $_FILES['ar_file']['error'] !== UPLOAD_ERR_OK) {
            wp_die(__('File upload failed.', 'ar-for-wordpress'));
        }
        
        // Process the upload securely
        $upload = wp_handle_upload($_FILES['ar_file'], array('test_form' => false));
        
        if (isset($upload['error'])) {
            wp_die($upload['error']);
        }
        
        // Return success response
        wp_send_json_success(array(
            'url' => $upload['url'],
            'file' => $upload['file']
        ));
    }
    
    /**
     * Deny unauthorized uploads
     */
    public function deny_unauthorized_upload() {
        wp_die(__('You must be logged in to upload files.', 'ar-for-wordpress'));
    }
    
    /**
     * Sanitize REST API responses
     */
    public function sanitize_rest_response($served) {
        // Remove sensitive information from responses
        if (isset($_GET['_fields'])) {
            $fields = explode(',', sanitize_text_field($_GET['_fields']));
            // Ensure only safe fields are returned
            $safe_fields = array('id', 'title', 'status', 'date');
            $fields = array_intersect($fields, $safe_fields);
            $_GET['_fields'] = implode(',', $fields);
        }
        
        return $served;
    }
    
    /**
     * Sanitize file paths to prevent directory traversal
     */
    public static function sanitize_file_path($path) {
        // Remove any directory traversal attempts
        $path = str_replace(array('../', '..\\', './', '.\\'), '', $path);
        
        // Ensure path is within uploads directory
        $upload_dir = wp_upload_dir();
        $real_path = realpath($path);
        $upload_real_path = realpath($upload_dir['basedir']);
        
        if ($real_path === false || strpos($real_path, $upload_real_path) !== 0) {
            return false;
        }
        
        return $path;
    }
    
    /**
     * Validate and sanitize AR model data
     */
    public static function sanitize_ar_model_data($data) {
        $sanitized = array();
        
        // Sanitize basic fields
        $basic_fields = array('title', 'description', 'status');
        foreach ($basic_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = sanitize_text_field($data[$field]);
            }
        }
        
        // Sanitize numeric fields
        $numeric_fields = array('ar_x', 'ar_y', 'ar_z', 'ar_field_of_view', 'ar_zoom_in', 'ar_zoom_out');
        foreach ($numeric_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = floatval($data[$field]);
            }
        }
        
        // Sanitize file URLs
        $file_fields = array('usdz_file', 'glb_file', 'skybox_file', 'ar_environment_image');
        foreach ($file_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = esc_url_raw($data[$field]);
            }
        }
        
        // Sanitize boolean fields
        $boolean_fields = array('ar_view_hide', 'ar_qr_hide', 'ar_hide_dimensions', 'ar_animation', 'ar_autoplay');
        foreach ($boolean_fields as $field) {
            if (isset($data[$field])) {
                $sanitized[$field] = (bool) $data[$field];
            }
        }
        
        return $sanitized;
    }
}

// Initialize security enhancements
new AR_Security_Enhancements();

/**
 * Additional security functions
 */

/**
 * Secure file download function
 */
function ar_secure_file_download($file_path, $filename = '') {
    // Validate file path
    $file_path = AR_Security_Enhancements::sanitize_file_path($file_path);
    if (!$file_path) {
        wp_die(__('Invalid file path.', 'ar-for-wordpress'));
    }
    
    // Check if file exists
    if (!file_exists($file_path)) {
        wp_die(__('File not found.', 'ar-for-wordpress'));
    }
    
    // Set proper headers
    $file_size = filesize($file_path);
    $file_type = wp_check_filetype($file_path);
    
    header('Content-Type: ' . $file_type['type']);
    header('Content-Length: ' . $file_size);
    header('Content-Disposition: attachment; filename="' . esc_attr($filename ?: basename($file_path)) . '"');
    header('Cache-Control: no-cache, must-revalidate');
    header('Expires: Sat, 26 Jul 1997 05:00:00 GMT');
    
    // Output file content
    readfile($file_path);
    exit;
}

/**
 * Secure file deletion function
 */
function ar_secure_file_delete($file_path) {
    // Validate file path
    $file_path = AR_Security_Enhancements::sanitize_file_path($file_path);
    if (!$file_path) {
        return false;
    }
    
    // Check if file exists
    if (!file_exists($file_path)) {
        return false;
    }
    
    // Delete file
    return unlink($file_path);
}

/**
 * Validate AR model ID
 */
function ar_validate_model_id($id) {
    $id = intval($id);
    if ($id <= 0) {
        return false;
    }
    
    // Check if post exists and is of correct type
    $post = get_post($id);
    if (!$post || $post->post_type !== 'armodels') {
        return false;
    }
    
    return $id;
}
