<?php
/**
 * Plugin Name:       Wally Monitor
 * Description:       Verificador de acessibilidade em tempo real e sob demanda para WordPress.
 * Version:           1.5.4
 * Author:            Equallyze Solutions
 * License:           GPL v2 or later
 * License URI:       https://www.gnu.org/licenses/gpl-2.0.html
 * Text Domain:       wally-monitor
 */

if ( ! defined( 'ABSPATH' ) ) {
    exit;
}

// Constantes
define( 'WALLY_MONITOR_VERSION', '1.5.4' );
define( 'WALLY_MONITOR_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
define( 'WALLY_MONITOR_PLUGIN_URL', plugin_dir_url( __FILE__ ) );

// Autoload de classes — mapeia nomes de classe para arquivos automaticamente.
spl_autoload_register( function ( $class ) {
    // Mapa de classes que não seguem a convenção padrão.
    $class_map = array(
        'Wally_Sanitizer'       => 'class-wally-sanitizer.php',
        'Wally_Database'        => 'class-wally-database.php',
        'Wally_Admin'           => 'class-wally-admin.php',
        'Wally_Ajax'            => 'class-wally-ajax.php',
        'Wally_Export'          => 'class-wally-export.php',
        'Wally_SEO_Integration' => 'class-wally-seo-integration.php',
        'Wally_HTML_Checker'    => 'class-wally-html-checker.php',
        'Wally_Cron'            => 'class-wally-cron.php',
        'Wally_Rest_API'        => 'class-wally-rest-api.php',
        'Wally_PDF_Generator'   => 'class-wally-pdf-generator.php',
        'Wally_CLI_Command'     => 'class-wally-cli.php',
    );

    if ( isset( $class_map[ $class ] ) ) {
        $file = WALLY_MONITOR_PLUGIN_DIR . 'includes/' . $class_map[ $class ];
        if ( file_exists( $file ) ) {
            require_once $file;
        }
    }
} );

// Activation hook - cria tabelas no banco
register_activation_hook( __FILE__, array( 'Wally_Database', 'activate' ) );

// Deactivation hook - limpa agendamentos cron
register_deactivation_hook( __FILE__, array( 'Wally_Cron', 'deactivate' ) );

// Inicializacao do plugin
add_action( 'plugins_loaded', 'wally_monitor_init' );

function wally_monitor_init() {
    Wally_Admin::init();
    Wally_Ajax::init();
    Wally_Export::init();
    Wally_Cron::init();
    Wally_Rest_API::init();
}

// Backwards compatibility wrappers
function wally_monitor_sanitize_report_data( $data ) {
    return Wally_Sanitizer::sanitize_report_data( $data );
}

function wally_monitor_validate_report_structure( $report_data ) {
    return Wally_Sanitizer::validate_report_structure( $report_data );
}

/**
 * Validates a URL against SSRF attacks.
 *
 * Ensures the URL uses http/https, resolves to a public IP, and belongs
 * to the current site (unless explicitly allowed via filter).
 *
 * @since 1.3.1
 * @param string $url URL to validate.
 * @return true|WP_Error True if safe, WP_Error with reason otherwise.
 */
function wally_monitor_validate_url( $url ) {
    // Must be http or https
    $scheme = wp_parse_url( $url, PHP_URL_SCHEME );
    if ( ! in_array( $scheme, array( 'http', 'https' ), true ) ) {
        return new WP_Error( 'invalid_scheme', __( 'Apenas URLs http/https são permitidas.', 'wally-monitor' ) );
    }

    $host = wp_parse_url( $url, PHP_URL_HOST );
    if ( empty( $host ) ) {
        return new WP_Error( 'invalid_host', __( 'URL sem host válido.', 'wally-monitor' ) );
    }

    // Block private/reserved IPs (SSRF protection)
    $ip = gethostbyname( $host );
    if ( $ip === $host && ! filter_var( $host, FILTER_VALIDATE_IP ) ) {
        // DNS resolution failed — allow through (could be internal hostname in some setups)
        // but only if it matches the site host
        $site_host = wp_parse_url( site_url(), PHP_URL_HOST );
        if ( $host !== $site_host ) {
            return new WP_Error( 'dns_failed', __( 'Não foi possível resolver o host da URL.', 'wally-monitor' ) );
        }
    } elseif ( filter_var( $ip, FILTER_VALIDATE_IP ) ) {
        // Check for private/reserved ranges
        if ( ! filter_var( $ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE ) ) {
            $site_host = wp_parse_url( site_url(), PHP_URL_HOST );
            $site_ip   = gethostbyname( $site_host );

            // Allow if the IP matches the site's own IP (self-scan is expected behavior)
            if ( $ip !== $site_ip && $host !== $site_host && $host !== 'localhost' ) {
                /**
                 * Filters whether to allow requests to private/reserved IPs.
                 *
                 * @since 1.3.1
                 * @param bool   $allow Whether to allow the request. Default false.
                 * @param string $url   The URL being validated.
                 * @param string $ip    The resolved IP address.
                 */
                if ( ! apply_filters( 'wally_monitor_allow_private_ip', false, $url, $ip ) ) {
                    return new WP_Error(
                        'ssrf_blocked',
                        __( 'URL aponta para IP privado/reservado. Requisição bloqueada por segurança.', 'wally-monitor' )
                    );
                }
            }
        }
    }

    return true;
}