<?php

/*
Plugin Name: Securicheck
Plugin URI: https://wp-securicheck.com
Description: Auditez et sécurisez votre site WordPress maintenant.
Author: Mickael Hauwy
Version: 2.2.0
Author URI: https://8pixl.fr
License: GPLv3
License URI: https://www.gnu.org/licenses/gpl-3.0.html
Domain Path: /languages/
Text Domain: securicheck
*/

if (!defined('ABSPATH')) {
    exit; // Pas d'accès direct !
}

require_once(ABSPATH . 'wp-admin/includes/plugin.php');
// les fonctions utiles
require_once(__DIR__ . '/utils/utils.php');
// la page d'administration
require_once(__DIR__ . '/admin/admin.php');
// les screens de l'administration audit
require_once(__DIR__ . '/admin/Screen_audit.php');
require_once(__DIR__ . '/admin/Screen_reglages.php');
require_once(__DIR__ . '/admin/Screen_protection_login.php');
require_once(__DIR__ . '/admin/Screen_protection_spam.php');
require_once(__DIR__ . '/admin/Screen_connexions.php');
// les screens de pub
require_once(__DIR__ . '/admin/Screen_outils_go_pro.php');
require_once(__DIR__ . '/admin/Screen_reglages_securite_go_pro.php');
require_once(__DIR__ . '/admin/Screen_licence_go_pro.php');
// les classes de l'audit
require_once(__DIR__ . '/audit/Audit.php');
require_once(__DIR__ . '/audit/ResultatAudit.php');
// le watch des connexions
require_once(__DIR__ . '/utils/connexions-logs.php');
// les notifications
require_once(__DIR__ . '/utils/notifications.php');
require_once(__DIR__ . '/utils/notification-compte-administrateur.php');
// cacher le BO
require_once(__DIR__ . '/utils/cachette.php');
// brute force protection
require_once(__DIR__ . '/utils/bruteForce.php');
// banti Spam
require_once(__DIR__ . '/utils/antiSpam.php');
// la baniere de pub
require_once(__DIR__ . '/utils/remote-config/class-promo-banner.php');

// déclare la version du plugin
//define('HPIXL_SECURICHECK_PLUGIN_VERSION', get_plugin_data(__FILE__, false)['Version']);
$_securicheck_file_data = get_file_data(__FILE__, ['Version' => 'Version']);
define('HPIXL_SECURICHECK_PLUGIN_VERSION', $_securicheck_file_data['Version']);
unset($_securicheck_file_data);
//le text domain
define('HPIXL_SECURICHECK_TEXT_DOMAIN', 'securicheck');
// déclare les constantes
define('HPIXL_SECURICHECK_PLUGIN_PATH', dirname(__FILE__));
define('HPIXL_SECURICHECK_PLUGIN_URL', plugin_dir_url(__FILE__));
define('HPIXL_SECURICHECK_PLUGIN_FILE_URL', __FILE__);
define('HPIXL_SECURICHECK_DB_VERSION', '1.9');

// la version minimum de PHP à comparer
define('HPIXL_SECURICHECK_PHP_MINI', '8.2.0');
// la version minimum de TLs à comparer
define('HPIXL_SECURICHECK_TLS_MINI', '1.2');
// Les versions minimales de base de données (LTS uniquement)
// Note : les Innovation releases MySQL (9.0, 9.1...) ont un cycle court mais version_compare
// les considère comme "récentes" — cas marginal en production.
define('HPIXL_SECURICHECK_MYSQL_MINI',   '8.4');
define('HPIXL_SECURICHECK_MARIADB_MINI', '10.6');


//la taille de la BDD Maxi
define('HPIXL_SECURICHECK_BDD_MAXI', '500 MB');
// déclare le slug du plugin
define('HPIXL_SECURICHECK_SETTINGS_SLUG', 'securicheck');

//les textes pour l'image de test hotlinking
define('HPIXL_SECURICHECK_HOTLINKING_IMAGE_NON_PRESENTE', 'Image définie dans les réglages du plugin non trouvée sur votre site');
define('HPIXL_SECURICHECK_HOTLINKING_PARAMETRE_NON_DEFINI', 'Merci d\'aller dans les réglages du plugin pour choisir l\'url d\'une image afin de pouvoir réaliser le test');

//les tables en bdd
define('HPIXL_SECURICHECK_TABLE_AUDIT', 'securicheck_audit');
define('HPIXL_SECURICHECK_TABLE_AUDIT_RESULTATS', 'securicheck_audit_resultats');
define('HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS', 'securicheck_audit_logs_connexions');
define('HPIXL_SECURICHECK_TABLE_BRUTE_FORCE_LOGS', 'securicheck_brute_force_logs');
define('HPIXL_SECURICHECK_TABLE_ANTISPAM_COMMENTAIRES_LOGS', 'securicheck_anti_spam_commentaires_logs');

//les constantes du mode d'audit
define('HPIXL_SECURICHECK_AUDIT_MODE_MANUEL', 'manuel');
define('HPIXL_SECURICHECK_AUDIT_MODE_AUTOMATIQUE', 'automatique');

//le nom du plugin pro
define('HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME', 'securicheck-pro/securicheck-pro.php');



//pour gérer la fermeture temporaire sur une durée donnée de la baniére de pub
add_action('wp_ajax_securicheck_hide_promo_banner', 'hpixl_securicheck_hide_banner');


// Priorité 5, donc avant la création de la classe
add_action('admin_init', 'hpixl_securicheck_check_migration_db', 5);
function hpixl_securicheck_check_migration_db()
{
    // pour les modifications de bdd
    $installed_version = get_option('hpixl_securicheck_db_version');

    // les modifications globales
    if ($installed_version !== HPIXL_SECURICHECK_DB_VERSION) {

        hpixl_securicheck_init_db_myplugin();
        update_option('hpixl_securicheck_db_version', HPIXL_SECURICHECK_DB_VERSION);
    }

    // Migration spécifique 1.3 → agrandissement varchar du champs de l'IP de la table des logs de connexion
    if ($installed_version && version_compare($installed_version, '1.3', '<')) {
        global $wpdb;
        $table = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
        $wpdb->query("ALTER TABLE `$table` MODIFY ip VARCHAR(45) NOT NULL");
    }
}

//pour ne pas charger la traduction avant le init (10)
add_action('init', 'hpixl_securicheck_init_securicheck', 10);
function hpixl_securicheck_init_securicheck()
{
    $securicheck = new Hpixl_Securicheck();
    load_plugin_textdomain('securicheck', false, dirname(plugin_basename(__FILE__)) . '/languages/');
}

register_activation_hook(__FILE__, 'hpixl_securicheck_activation_plugin');
/**
 * Lancé à l'activation du plugin
 */
function hpixl_securicheck_activation_plugin()
{
    // Insertion des tables en bdd
    hpixl_securicheck_init_db_myplugin();

    // Stocke la version installée
    update_option('hpixl_securicheck_db_version', HPIXL_SECURICHECK_DB_VERSION);
}

// quand le plugin est initialisé
function hpixl_securicheck_init_db_myplugin()
{
    global $wpdb;

    require_once ABSPATH . 'wp-admin/includes/upgrade.php';
    $charset_collate = $wpdb->get_charset_collate();

    $tableAudit = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT;
    $tableAuditResultats = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_RESULTATS;
    $tableAuditLogsConnexions = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_AUDIT_LOGS_CONNEXIONS;
    $tableBruteForceLogs = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_BRUTE_FORCE_LOGS;
    $tableAntiSpamCommentairesLogs = $wpdb->prefix . HPIXL_SECURICHECK_TABLE_ANTISPAM_COMMENTAIRES_LOGS;

    /**
     * La table wp_securicheck_audit
     */
    // Query - Create Table
    $sqlAudit = "CREATE TABLE `$tableAudit` (";
    $sqlAudit .= " `id` int(11) NOT NULL auto_increment, ";
    $sqlAudit .= " `date` DATETIME NOT NULL, ";
    $sqlAudit .= " `type` VARCHAR(32) NOT NULL, ";
    $sqlAudit .= " `score` int(11) NOT NULL, ";
    $sqlAudit .= " `pb_total` int(11) NOT NULL, ";
    $sqlAudit .= " `pb_techniques` int(11) NOT NULL, ";
    $sqlAudit .= " `pb_fonctionnels` int(11) NOT NULL, ";
    $sqlAudit .= " `pb_securite` int(11) NOT NULL, ";
    $sqlAudit .= " `pb_performance` int(11) NOT NULL, ";
    $sqlAudit .= " PRIMARY KEY `audit_id` (`id`) ";
    $sqlAudit .= ") $charset_collate;";

    // Créer la Table
    dbDelta($sqlAudit);

    /**
     * La table wp_securicheck_audit_resultats
     */

    // Query - Create Table
    $sqlAuditResultats = "CREATE TABLE `$tableAuditResultats` (";
    $sqlAuditResultats .= " `id` int(11) NOT NULL auto_increment, ";
    $sqlAuditResultats .= " `id_audit` int(11) NOT NULL, ";
    $sqlAuditResultats .= " `action` VARCHAR(128) NOT NULL, ";
    $sqlAuditResultats .= " `resultat` VARCHAR(6144) NOT NULL, ";
    $sqlAuditResultats .= " PRIMARY KEY `resultat_id` (`id`) ";
    $sqlAuditResultats .= ") $charset_collate;";

    // Créer la Table
    dbDelta($sqlAuditResultats);

    /**
     * La table wp_securicheck_audit_logs_connexions
     */

    // Query - Create Table
    $sqlAuditLogsConnexions  = "CREATE TABLE `$tableAuditLogsConnexions` (\n";
    $sqlAuditLogsConnexions .= "  `id` int(11) NOT NULL auto_increment,\n";
    $sqlAuditLogsConnexions .= "  `date` DATETIME NOT NULL,\n";
    $sqlAuditLogsConnexions .= "  `username` VARCHAR(128) NOT NULL,\n";
    $sqlAuditLogsConnexions .= "  `browser` VARCHAR(512) NOT NULL,\n";
    $sqlAuditLogsConnexions .= "  `ip` VARCHAR(45) NOT NULL,\n";
    $sqlAuditLogsConnexions .= "  `etat` VARCHAR(16) NOT NULL,\n";
    $sqlAuditLogsConnexions .= "  PRIMARY KEY  (`id`),\n";
    $sqlAuditLogsConnexions .= "  KEY `idx_ip_etat_date` (`ip`, `etat`, `date`)\n";
    $sqlAuditLogsConnexions .= ") $charset_collate;";

    // Créer la Table
    dbDelta($sqlAuditLogsConnexions);

    /**
     * La table wp_securicheck_brute_force_logs
     */
    $sqlBruteForceLogs  = "CREATE TABLE `$tableBruteForceLogs` (\n";
    $sqlBruteForceLogs .= "  `id` int(11) NOT NULL auto_increment,\n";
    $sqlBruteForceLogs .= "  `ip` VARCHAR(45) NOT NULL,\n";
    $sqlBruteForceLogs .= "  `action` VARCHAR(20) NOT NULL,\n";
    $sqlBruteForceLogs .= "  `date_action` DATETIME NOT NULL,\n";
    $sqlBruteForceLogs .= "  `auteur_action` VARCHAR(100) NOT NULL,\n";
    $sqlBruteForceLogs .= "  `raison` VARCHAR(255) NULL,\n";
    $sqlBruteForceLogs .= "  `duree_blocage` int(11) NULL,\n";
    $sqlBruteForceLogs .= "  PRIMARY KEY  (`id`),\n";
    $sqlBruteForceLogs .= "  KEY `idx_ip_date` (`ip`, `date_action`)\n";
    $sqlBruteForceLogs .= ") $charset_collate;";

    dbDelta($sqlBruteForceLogs);

    /**
     * La table wp_securicheck_anti_spam_commentaires_logs
     */
    $sqlAntiSpamCommentairesLogs  = "CREATE TABLE `$tableAntiSpamCommentairesLogs` (\n";
    $sqlAntiSpamCommentairesLogs .= "  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,\n";
    $sqlAntiSpamCommentairesLogs .= "  `ip` VARCHAR(45) NOT NULL,\n";
    $sqlAntiSpamCommentairesLogs .= "  `email` VARCHAR(100) NULL,\n";
    $sqlAntiSpamCommentairesLogs .= "  `content` TEXT NULL,\n";
    $sqlAntiSpamCommentairesLogs .= "  `score` INT NOT NULL,\n";
    $sqlAntiSpamCommentairesLogs .= "  `reason` VARCHAR(255) NULL,\n";
    $sqlAntiSpamCommentairesLogs .= "  `is_audit` TINYINT(1) NOT NULL DEFAULT 0,\n";
    $sqlAntiSpamCommentairesLogs .= "  `created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,\n";
    $sqlAntiSpamCommentairesLogs .= "  PRIMARY KEY (`id`),\n";
    $sqlAntiSpamCommentairesLogs .= "  KEY `idx_ip_score` (`ip`, `score`)\n";
    $sqlAntiSpamCommentairesLogs .= ") $charset_collate;";

    dbDelta($sqlAntiSpamCommentairesLogs);
}

/**
 * Ferme la baniere pendant 3 jours au clic sur la croix
 */
function hpixl_securicheck_hide_banner()
{

    check_ajax_referer('securicheck_hide_banner', 'nonce');

    $user_id = get_current_user_id();
    if (!$user_id) {
        wp_send_json_error();
    }

    $days = isset($_POST['days']) ? (int) $_POST['days'] : 3;
    $days = max(1, min(30, $days)); // sécurité

    update_user_meta(
        $user_id,
        'securicheck_promo_banner_hidden_until',
        time() + DAY_IN_SECONDS * $days
    );

    wp_send_json_success();
}


// Hook pour désactiver le lien "Désactiver" du plugin gratuit si securicheck pro et actif
add_filter('plugin_action_links_securicheck/securicheck.php', 'hpixl_securicheck_disable_deactivate_link', 10, 1);

function hpixl_securicheck_disable_deactivate_link($actions)
{
    // Vérifier si la version pro est active
    if (defined('HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME') && is_plugin_active(HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME)) {
        // Supprimer le lien "Désactiver"
        if (isset($actions['deactivate'])) {
            unset($actions['deactivate']);
        }

        // Optionnel : ajouter un message informatif
        $actions['info'] = '<span style="color:#999;">Désactivation désactivée (Securicheck Pro actif)</span>';
    }
    return $actions;
}

class Hpixl_Securicheck
{

    protected $pluginPath;
    protected $pluginUrl;
    protected $pluginSlug;

    public function __construct()
    {
        // les infos utiles du plugin
        $this->pluginPath = HPIXL_SECURICHECK_PLUGIN_PATH;
        $this->pluginUrl = HPIXL_SECURICHECK_PLUGIN_URL;
        $this->pluginSlug = HPIXL_SECURICHECK_SETTINGS_SLUG;

        register_deactivation_hook(__FILE__, array($this, 'hpixl_securicheck_desactivation_plugin'));

        add_action('plugins_loaded', array($this, 'hpixl_securicheck_init_after_plugin_loaded'), 5);
        add_action('admin_init', array($this, 'hpixl_securicheck_init'));
        add_action('wp_enqueue_scripts', array($this, 'reports_scripts_hpixl_securicheck'));
        add_action('admin_enqueue_scripts', array($this, 'reports_admin_scripts_hpixl_securicheck'), 10);

        add_filter('plugin_action_links_' . plugin_basename(__FILE__), array($this, 'hpixl_securicheck_plugin_action_links'));
        add_action('in_plugin_update_message-8PIXL-hpixl-securicheck/hpixl-securicheck.php', array($this, 'hpixl_securicheck_prefix_plugin_update_message'), 10, 2);

        add_action('wp_dashboard_setup', array($this, 'hpixl_securicheck_register_custom_dashboard_widget'), 1);

        //on ajoute un loader dans le header de la page d'admin
        add_action('admin_head', array($this, 'hpixl_securicheck_adminheader'));
    }


    //loader si on est en train de créer un audit
    function hpixl_securicheck_adminheader()
    {
        //si on n'est pas sur la page admin.php on sort
        global $pagenow;
        if (!('admin.php' == $pagenow)) return;

        //si la page n'est pas la page d'audit on sort
        if (!isset($_GET['page']) || $_GET['page'] != 'securicheck') return;

        //si on n'est pas en train de créer un audit on sort
        if (!isset($_POST['btn-submit-audit']) || $_POST['btn-submit-audit'] === "") return;
        if (!((isset($_POST['_wpnonce-lancer-audit-bienvenue']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce-lancer-audit-bienvenue'])), 'lancer_audit')) ||
            (isset($_POST['_wpnonce-lancer-audit']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['_wpnonce-lancer-audit'])), 'lancer_audit'))
        )) {
            return;
        }

        $urlLogo = HPIXL_SECURICHECK_PLUGIN_URL . "images/securicheck.png";
        $urlLoader = HPIXL_SECURICHECK_PLUGIN_URL . "images/Preloader_4.gif";
?>
        <div class='hpixl-securicheck-pre-con' style='--imgLoader : url("<?php echo esc_url($urlLoader) ?>")'>
            <h2>Securicheck</h2>
            <img src="<?php echo esc_url($urlLogo) ?>" />
            <p><?php esc_html_e("Audit en cours", "securicheck"); ?></p>
        </div>";
    <?php
    }

    /**
     * Lancé à la désactivation du plugin
     */
    public function hpixl_securicheck_desactivation_plugin()
    {
        //suppression des options
        // delete_option('hpixl_securicheck_toggle_notifications');
        //delete_option('hpixl_securicheck_toggle_page_connexion_url');
        //delete_option('hpixl_securicheck_textarea_page_connexion_url');
        //delete_option('hpixl_securicheck_toggle_page_connexion_redirection');
        //delete_option('hpixl_securicheck_textarea_page_connexion_redirection');
        //delete_option('hpixl_securicheck_toggle_brute_force');
    }

    //on désactive le plugin securicheck pro si il est actif
    public function hpixl_securicheck_disable_securicheck_pro()
    {
        // Vérifie si le plugin est actif
        if (is_plugin_active(HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME)) {
            // Désactive le plugin
            deactivate_plugins(HPIXL_SECURICHECK_PREMIUM_PLUGIN_NAME);
        }
    }

    /** 
     * charge ceci une fois le plugin chargé
     */

    public function hpixl_securicheck_init_after_plugin_loaded() {}

    /**
     * init
     */
    public function hpixl_securicheck_init()
    {
        /* chargement de la baniere*/
        if (!is_admin()) {
            return;
        }
        if (class_exists('HPIXLSecuricheck_Promo_Banner')) {
            HPIXLSecuricheck_Promo_Banner::init();
        }
    }


    /** 
     * le style et le js du frontend 
     */
    public function reports_scripts_hpixl_securicheck() {}

    /* le style et le js du backend */
    public function reports_admin_scripts_hpixl_securicheck($hook_suffix)
    {
        //scripts
        wp_enqueue_script('hpixl_securicheck_admin_script',  $this->pluginUrl . 'js/hpixl_securicheck_admin.js', array('jquery'), false, true);
        //chartjs
        wp_enqueue_script('hpixl_securicheck_admin_script_chartjs', $this->pluginUrl . "js/chart.umd.js", array('jquery'), false, true);
        //style
        //  if ('appearance_page_theme-options' === $hook_suffix) {
        wp_enqueue_style('hpixl_securicheck_admin_style', $this->pluginUrl . 'css/hpixl_securicheck_admin_style.css', array(), HPIXL_SECURICHECK_PLUGIN_VERSION);
        wp_enqueue_style('hpixl_securicheck_admin_audit_style', $this->pluginUrl . 'css/hpixl_securicheck_admin_audit_style.css', array(), HPIXL_SECURICHECK_PLUGIN_VERSION);
        wp_enqueue_style('hpixl_securicheck_admin_reglages_style', $this->pluginUrl . 'css/hpixl_securicheck_admin_reglages_style.css', array(), HPIXL_SECURICHECK_PLUGIN_VERSION);
        // }
        // chargement du custom_dashicons() 
        wp_enqueue_style('hpixl_securicheck_securicheck-dashicon', $this->pluginUrl . 'css/hpixl_dashicon_securicheck.css', array(), HPIXL_SECURICHECK_PLUGIN_VERSION);
        //pour le widget dans le dashboard
        wp_enqueue_script('hpixl_securicheck_show_chart_script',  $this->pluginUrl . 'js/hpixl_securicheck_show_chart.js', array('jquery'), true, true);
        wp_localize_script('hpixl_securicheck_show_chart_script', 'data', hpixl_securicheck_count_connexions_failed_by_day());
    }




    /**
     * Ajout d'un widget dans le dashboard du wordpress
     */
    function hpixl_securicheck_render_dashboard_widget_connexions($callback_args, $widget)
    {
        $nb = hpixl_securicheck_get_nb_connexions_failed();
        echo '<strong>Nombre de connexions échouées sur les 30 derniers jours : ' . esc_html($nb) . '</strong>';
    ?>

        <div id="chart-container" style="position: relative; height:320px;margin-bottom:20px;">
            <canvas id="graphCanvas"></canvas>
        </div>

        <a class="hpixl-securicheck-widget-bouton"
            href="<?php echo esc_url(admin_url('admin.php?page=securicheck-connexions&tab=echouees')); ?>">
            Détails des connexions
        </a>

<?php
    }

    function hpixl_securicheck_register_custom_dashboard_widget()
    {
        global $wp_meta_boxes;

        // Sauvegarder les widgets existants
        $normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
        $side_dashboard = $wp_meta_boxes['dashboard']['side']['core'];

        // Supprimer tous les widgets
        $wp_meta_boxes['dashboard']['normal']['core'] = array();
        $wp_meta_boxes['dashboard']['side']['core'] = array();

        wp_add_dashboard_widget(
            'hpixl-securicheck-dashboard-widget-connexions',
            'Securicheck',
            array($this, 'hpixl_securicheck_render_dashboard_widget_connexions'), // Fonction de callback
            null, // Pas d'édition
            null, // Pas de contrôle de contenu
            'normal', // Section "normal"
            'high' // Priorité haute
        );
        // Remettre les widgets sauvegardés en dessous du widget personnalisé
        // Vérifier si la clé 'hpixl-securicheck-dashboard-widget-connexions' existe dans $wp_meta_boxes avant d'essayer de la récupérer
        if (isset($wp_meta_boxes['dashboard']['normal']['core']['hpixl-securicheck-dashboard-widget-connexions'])) {
            $custom_widget = array(
                'hpixl-securicheck-dashboard-widget-connexions' => $wp_meta_boxes['dashboard']['normal']['core']['hpixl-securicheck-dashboard-widget-connexions']
            );
        } else {
            $custom_widget = array();
        }

        // Fusionner le widget personnalisé avec les autres widgets sauvegardés
        $wp_meta_boxes['dashboard']['normal']['core'] = array_merge(
            $custom_widget,
            $normal_dashboard
        );

        $wp_meta_boxes['dashboard']['side']['core'] = $side_dashboard;
    }

    /** 
     * Ajout d'un lien "settings" dans la liste des plugins dans le backoffice
     */
    public function hpixl_securicheck_plugin_action_links($links)
    {
        $links[] = '<a href="' . menu_page_url($this->pluginSlug, false) . '">Paramètres</a>';
        return $links;
    }
}
