<?php

use CleantalkSP\SpbctWP\AdjustToEnvironmentModule\AdjustToEnvironmentHandler;
use CleantalkSP\SpbctWP\CleantalkSettingsTemplates;
use CleantalkSP\SpbctWP\Cron;
use CleantalkSP\SpbctWP\Escape;
use CleantalkSP\SpbctWP\Scanner\DBTrigger\DBTriggerService;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\Dto\PluginReport;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\Dto\ThemeReport;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\VulnerabilityAlarmService;
use CleantalkSP\Variables\Post;
use CleantalkSP\Variables\Server;
use CleantalkSP\SpbctWP\LinkConstructor;
use CleantalkSP\SpbctWP\ListTable;
use CleantalkSP\SpbctWP\Scanner\Cure;
use CleantalkSP\SpbctWP\Scanner\OSCron\Storages\OsCronTasksStorage;
use CleantalkSP\SpbctWP\Scanner\ScannerQueue;
use CleantalkSP\SpbctWP\SpbcEnqueue;
use CleantalkSP\SpbctWP\Variables\Cookie;
use CleantalkSP\SpbctWP\VulnerabilityAlarm\VulnerabilityAlarm;
use CleantalkSP\SpbctWP\FileEditorDisabler\FileEditorDisabler;
use CleantalkSP\SpbctWP\UsersPassCheckModule\UsersPassCheckHandler;

// Prevent direct call
if ( ! defined('ABSPATH') ) {
    die('Not allowed!');
}

// Settings page
require_once('spbc-settings.php');

/**
 * Admin action 'admin_init' - Add the admin settings and such
 */
function spbc_admin_init()
{
    global $spbc, $apbct;

    //Logging admin actions
    if (
        $spbc->feature_restrictions->getState($spbc, 'security_log')->is_active &&
        ! defined('DOING_AJAX')
    ) {
        spbc_admin_log_action();
    }

    if ( is_main_site() ) {
        spbc_set_malware_scan_warns();
    }

    // Admin bar
    $spbc->admin_bar_enabled = $spbc->settings['admin_bar__show'] && current_user_can('activate_plugins');

    if ($spbc->admin_bar_enabled) {
        require_once SPBC_PLUGIN_DIR . '/inc/admin-bar.php';

        if (
            /** @psalm-suppress UndefinedFunction */
            ! has_action('admin_bar_menu', 'apbct_admin__admin_bar__add_structure') &&
            ! has_action('admin_bar_menu', 'spbc_admin__admin_bar__add_structure')
        ) {
            add_action('admin_bar_menu', 'spbc_admin__admin_bar__add_structure', 999);
        }

        add_action('cleantalk_admin_bar__parent_node__before', 'spbc_admin__admin_bar__prepare_counters');
        add_action('cleantalk_admin_bar__add_icon_to_parent_node', 'spbc_admin__admin_bar__prepare_counters');
        // Temporary disable the icon
        // add_filter( 'cleantalk_admin_bar__parent_node__before', 'spbc_admin__admin_bar__add_parent_icon', 10, 1 );
        add_filter('cleantalk_admin_bar__parent_node__after', 'spbc_admin__admin_bar__add_counter', 10, 1);

        add_filter('admin_bar_menu', 'spbc_admin__admin_bar__add_child_nodes', 1000);
        if ( ! $apbct) {
            add_filter('admin_bar_menu', 'spbc_apbct_admin__admin_bar__add_child_nodes', 1001);
        }
    }

    // Admin bar
    add_action('wp_ajax_spbc_get_authorized_admins', 'spbc_get_authorized_admins'); // Counting online users

    // Logs
    add_action('wp_ajax_spbc_show_more_security_logs', 'spbc_show_more_security_logs_callback');
    add_action('wp_ajax_spbc_show_hostname_security_logs', 'spbc_show_hostname_security_logs_callback');
    add_action('wp_ajax_spbc_show_more_security_firewall_logs', 'spbc_show_more_security_firewall_logs_callback');
    add_action('wp_ajax_spbc_tc__filter_ip', 'spbc_tc__filter_ip');

    // Scanner
    add_action('wp_ajax_spbc_scanner_controller_front', array(ScannerQueue::class, 'controllerFront'));
    add_action('wp_ajax_spbc_scanner_load_more_scan_logs', 'spbc_scanner_load_more_scan_logs');
    add_action('wp_ajax_spbc_scanner_save_to_pdf', 'spbc_scanner_save_to_pdf');
    add_action('wp_ajax_spbc_scanner_get_pdf_file_name', 'spbc_scanner_get_pdf_file_name');
    add_action('wp_ajax_spbc_scanner_clear', 'spbc_scanner_clear'); // Debug. Clear the table
    add_action('wp_ajax_spbc_scanner__last_scan_info', 'spbc_scanner__last_scan_info');

    // Scanner buttons
    add_action('wp_ajax_spbc_scanner_file_send', 'spbc_scanner_file_send');
    add_action('wp_ajax_spbc_scanner_file_delete', 'spbc_scanner_file_delete');
    add_action('wp_ajax_spbc_scanner_file_approve', 'spbc_scanner_file_approve');
    add_action('wp_ajax_spbc_scanner_file_view', 'spbc_scanner_file_view');
    add_action('wp_ajax_spbc_scanner_page_view', 'spbc_scanner_page_view');
    add_action('wp_ajax_spbc_scanner_file_replace', 'spbc_scanner_file_replace');
    add_action('wp_ajax_spbc_scanner_file_check_analysis_status', 'spbc_scanner_pscan_check_analysis_status');
    add_action('wp_ajax_spbc_scanner_analysis_log_delete_from_log', 'spbc_scanner_analysis_log_delete_from_log');
    add_action('wp_ajax_spbc_file_cure_ajax_action', 'spbc_file_cure_ajax_action');
    add_action('wp_ajax_spbc_restore_file_from_backup_ajax_action', 'spbc_restore_file_from_backup_ajax_action');

    // Settings
    add_action('wp_ajax_spbc_settings__draw_elements', 'spbc_settings__draw_elements');
    add_action('wp_ajax_spbc_scanner_tab__reload_accordion', 'spbc_field_scanner__show_accordion');

    // SPBC Table
    add_action('wp_ajax_spbc_tbl-action--bulk', array(ListTable::class, 'ajaxBulkActionHandler'));
    add_action('wp_ajax_spbc_tbl-action--row', array(ListTable::class, 'ajaxRowActionHandler'));
    add_action('wp_ajax_spbc_tbl-pagination', array(ListTable::class, 'ajaxPaginationHandler'));
    add_action('wp_ajax_spbc_tbl-sort', array(ListTable::class, 'ajaxSortHandler'));
    add_action('wp_ajax_spbc_tbl-switch', array(ListTable::class, 'ajaxSwitchTable'));
    add_action('wp_ajax_spbc_cure_selected', array(Cure::class, 'cureSelectedAction'));
    add_action('wp_ajax_spbc_restore_selected', array(Cure::class, 'restoreSelectedAction'));

    // Send logs_mscan
    add_action('wp_ajax_spbc_send_traffic_control', 'spbc_send_firewall_logs_ajax_handler', 1, 0);
    add_action('wp_ajax_spbc_send_security_log', 'spbc_send_logs_ajax_handler', 1, 0);

    // UploadChecker. Notification about blocked file.
    add_action('wp_ajax_spbc_check_file_block', array(\CleantalkSP\SpbctWP\Firewall\UploadChecker::class, 'uploadCheckerGetLastBlockInfo'));

    // Backups
    add_action('wp_ajax_spbc_rollback', 'spbc_rollback');
    add_action('wp_ajax_spbc_backup__delete', 'spbc_backup__delete');

    // Misc
    add_action('wp_ajax_spbc_settings__get_description', 'spbc_settings__get_description');
    add_action('wp_ajax_spbc_settings__get_recommendation', 'spbc_settings__get_recommendation');
    add_action('wp_ajax_spbc_settings__check_renew_banner', 'spbc_settings__check_renew_banner');
    add_action('wp_ajax_spbc_sync', 'spbc_sync');
    add_action('wp_ajax_spbc_get_key_auto', 'spbc_get_key_auto');
    add_action('wp_ajax_spbc_update_account_email', 'spbc_settings__update_account_email');
    add_action('wp_ajax_spbc_create_support_user', 'spbc_settings__spbc_create_support_user');

    // Confirm the email to activate 2FA
    add_action('wp_ajax_spbc_generate_confirmation_code', 'spbctGenerateAndSendConfirmationCode');
    add_action('wp_ajax_spbc_check_confirmation_code', 'spbctCheckConfirmationCode');

    // Auto-adding admin IP to the whitelist
    add_action('wp_ajax_spbc_private_list_add', 'spbc_private_list_add');

    // Change role
    add_action('wp_ajax_spbc_change_role_template', 'spbc_change_role_template');
    add_action('wp_ajax_spbc_change_role', 'spbc_change_role');

    // Settings Templates
    if (
        ! $spbc->data['wl_mode_enabled'] &&
        $spbc->is_mainsite ||
        $spbc->ms__work_mode != 2
    ) {
        new CleantalkSettingsTemplates($spbc->api_key);
    }

    // Getting key for daughter blogs once
    if (!$spbc->is_mainsite && $spbc->ms__work_mode == 1 && $spbc->ms__hoster_api_key && $spbc->data['ms__key_tries'] < 3) {
        $spbc->data['ms__key_tries']++;
        $spbc->save('data');
        spbc_set_api_key();
    }

    // Drop debug data
    if (Post::getString('spbc_debug__drop')) {
        $spbc->deleteOption('debug', 'use_prefix');
    }

    // Drop debug data
    if (Post::getString('spbc_debug__check_connection')) {
        $result = spbc_test_connection();
        spbc_log($result);
    }

    // Set cookie to detect admin on public pages
    if (
            ! empty($spbc->settings['data__set_cookies']) &&
            (
                ! Cookie::getString('spbc_admin_logged_in') ||
                Cookie::getString('spbc_admin_logged_in') !== md5($spbc->data['salt'] . 'admin' . get_option('home'))
            ) &&
            is_admin() &&
            current_user_can('manage_options')
    ) {
        Cookie::set('spbc_admin_logged_in', md5($spbc->data['salt'] . 'admin' . get_option('home')), time() + 86400 * 365, '/');
    }

    if ($spbc->settings['check_pass__enable']) {
        add_filter('manage_users_columns', 'spbc_users_list_pass_check_column');
        add_action('wp_ajax_spbc_check_pass_leak', [UsersPassCheckHandler::class, 'checkPassLeak']);
    }
}

/**
 * Add column to users list
 * @param array $columns
 * @return array
 */
function spbc_users_list_pass_check_column($columns)
{
    $columns['spbc_pass_check'] = __('Password Leak', 'security-malware-firewall');

    return $columns;
}

/**
 * Manage links in plugins list
 * @return array
 */
function spbc_plugin_action_links($links)
{
    $settings_link = is_network_admin()
        ? '<a href="settings.php?page=spbc">' . __('Settings') . '</a>'
        : '<a href="options-general.php?page=spbc">' . __('Settings') . '</a>';

    array_unshift($links, $settings_link); // before other links

    // Add "Start scan" link only of the main site
    if (is_main_site()) {
        $start_scan = is_network_admin()
            ? '<a href="settings.php?page=spbc&spbc_tab=scanner&spbc_target=spbc_perform_scan&spbc_action=click">' . __('Start scan') . '</a>'
            : '<a href="options-general.php?page=spbc&spbc_tab=scanner&spbc_target=spbc_perform_scan&spbc_action=click">' . __('Start scan') . '</a>';
        array_unshift($links, $start_scan); // before other links
    }

    $trial = spbc_badge__get_premium(false);
    if ( ! empty($trial)) {
        array_unshift($links, $trial);
    }

    return $links;
}

add_action('after_plugin_row', 'spbc_plugin_list_show_vulnerability', 20, 3);
function spbc_plugin_list_show_vulnerability($plugin_file, $plugin_data, $_status)
{
    global $spbc;
    $do_show = (
            isset($spbc->settings['vulnerability_check__enable_cron'], $spbc->settings['vulnerability_check__warn_on_modules_pages']) &&
            $spbc->settings['vulnerability_check__enable_cron'] == true &&
            $spbc->settings['vulnerability_check__warn_on_modules_pages'] == true &&
            isset($plugin_data['slug']) // Only plugins which have slug (from wordpress catalog) need to check
    );

    if ($do_show) {
        $plugin_slug = isset($plugin_data['slug']) ? $plugin_data['slug'] : sanitize_title($plugin_data['Name']);
        $plugin_version = ! empty($plugin_data['Version']) ? $plugin_data['Version'] : '';
        $plugin_report = VulnerabilityAlarm::checkPluginVulnerabilityStatic($plugin_slug, $plugin_version);
        if ( $plugin_report ) {
            echo VulnerabilityAlarm::getPluginAlarmHTML($plugin_file, $plugin_report);
        }
    }
}

if (isset($spbc->settings['vulnerability_check__show_reports']) && $spbc->settings['vulnerability_check__show_reports'] == true) {
    add_filter('plugins_api_result', 'spbc_plugin_install_show_safety', 10, 3);
    add_filter('plugin_row_meta', 'spbc_plugin_list_show_safety', 10, 3);
}

/**
 * Show safety link for plugins
 * @param array $links
 * @param string $file
 * @param array $plugin_data
 * @return array
 * @psalm-suppress UnusedParam
 */
function spbc_plugin_list_show_safety($links, $file, $plugin_data)
{
    global $spbc;

    if (!isset($plugin_data, $plugin_data['slug'], $plugin_data['Version'])) {
        return $links;
    }

    $slug = $plugin_data['slug'];
    $version = $plugin_data['Version'];

    $report = VulnerabilityAlarmService::getItemReportStatic($slug, $version, true, false);

    $do_show = (
        isset($spbc->settings['vulnerability_check__show_reports']) &&
        $spbc->settings['vulnerability_check__show_reports'] == true
    );

    if ($do_show && isset($report, $report->psc, $report->id, $slug)) {
        $links[] = sprintf(
            '<a href="https://research.cleantalk.org/reports/app/%s#%s" target="_blank" title="%s">%s</a>',
            $slug,
            $report->id,
            $report->psc,
            __('Security certified plugin', 'security-malware-firewall')
        );
    }

    return $links;
}

function spbc_plugin_install_show_safety($res, $action, $_args)
{
    global $spbc;
    $do_show = (
        isset($spbc->settings['vulnerability_check__test_before_install']) &&
        $spbc->settings['vulnerability_check__test_before_install'] == true
    );
    if ($do_show && $action === 'query_plugins' && ! ($res instanceof WP_Error) && is_array($res->plugins) && count($res->plugins) ) {
        $safe_plugins = VulnerabilityAlarm::getSafePlugins($res->plugins);
        if ( !empty($safe_plugins) ) {
            foreach ($safe_plugins as $safe_plugin_data) {
                if ( ! empty($safe_plugin_data['psc']) ) {
                    add_filter('plugin_install_action_links', function ($action_links, $plugin) use ($safe_plugin_data) {
                        $plugin_slug = $safe_plugin_data['slug'];
                        $plugin_id = $safe_plugin_data['id'];
                        /**
                         * @var PluginReport $report_dto
                         */
                        $report_dto = $safe_plugin_data['report_object'];
                        if ( $plugin['slug'] === $plugin_slug) {
                            $badge = VulnerabilityAlarm::showSafeBadge(
                                '',
                                $plugin['slug'],
                                $plugin_id,
                                $safe_plugin_data['psc'],
                                $report_dto->research_url
                            );
                            if (!empty($badge)) {
                                $action_links[] = $badge;
                            }
                        }
                        return $action_links;
                    }, 10, 2);
                }
            }
        }
    }
    return $res;
}

add_action('wp_ajax_spbc_check_vulnerability_list', 'spbc_theme_list_show_vulnerability');
function spbc_theme_list_show_vulnerability()
{
    spbc_check_ajax_referer('spbc_secret_nonce', 'security');

    try {
        if (isset($_POST['list'])) {
            $list = $_POST['list'];

            $data = [
                'success' => true,
                'list' => [],
            ];

            foreach ($list as $installed_theme) {
                $theme_slug = isset($installed_theme['slug']) ? $installed_theme['slug'] : '';
                $theme_version = ! empty($installed_theme['version']) ? $installed_theme['version'] : '';
                if ( isset($theme_slug, $theme_slug) ) {
                    $theme_report = VulnerabilityAlarm::checkThemeVulnerabilityStatic($theme_slug, $theme_version);
                    if ( $theme_report ) {
                        $vulnerable_theme_data = array(
                            'slug' => $installed_theme['slug'],
                            'msg' => VulnerabilityAlarm::getThemeAlarmHTML($theme_report)
                        );
                        $data['list'][] = $vulnerable_theme_data;
                    }
                }
            }
            wp_send_json($data);
        }
    } catch (\Exception $_exception) {
        wp_send_json_error(esc_html__('Error: Something is going wrong.', 'security-malware-firewall'));
    }
}

if (isset($spbc->settings['vulnerability_check__show_reports']) && $spbc->settings['vulnerability_check__show_reports'] == true) {
    add_action('wp_ajax_spbc_check_vulnerability_install', 'spbc_themes_install_show_safety');
}
function spbc_themes_install_show_safety()
{
    spbc_check_ajax_referer('spbc_secret_nonce', 'security');

    try {
        if (isset($_POST['list'])) {
            $list = $_POST['list'];
            $safe_themes_reports = VulnerabilityAlarm::getSafeThemesViaApi($list);
            $data = [
                'success' => true,
                'list' => [],
            ];

            foreach ($list as $installed_theme) {
                foreach ($safe_themes_reports as $report) {
                    if (isset($installed_theme['psc']) && isset($installed_theme['slug']) && $installed_theme['slug'] === $report->slug) {
                        $theme_id = !empty($installed_theme['slug']) ? $installed_theme['slug'] : '';
                        /**
                         * @var ThemeReport $report_dto
                         */
                        $report_dto = $report['report_object'];
                        $safe_theme_data = array(
                            'slug' => $installed_theme['slug'],
                            'msg' => VulnerabilityAlarm::showSafeBadge(
                                'theme',
                                $installed_theme['slug'],
                                $theme_id,
                                $installed_theme['psc'],
                                $report_dto->research_url
                            )
                        );
                        $data['list'][] = $safe_theme_data;
                    }
                }
            }
            wp_send_json($data);
        }
    } catch (\Exception $_exception) {
        wp_send_json_error(esc_html__('Error: Something is going wrong.', 'security-malware-firewall'));
    }
}

add_filter('upgrader_post_install', 'spbc_plugin_install__run_vulnerability_check_cron', 999, 3);

/**
 * Hook wrapper for upgrader_post_install. Run Vulnerability request to research.cleantalk.org to fill the vulnerabilities database
 * when a plugin installation performed.
 * @param $response
 * @param $hook_extra
 * @param $result
 * @return void
 * @psalm-suppress UnusedParam
 */
function spbc_plugin_install__run_vulnerability_check_cron($response, $hook_extra, $result)
{
    if (
            isset($hook_extra, $hook_extra['type'], $hook_extra['action']) &&
            $hook_extra['type'] === 'plugin' &&
            $hook_extra['action'] === 'install'
    ) {
        Cron::updateTask('check_vulnerabilities', 'spbc_security_check_vulnerabilities', 86400, time() + 30);
    }
}

/**
 * Manage links and plugins page
 * @return array
 */
function spbc_plugin_links_meta($meta, $plugin_file)
{
    global $spbc;

    $plugin_name = SPBC_NAME ?: 'Security by CleanTalk';

    //Return if it's not our plugin
    if (strpos($plugin_file, SPBC_PLUGIN_BASE_NAME) === false) {
        return $meta;
    }

    if ($spbc->data["wl_mode_enabled"]) {
        $meta   = array_slice($meta, 0, 1);
        $meta[] = "<script " . (class_exists('Cookiebot_WP') ? 'data-cookieconsent="ignore"' : '') . ">
        function changedPluginName(){
            document.addEventListener('DOMContentLoaded', function() {
                jQuery('.plugin-title strong').each(function(i, item){
                    if (jQuery(item).html() == '{$plugin_name}') {
                        jQuery(item).html('{$spbc->data["wl_brandname"]}' + '&nbsp; Security');
                    }
                });
                jQuery('.plugin-description p').each(function(i, item){
                    if (jQuery(item).html().indexOf('Security &amp; Malware scan by CleanTalk') >= 0) {
                        jQuery(item).html(jQuery(item).html().replace('CleanTalk','{$spbc->data["wl_brandname"]}'));
                    }
                });
                jQuery('#security-malware-firewall-update p').each(function(i, item){
                    if (jQuery(item).html().indexOf('Security by CleanTalk') >= 0) {
                        jQuery(item).html(jQuery(item).html().replace('CleanTalk','{$spbc->data["wl_brandname"]}'));
                    }
                });
            });
        }
        changedPluginName();
		jQuery( document ).ajaxComplete(function() {
            changedPluginName();
        });
		</script>";

        if (!empty($spbc->data['wl_support_faq'])) {
            $meta[] = '<a href="' . esc_url($spbc->data['wl_support_faq']) . '" class="spbc_meta_links spbc_faq_links">' . __('FAQ') . '</a>';
        }

        return $meta;
    }

    if (substr(get_locale(), 0, 2) != 'en') {
        $meta[] = '<a class="spbc_meta_links spbc_translate_links" href="'
                  . sprintf('https://translate.wordpress.org/locale/%s/default/wp-plugins/security-malware-firewall', substr(get_locale(), 0, 2))
                  . '" target="_blank">'
                  . __('Translate', 'security-malware-firewall')
                  . '</a>';
    }
    $meta[] = '<a class="spbc_meta_links spbc_faq_links" href="https://wordpress.org/plugins/security-malware-firewall/faq/" target="_blank">' . __('FAQ', 'security-malware-firewall') . '</a>';
    $meta[] = '<a class="spbc_meta_links spbc_support_links" href="https://wordpress.org/support/plugin/security-malware-firewall" target="_blank">' . __('Support', 'security-malware-firewall') . '</a>';

    return $meta;
}

function spbc_admin_add_script_attribute($tag, $handle)
{
    $async_scripts = array(
        //'jquery-ui',
        //'spbc-common-js',
        'spbc-scannerplugin-js',
        'spbc-scaner-events-js',
        'spbc-scaner-callbacks-js',
    );

    $defer_scripts = array(
        'spbc-settings-js',
        'spbc-scaner-js',
    );

    if (in_array($handle, $async_scripts)) {
        return str_replace(' src', ' async="async" src', $tag);
    } elseif (in_array($handle, $defer_scripts)) {
        return str_replace(' src', ' defer="defer" src', $tag);
    } else {
        return $tag;
    }
}

/*
 * Logging admin action
*/
function spbc_admin_log_action()
{
    $user = wp_get_current_user();
    $secure_cookies = array();

    try {
        $secure_cookies = spbc_get_secure_cookies();
    } catch (Exception $e) {
        // @ToDo for the handling failing cookies testing
    }

    if ( ! empty($secure_cookies)) {
        try {
            spbc_write_timer($secure_cookies);
        } catch (Exception $e) {
            error_log($e->getMessage());
        }
    }

    if (isset($user->ID) && $user->ID > 0) {
        $roles = (is_array($user->roles) && ! empty($user->roles) ? reset($user->roles) : null); // Takes only first role.
        $action = spbc_parse_action_from_admin_page_uri(Server::get('REQUEST_URI', null, 'url'));

        $log_id = spbc_auth_log(array(
            'username' => $user->get('user_login'),
            'event'    => isset($action["action_event"]) ? $action["action_event"] : 'view',
            'page'     => Server::get('REQUEST_URI', null, 'url'),
            'blog_id'  => get_current_blog_id(),
            'roles'    => $roles
        ));
    }

    // Setting timer with event ID
    if (isset($log_id)) {
        $cookies_arr = array(
            'spbc_log_id' => $log_id,
            'spbc_timer'  => time()
        );

        try {
            spbc_set_secure_cookies($cookies_arr);
        } catch (Exception $e) {
            error_log($e->getMessage());
        }
    }

    return;
}

/**
 * Calculates and writes page time to DB
 *
 * @param $timer               array of the row like array('spbc_log_id' => $log_id, 'spbc_timer'  => time())
 *
 * @throws Exception           throws if the query faults
 */
function spbc_write_timer($timer)
{
    global $wpdb;

    if ( ! isset($timer['log_id'], $timer['timer'])) {
        throw new Exception('SPBC: Can not update the logs table (cookies was not provided).');
    }

    $result = $wpdb->update(
        SPBC_TBL_SECURITY_LOG,
        array('page_time' => (string) (time() - $timer['timer'])),
        array('id' => $timer['log_id']),
        '%s',
        '%s'
    );

    if (false === $result) {
        throw new Exception('SPBC: Can not update the logs table.');
    }
}

function spbc_badge__get_premium($print = true, $make_it_right = false)
{
    global $spbc;
    $out = '';

    if ($spbc->data['license_trial'] == 1 && ! empty($spbc->user_token) && ! $spbc->data["wl_mode_enabled"] ) {
        $inner_html = __('Get premium', 'security-malware-firewall');
        $link_tag = linkConstructor::buildRenewalLinkATag(
            $spbc->user_token,
            $inner_html,
            4,
            $make_it_right ? 'renew_top_info' : 'renew_plugins_listing'
        );
        if ($make_it_right) {
            $out = __('Make it right!', 'security-malware-firewall') . '<span style="display: inline; margin-left: 5px;">' . $link_tag . '</span>';
        } else {
            $out = '<b style="display: inline-block; margin-top: 10px;">' . $link_tag . '</b>';
        }
    }

    if ($print) {
        print($out);
    }

    return $out;
}

/**
 * Setting up secure cookies
 *
 * @param $cookies            array of the cookies to be set
 *
 * @throws Exception          error_log errors of setting cookies
 */
function spbc_set_secure_cookies($cookies)
{
    if (headers_sent()) {
        throw new Exception('SPBC: Secure cookies does not set (headers already sent).');
    }

    if (!is_array($cookies) || empty($cookies)) {
        throw new Exception('SPBC: Secure cookies does not set (there are not cookies).');
    }

    global $spbc;
    $domain  = parse_url(get_option('home'), PHP_URL_HOST);
    $success = array();

    $cookie_test_value = array(
        'cookies_names' => array(),
        'check_value'   => $spbc->settings['spbc_key'],
    );

    foreach ($cookies as $cookie_name => $cookie_value) {
        $success[] = Cookie::set($cookie_name, $cookie_value, 0, '/', $domain, false, true);
        $cookie_test_value['cookies_names'][] = $cookie_name;
        $cookie_test_value['check_value']     .= $cookie_value;
    }

    $cookie_test_value['check_value'] = md5($cookie_test_value['check_value']);
    $success[]                        = Cookie::set('spbc_cookies_test', $cookie_test_value, 0, '/', $domain, false, true);

    if (in_array(false, $success)) {
        throw new Exception('SPBC: Secure cookies does not set (setcookie error).');
    }
}

/**
 * Getting the secure cookies
 *
 * @return array       array of cookies
 * @throws Exception   throws if our $_COOKIE not set
 */
function spbc_get_secure_cookies()
{
    $secure_cookies = array();

    if (Cookie::getString('spbc_cookies_test')) {
        $cookie_test = Cookie::getString('spbc_cookies_test');

        if (!is_array($cookie_test)) {
            throw new Exception('SPBC: Secure cookies does not get (there are not cookies).');
        }

        $check_secure_cookies = spbc_validate_secure_cookies($cookie_test);

        if (!$check_secure_cookies) {
            throw new Exception('SPBC: Secure cookies does not get (cookies was malformed).');
        } else {
            foreach ($cookie_test['cookies_names'] as $cookie_name) {
                if (Cookie::getString($cookie_name) !== '') {
                    $cookie_name_prepared                    = str_replace('spbc_', '', $cookie_name);
                    $secure_cookies[ $cookie_name_prepared ] = Cookie::getString($cookie_name);
                }
            }
        }
    }

    return $secure_cookies;
}

/**
 * Check if cookies was not malformed
 *
 * @param $cookies_arr    array of cookies
 *
 * @return bool           true|false
 */
function spbc_validate_secure_cookies($cookies_arr)
{
    global $spbc;

    $check_string = $spbc->settings['spbc_key'];
    foreach ($cookies_arr['cookies_names'] as $cookie_name) {
        $check_string .= Cookie::getString($cookie_name);
    }
    unset($cookie_name);

    if ($cookies_arr['check_value'] == md5($check_string)) {
        return true;
    } else {
        return false;
    }
}

function spbc_get_authorized_admins($direct_call = false)
{
    if ( ! $direct_call) {
        spbc_check_ajax_referer('spbc_secret_nonce', 'security');
    }

    $users = \CleantalkSP\Monitoring\User::getAdminsOnline();

    if ($direct_call) {
        return $users;
    } else {
        header('Content-Type: application/json');
        die(json_encode(array('count' => count($users), 'users' => $users)));
    }
}

/**
 * Action for shuffle authentication unique keys and salts
 */
add_action('wp_ajax_spbc_action_shuffle_salts', 'spbc_action_shuffle_salts');

function spbc_action_shuffle_salts()
{
    spbc_check_ajax_referer('spbc_secret_nonce', 'security');

    global $spbc;
    $salts_array = array(
        'AUTH_KEY',
        'SECURE_AUTH_KEY',
        'LOGGED_IN_KEY',
        'NONCE_KEY',
        'AUTH_SALT',
        'SECURE_AUTH_SALT',
        'LOGGED_IN_SALT',
        'NONCE_SALT',
    );

    $http_salts     = wp_remote_get('https://api.wordpress.org/secret-key/1.1/salt/');
    $returned_salts = wp_remote_retrieve_body($http_salts);
    $new_salts      = explode("\n", $returned_salts);

    if (empty($new_salts[0])) {
        wp_send_json_error(esc_html__('Error: Something went wrong. Please, try again.', 'security-malware-firewall'));
    }

    // Adding filters for additional salts.
    $new_salts   = apply_filters('spbc_new_salts_filter', $new_salts);
    $salts_array = apply_filters('spbc_salts_array_filter', $salts_array);

    $shuffle_salts_result = spbc_write_salts($salts_array, $new_salts);

    if (!$shuffle_salts_result) {
        wp_send_json_error(esc_html__('Error: Something went wrong. Please, try again.', 'security-malware-firewall'));
    }

    $spbc->settings['there_was_signature_treatment'] = 0;
    $spbc->save('settings');

    //drop spbc_is_logged_in cookie to prevent ЕС and BFP incorrect work
    Cookie::set('spbc_is_logged_in', '0', time() - 30, '/');

    wp_send_json_success();
}

add_action('wp_ajax_spbc_action_adjust_change', 'spbc_action_adjust_change');

function spbc_action_adjust_change()
{
    spbc_check_ajax_referer('spbc_secret_nonce', 'security');

    if (in_array(Post::getString('adjust'), array_keys(AdjustToEnvironmentHandler::SET_OF_ADJUST))) {
        $adjust = Post::getString('adjust');
        $adjust_class = AdjustToEnvironmentHandler::SET_OF_ADJUST[$adjust];
        $adjust_handler = new AdjustToEnvironmentHandler();
        $adjust_handler->handleOne($adjust_class);
    }

    wp_send_json_success();
}

add_action('wp_ajax_spbc_action_adjust_reverse', 'spbc_action_adjust_reverse');

function spbc_action_adjust_reverse()
{
    spbc_check_ajax_referer('spbc_secret_nonce', 'security');

    if (in_array(Post::getString('adjust'), array_keys(AdjustToEnvironmentHandler::SET_OF_ADJUST))) {
        $adjust = Post::getString('adjust');
        $adjust_class = AdjustToEnvironmentHandler::SET_OF_ADJUST[$adjust];
        $adjust_handler = new AdjustToEnvironmentHandler();
        $adjust_handler->reverseAdjust($adjust_class);
    }

    wp_send_json_success();
}

/**
 * Write salts in wp-config.php
 */
function spbc_write_salts($salts_array, $new_salts)
{
    $config_file = spbc_config_file_path();

    // Not founded wp-config.php
    if ( ! $config_file) {
        return false;
    }

    // Get the current permissions of wp-config.php.
    $config_file_permissions = fileperms($config_file);

    $tmp_config_file = ABSPATH . 'wp-config-temp.php';

    $reading_config = fopen($config_file, 'r');
    $writing_config = fopen($tmp_config_file, 'w');

    while (!feof($reading_config)) {
        $line = fgets($reading_config);
        foreach ($salts_array as $salt_key => $salt_value) {
            if (strripos($line, $salt_value)) {
                $line = $new_salts[ $salt_key ] . "\n";
                unset($salts_array[ $salt_key ]);
            }
        }
        fputs($writing_config, $line);
    }

    fclose($reading_config);
    fclose($writing_config);
    rename($tmp_config_file, $config_file);

    // Keep the original permissions of wp-config.php.
    chmod($config_file, $config_file_permissions);

    return true;
}

/**
 * Get wp-config.php path
 */
function spbc_config_file_path()
{
    $config_file_name = 'wp-config';
    $config_file      = ABSPATH . $config_file_name . '.php';
    $config_file_up   = ABSPATH . '../' . $config_file_name . '.php';

    if (file_exists($config_file) && is_writable($config_file)) {
        return $config_file;
    } elseif (file_exists($config_file_up) && is_writable($config_file_up) && ! file_exists(dirname(ABSPATH) . '/wp-settings.php')) {
        return $config_file_up;
    }

    return false;
}

function spbc_set_malware_scan_warns()
{
    global $wpdb, $spbc;
    $query = 'SELECT COUNT(*)
        FROM ' . SPBC_TBL_SCAN_FILES . ' 
        WHERE (STATUS = "INFECTED" AND severity = "CRITICAL") 
        OR STATUS = "DENIED_BY_CLOUD"
        OR STATUS = "DENIED_BY_CT"';
    $critical_count = (int)$wpdb->get_var($query);

    $query = 'SELECT COUNT(*)
        FROM ' . SPBC_TBL_SCAN_FILES . ' 
        WHERE weak_spots LIKE "%SIGNATURES%"
        OR STATUS = "DENIED_BY_CLOUD"';
    $signatures_count = (int)$wpdb->get_var($query);

    $query = 'SELECT COUNT(*) 
        FROM ' . SPBC_TBL_SCAN_FRONTEND . ' 
        WHERE approved IS NULL OR approved = 0';
    $frontend_count = (int)$wpdb->get_var($query);

    $query = 'SELECT COUNT(*) 
        FROM ' . SPBC_TBL_SCAN_FILES . ' 
        WHERE pscan_status = "DANGEROUS" OR 
        (status = "DENIED_BY_CT" AND last_sent IS NOT NULL)';
    $analysis_has_dangerous = (int)$wpdb->get_var($query) > 0;

    $query = 'SELECT COUNT(*) 
        FROM ' . SPBC_TBL_SCAN_FILES . ' 
        WHERE last_sent IS NOT NULL
        AND (pscan_processing_status <> "DONE")';
    $analysis_has_uncheked = (int)$wpdb->get_var($query) <> 0;

    $oscron_has_dangerous = OsCronTasksStorage::getCountOfDangerousTasks();

    $triggers_has_dangerous = DBTriggerService::countTriggersStorage();

    //// Sync disallow file edit setting with FileEditorDisabler
    FileEditorDisabler::syncDisallowFileEditBySettings($spbc->settings, $critical_count);

    $spbc->data['display_scanner_warnings'] = array(
        'critical' => $critical_count,
        'signatures' => $signatures_count,
        'frontend' => $frontend_count,
        'analysis' => $analysis_has_dangerous,
        'oscron' => $oscron_has_dangerous,
        'db_triggers' => $triggers_has_dangerous,
        'analysis_all_safe' => !$analysis_has_uncheked && !$analysis_has_dangerous && !$oscron_has_dangerous && !$triggers_has_dangerous,
        'warn_on_admin_bar' => $critical_count || $frontend_count || $analysis_has_dangerous || $oscron_has_dangerous || $triggers_has_dangerous,
    );
    $spbc->notice_critical_files_warning = !empty($critical_count);
    $spbc->save('data');
}

/**
 * Change the plugin description on all plugins page.
 * @param $all_plugins
 * @return array
 */
function spbc_admin__change_plugin_description($all_plugins)
{
    global $spbc;
    if (
        $spbc->data["wl_mode_enabled"] &&
        isset($all_plugins['security-malware-firewall/security-malware-firewall.php']) &&
        $spbc->data["wl_plugin_description"]
    ) {
        $all_plugins['security-malware-firewall/security-malware-firewall.php']['Description'] = $spbc->data["wl_plugin_description"];
    }
    return $all_plugins;
}


/**
 * Add the statistics widget to the dashboard.
 * @return void
 * @psalm-suppress UndefinedFunction
 */
function spbc_dashboard_statistics_widget()
{
    global $spbc;

    $actual_plugin_name = SPBC_NAME;
    if (isset($spbc->data['wl_brandname']) && $spbc->data['wl_brandname'] !== SPBC_NAME) {
        $actual_plugin_name = $spbc->data['wl_brandname'];
    }

    if ( current_user_can('activate_plugins') ) {
        wp_add_dashboard_widget(
            'spbc_dashboard_statistics_widget',
            $actual_plugin_name,
            'spbc_dashboard_statistics_widget_output'
        );
    }
}

/**
 * Generate statistics widget output HTML.
 * @param $_post
 * @param $_callback_args
 * @return void
 */
function spbc_dashboard_statistics_widget_output($_post, $_callback_args)
{
    global $spbc, $current_user;

    $actual_plugin_name = SPBC_NAME;
    if (isset($spbc->data['wl_brandname']) && $spbc->data['wl_brandname'] !== SPBC_NAME) {
        $actual_plugin_name = $spbc->data['wl_brandname'];
    }

    echo "<div id='spbc_widget_wrapper'>";
    ?>
    <div class='spbc_widget_top_links'>
        <img src="<?php echo Escape::escUrl(SPBC_PATH . '/images/preloader.gif'); ?>" class='spbc_preloader'>
        <?php

        if ($spbc->data['display_scanner_warnings']['critical'] > 0) {
            echo (spbc__get_accordion_tab_info_block_html('critical-for-widget'));
        }

        echo '<div style="display: flex; align-self: end;">';
        echo sprintf(
            __("%sRefresh%s", 'security-malware-firewall'),
            "<a href='#spbc_widget' class='spbc_widget_refresh_link'>",
            "</a>"
        ); ?>
        <?php
        echo sprintf(
            __("%sConfigure%s", 'security-malware-firewall'),
            "<a href='{$spbc->settings_link}' class='spbc_widget_settings_link'>",
            "</a>"
        );
        echo '</div>';
        ?>
    </div>
    <form id='spbc_refresh_form' method='POST' action='#spbc_widget'>
        <input type='hidden' name='spbc_brief_refresh' value='1'>
    </form>
    <h4 class='spbc_widget_block_header' style='margin-left: 12px;'><?php
        _e('7 days Security FireWall and Bruteforce stats', 'security-malware-firewall'); ?></h4>
    <div class='spbc_widget_block spbc_widget_chart_wrapper'>
        <canvas id='spbc_widget_chart' ></canvas>
    </div>
    <h4 class='spbc_widget_block_header'><?php
        _e('10 last actions in WP Dashboard', 'security-malware-firewall'); ?></h4>
    <hr class='spbc_widget_hr'>
    <?php
    // todo if new brand brief method will be implemented, adopt this scum
    if (
        ! spbc_api_key__is_correct() ||
        (isset($spbc->data['brief_data']['error_no']) && $spbc->data['brief_data']['error_no'] == 6)
    ) {
        ?>
        <div class='spbc_widget_block'>
            <form action='<?php
            echo $spbc->settings_link; ?>' method='POST'>
                <h2 class='spbc_widget_activate_header'><?php
                    _e('Get Access key to activate Security protection!', 'security-malware-firewall'); ?></h2>
                <input class='spbc_widget_button spbc_widget_activate_button' type='submit' name='get_apikey_auto'
                       value='ACTIVATE'/>
            </form>
        </div>
        <?php
    } elseif ( ! empty($spbc->data['brief_data']['error']) ) {
        echo '<div class="spbc_widget_block">'
            . '<h2 class="spbc_widget_activate_header">'
            . sprintf(
                __('Something went wrong! Error: "%s".', 'security-malware-firewall'),
                "<u>{$spbc->brief_data['error']}</u>"
            )
            . '</h2>';
        if ( $spbc->user_token && ! $spbc->white_label ) {
            echo '<h2 class="spbc_widget_activate_header">'
                . __('Please, visit your Dashboard.', 'security-malware-firewall')
                . '</h2>'
                . '<a target="_blank" href="https://cleantalk.org/my?user_token=' . $spbc->user_token . '&cp_mode=spbc">'
                . '<input class="spbc_widget_button spbc_widget_activate_button spbc_widget_resolve_button" type="button" value="VISIT CONTROL PANEL">'
                . '</a>';
        }
        echo '</div>';
    }

    if ( spbc_api_key__is_correct() && empty($spbc->data['brief_data']['error']) ) {
        ?>
        <div class='spbc_widget_block'>
            <table cellspacing="0">
                <tr>
                    <th><?php
                        _e('Date', 'security-malware-firewall'); ?></th>
                    <th><?php
                        _e('IP', 'security-malware-firewall'); ?></th>
                    <th><?php
                        _e('Login', 'security-malware-firewall'); ?></th>
                    <th><?php
                        _e('Action', 'security-malware-firewall'); ?></th>
                </tr>
                <?php
                foreach ( $spbc->brief_data['last_actions'] as $val ) { ?>
                    <tr>
                        <td><?php
                            echo Escape::escHtml($val['date']); ?></td>

                        <td><?php
                            echo Escape::escHtml($val['ip']); ?></td>

                        <td><?php
                            echo Escape::escHtml($val['login']); ?></td>

                        <td><a class="spbc_auto_link" title="<?php echo Escape::escHtml($val['action_url']) ?>"><?php
                            echo Escape::escHtml($val['action_event']); ?></td>
                    </tr>
                    <?php
                } ?>
            </table>
            <?php
            if ( $spbc->user_token && ! $spbc->data["wl_mode_enabled"] ) { ?>
                <a target='_blank' href='https://cleantalk.org/my?user_token=<?php
                echo Escape::escHtml($spbc->user_token); ?>&cp_mode=security'>
                    <input class='spbc_widget_button' id='spbc_widget_button_view_all' type='button' value='View all'>
                </a>
                <?php
            } ?>
        </div>

        <?php
    }
    // Notice at the bottom
    if ( isset($current_user) && in_array('administrator', $current_user->roles) ) {
        $brief_data_total_count = $spbc->data['brief_data']['total_count'];
        if ( !empty($brief_data_total_count) && $brief_data_total_count > 0 ) {
            echo '<div class="spbc_widget_wprapper_total_blocked">'
                . ($spbc->data["wl_mode_enabled"] ? '' : '<img src="' . SPBC_PATH . '/images/logo_small.png" class="spbc_widget_small_logo"/>')
                . '<span title="'
                . sprintf(
                /* translators: %s: Number of spam messages */
                    __(
                        '%s%s%s has blocked %s attacks for all time. The statistics are automatically updated every 24 hours.',
                        'security-malware-firewall'
                    ),
                    ! $spbc->data["wl_mode_enabled"] ? '<a href="https://cleantalk.org/my/?user_token=' . $spbc->user_token . '&utm_source=wp-backend&utm_medium=dashboard_widget&cp_mode=spbc" target="_blank">' : '',
                    $actual_plugin_name,
                    ! $spbc->data["wl_mode_enabled"] ? '</a>' : '',
                    '<b>' . number_format($brief_data_total_count, 0, ',', ' ') . '</b>'
                )
                . '</span>'
                . (! $spbc->white_label && ! $spbc->data["wl_mode_enabled"]
                    ? '<br><br>'
                    . '<b style="font-size: 16px;">'
                    . sprintf(
                        __('Do you like CleanTalk? %sPost your feedback here%s.', 'security-malware-firewall'),
                        '<u><a href="https://wordpress.org/support/plugin/security-malware-firewall/reviews/#new-post" target="_blank">',
                        '</a></u>'
                    )
                    . '</b>'
                    : ''
                )
                . '</div>';
        }
    }
    echo '</div>';
}
