<?php
/**
 * Code related to displaying/managing vulnerabilities information.
 *
 * PHP version 5
 *
 * @category   Library
 * @package    Sucuri
 * @subpackage SucuriScanner
 * @author     Sucuri
 * @license    https://www.gnu.org/licenses/gpl-2.0.txt GPL2
 * @link       https://wordpress.org/plugins/sucuri-scanner
 */

if (!defined('SUCURISCAN_INIT') || SUCURISCAN_INIT !== true) {
    if (!headers_sent()) {
        /* Report invalid access if possible. */
        header('HTTP/1.1 403 Forbidden');
    }
    exit(1);
}

/**
 * Class to manage vulnerability data and UI within the Sucuri plugin.
 */
class SucuriScanVulnerability extends SucuriScanSettings
{
    protected static $allowed_keys = array(
        'user_version',
        'is_vulnerable',
        'matched_vulnerabilities',
        'is_cached',
    );

    protected static $allowed_vuln_keys = array(
        'cve_id',
        'description',
        'severity',
        'affected_version',
    );

    protected static function filterAndSanitizeVulnerabilities($vulnerabilities)
    {
        $cleanResponse = array();

        if (!is_array($vulnerabilities)) {
            return $cleanResponse;
        }

        foreach ($vulnerabilities as $vulnerability) {
            if (!is_array($vulnerability)) {
                continue;
            }

            $cleanVulnerability = array();

            foreach (self::$allowed_vuln_keys as $field) {
                if (isset($vulnerability[$field])) {
                    $cleanVulnerability[$field] = sanitize_text_field($vulnerability[$field]);
                }
            }

            $cleanResponse[] = $cleanVulnerability;
        }

        return $cleanResponse;
    }

    protected static function filterAndSanitizeResponse($data)
    {
        $cleanResponse = array();

        if (!is_array($data)) {
            return $cleanResponse;
        }

        foreach (self::$allowed_keys as $key) {
            if (!array_key_exists($key, $data)) {
                // let's ignore keys that are not in the list of allowed keys
                continue;
            }

            if ($key === 'matched_vulnerabilities') {
                $cleanResponse[$key] = self::filterAndSanitizeVulnerabilities($data[$key]);
            } else {
                if (is_bool($data[$key])) {
                    $cleanResponse[$key] = filter_var($data[$key], FILTER_VALIDATE_BOOLEAN, array("flags" => FILTER_NULL_ON_FAILURE));
                } elseif (is_string($data[$key])) {
                    $cleanResponse[$key] = sanitize_text_field($data[$key]);
                }
            }
        }

        return $cleanResponse;
    }

    /**
     * Render or process the vulnerabilities dashboard panel.
     *
     * @return string HTML output for the vulnerabilities panel.
     */
    public static function renderVulnerabilitiesPanelAjax()
    {
        $output = array();

        if (SucuriscanRequest::post('form_action') !== 'vulnerabilities_scan_core_php') {
            return;
        }

        $phpVersion = PHP_VERSION;
        $wpVersion  = get_bloginfo('version');

        $phpInfo  = SucuriScanAPI::getPHPVulnerabilities($phpVersion);
        $coreInfo = SucuriScanAPI::getWordPressCoreVulnerabilities($wpVersion);

        if (isset($phpInfo['error']) && isset($coreInfo['error'])) {
            return wp_send_json_error($phpInfo['error']);
        }

        $output['PHPVulnerabilities']         = self::filterAndSanitizeResponse($phpInfo);
        $output['WordPressCoreVulnerabilities'] = self::filterAndSanitizeResponse($coreInfo);

        return wp_send_json_success($output);
    }

    public static function vulnerabilitiesPluginAjax()
    {
        if (SucuriscanRequest::post('form_action') !== 'plugin_vulnerabilities_scan') {
            return;
        }

        $slug    = SucuriscanRequest::post('slug');
        $version = SucuriscanRequest::post('version');

        $pluginInfo = SucuriScanAPI::getPluginVulnerabilities($slug, $version);

        if (isset($pluginInfo['error'])) {
            return wp_send_json_error($pluginInfo['error']);
        }

        $cleanResponse = self::filterAndSanitizeResponse($pluginInfo);

        return wp_send_json_success($cleanResponse);
    }

    public static function vulnerabilitiesThemeAjax()
    {
        if (SucuriscanRequest::post('form_action') !== 'theme_vulnerabilities_scan') {
            return;
        }

        $slug    = SucuriscanRequest::post('slug');
        $version = SucuriscanRequest::post('version');

        $themeInfo = SucuriScanAPI::getThemeVulnerabilities($slug, $version);

        if (isset($themeInfo['error'])) {
            return wp_send_json_error($themeInfo['error']);
        }

        $cleanResponse = self::filterAndSanitizeResponse($themeInfo);

        return wp_send_json_success($cleanResponse);
    }
}
