634 lines
21 KiB
PHP
634 lines
21 KiB
PHP
<?php
|
|
|
|
class OCVMScan {
|
|
|
|
|
|
private $settings;
|
|
private $scan_data = null;
|
|
private $last_scan_data = array();
|
|
private $items_without_fixed_in = array();
|
|
private $versions = array(
|
|
'wp' => ONECOM_WP_CORE_VERSION,
|
|
'plugins' => array(),
|
|
'themes' => array(),
|
|
);
|
|
private $http_error = false;
|
|
private $http_response;
|
|
private $http_args = array(
|
|
'timeout' => 10,
|
|
'httpversion' => '1.0',
|
|
'compress' => false,
|
|
'decompress' => true,
|
|
'sslverify' => true,
|
|
'stream' => false,
|
|
);
|
|
|
|
public $isNewVulnerabilityExist = false;
|
|
public $isFixVersionMissing = false;
|
|
public function __construct() {
|
|
$this->settings = new OCVMSettings();
|
|
$this->setCron();
|
|
}
|
|
|
|
public function collectVersions(): void {
|
|
|
|
// get all active plugins
|
|
$activePlugins = get_site_option( 'active_plugins' );
|
|
|
|
// active plugins' slug and version
|
|
foreach ( $activePlugins as $activePlugin ) {
|
|
$this->versions['plugins'][] = array(
|
|
'slug' => explode( DIRECTORY_SEPARATOR, $activePlugin )[0],
|
|
'installed_version' => get_plugin_data( WP_PLUGIN_DIR . DIRECTORY_SEPARATOR . $activePlugin, false, false )['Version'],
|
|
);
|
|
}
|
|
|
|
// in case current theme is a child theme then fetch parent theme's details
|
|
if ( get_template_directory() !== get_stylesheet_directory() && ! empty( wp_get_theme()->parent() ) ) {
|
|
$theme = wp_get_theme()->parent();
|
|
} else {
|
|
|
|
// get active theme
|
|
$theme = wp_get_theme();
|
|
}
|
|
// active theme's slug and version
|
|
$this->versions['themes'][] = array(
|
|
'slug' => $theme->template,
|
|
'installed_version' => $theme->version,
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Send versions of all plugins/themes/core
|
|
*/
|
|
public function sendVersions() {
|
|
// stats
|
|
$this->sendVersionStats( $this->versions );
|
|
|
|
// http call
|
|
$this->http_args['user-agent'] = 'WordPress/' . ONECOM_WP_CORE_VERSION . '; ' . home_url();
|
|
$this->http_args['body'] = json_encode( $this->versions );
|
|
$this->http_response = wp_remote_post( $this->settings::ocvm_endpoint, $this->http_args );
|
|
}
|
|
|
|
/**
|
|
* Process http_response
|
|
*/
|
|
public function processResponse() {
|
|
if ( is_wp_error( $this->http_response ) ) {
|
|
if ( isset( $this->http_response->errors['http_request_failed'] ) ) {
|
|
$this->http_error = __( 'Connection timed out', OC_VALIDATOR_DOMAIN );
|
|
} else {
|
|
$this->http_error = $this->http_response->get_error_message();
|
|
}
|
|
} else {
|
|
if ( wp_remote_retrieve_response_code( $this->http_response ) !== 200 ) {
|
|
$this->http_error = '(' . wp_remote_retrieve_response_code( $this->http_response ) . ') ' . wp_remote_retrieve_response_message( $this->http_response );
|
|
} else {
|
|
$body = wp_remote_retrieve_body( $this->http_response );
|
|
$body_arr = json_decode( $body, 1 );
|
|
if ( null !== $body_arr['error'] ) {
|
|
error_log( 'Error reported by API endpoint --> ' . $body );
|
|
} else {
|
|
// To handle the case of plugins that are having same slug for free and pro version but different names
|
|
$plugins_array = $body_arr['data']['plugins'] ?? array();
|
|
if ( is_array( $plugins_array ) ) {
|
|
foreach ( $plugins_array as $plugin => $vulnerabilities ) {
|
|
$name = $this->get_name_for_slug( $plugin, 'plugins' );
|
|
foreach ( $vulnerabilities['vulnerabilities'] as $key => $value ) {
|
|
if ( isset( $value['product_name_premium'] ) && '' !== $value['product_name_premium'] && $name !== $value['product_name_premium'] ) {
|
|
error_log( 'vulnerability for the premium version of plugin found removing it..' );
|
|
unset( $plugins_array[ $plugin ]['vulnerabilities'][ $key ] );
|
|
// Check if vulnerabilities array is empty after unset
|
|
if ( empty( $plugins_array[ $plugin ]['vulnerabilities'] ) ) {
|
|
unset( $plugins_array[ $plugin ] );
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$this->scan_data = array_merge(
|
|
array(
|
|
'plugins' => (array) $plugins_array,
|
|
'themes' => (array) $body_arr['data']['themes'],
|
|
'wp' => (array) $body_arr['data']['wp'],
|
|
)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Check if Vulnerability reported by Endpoint
|
|
* If no vulnerabilities, clear existing vulnerabilities in db
|
|
*/
|
|
public function vulnerabilityExists(): bool {
|
|
if (
|
|
empty( $this->scan_data['wp'] ) &&
|
|
empty( $this->scan_data['plugins'] ) &&
|
|
empty( $this->scan_data['themes'] )
|
|
) {
|
|
// Get existing VM data
|
|
$existing_vm_data = $this->settings->get();
|
|
|
|
// if no vulnerability exits now, push existing vulnerability (if any) to VM log as they are fixed (via update, delete, deactivation)
|
|
$fixed_vuls = $existing_vm_data['vulnerabilities'];
|
|
if ( count( $fixed_vuls ) > 0 ) {
|
|
$history_log_obj = new OCVMHistoryLog();
|
|
$history_log_obj->iterateVulnerabilitiesForLog( $fixed_vuls );
|
|
}
|
|
|
|
// As no vulnerability found in this scan, clear existing vulnerabilities (however retain settings)
|
|
$existing_vm_data['vulnerabilities'] = array();
|
|
$this->settings->update( $existing_vm_data );
|
|
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Get FQN of plugin by slug
|
|
* @param $slug string Theme's stylesheet or Plugin's PHP dir name
|
|
* @return string Name of the plugin/theme
|
|
*/
|
|
protected function get_name_for_slug( $slug, $type ): string {
|
|
if ( 'themes' === $type ) {
|
|
// theme headers
|
|
$themeData = wp_get_theme( $slug );
|
|
return $themeData->get( 'Name' );
|
|
}
|
|
|
|
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
$plugin_files = get_plugins( '/' . $slug );
|
|
if ( ! $plugin_files ) {
|
|
return '';
|
|
}
|
|
$plugin_files = array_keys( $plugin_files );
|
|
$plugin_dir = $slug . '/' . reset( $plugin_files );
|
|
$pluginData = get_plugin_data( trailingslashit( WP_PLUGIN_DIR ) . $plugin_dir );
|
|
return $pluginData['Name'];
|
|
}
|
|
|
|
/**
|
|
* Iterator
|
|
*/
|
|
public function arrayIterator( $items, $type = 'plugins' ) {
|
|
|
|
$arr_items = array();
|
|
foreach ( $items as $slug => $vuls ) {
|
|
// find the highest fix version across all the vulnerabilities found for this item
|
|
$arr_items[ $slug ]['fixed_in'] = max( array_column( $vuls['vulnerabilities'], 'fixed_in' ) );
|
|
$arr_items[ $slug ]['name'] = $this->get_name_for_slug( $slug, $type );
|
|
$arr_items[ $slug ] = array_merge( $arr_items[ $slug ], $vuls );
|
|
|
|
// cleanup duplicate vulnerability codes
|
|
$vuls_arr = array();
|
|
foreach ( $arr_items[ $slug ]['vulnerabilities'] as $k => $v ) {
|
|
|
|
//check is fixed version is missing
|
|
if ( $arr_items[ $slug ]['vulnerabilities'][ $k ]['fixed_in'] === '' ) {
|
|
// Store items with missing fixed-in, to prevent repeat mail after update attempt
|
|
if ( ! array_key_exists( $type, $this->items_without_fixed_in ) || ! in_array( $slug, $this->items_without_fixed_in[ $type ] ) ) {
|
|
$this->items_without_fixed_in[ $type ][] = $slug;
|
|
}
|
|
error_log( 'Fixed in missing for ' . $type );
|
|
$this->isFixVersionMissing = true;
|
|
}
|
|
//round cvss score at two decimal points
|
|
$arr_items[ $slug ]['vulnerabilities'][ $k ]['cvss_score'] = sprintf( '%.2f', $arr_items[ $slug ]['vulnerabilities'][ $k ]['cvss_score'] );
|
|
$v['cvss_score'] = sprintf( '%.2f', $v['cvss_score'] );
|
|
|
|
$vuln_type = $v['vuln_type'];
|
|
$fixedIn = $v['fixed_in'];
|
|
|
|
if ( isset( $vuls_arr[ $vuln_type ] ) ) {
|
|
// Compare fixed_in values to keep the one with the higher fixed_in value
|
|
$existingFixedIn = $vuls_arr[ $vuln_type ]['fixed_in'];
|
|
if ( version_compare( $fixedIn, $existingFixedIn, '>' ) ) {
|
|
// Replace the existing vulnerability with the new one
|
|
$vuls_arr[ $vuln_type ] = $v;
|
|
} elseif ( version_compare( $fixedIn, $existingFixedIn, '<=' ) ) {
|
|
unset( $arr_items[ $slug ]['vulnerabilities'][ $k ] );
|
|
|
|
}
|
|
} else {
|
|
$vuls_arr[ $vuln_type ] = $v;
|
|
|
|
}
|
|
}
|
|
// Convert the associative array back to a sequential array
|
|
$arr_items[ $slug ]['vulnerabilities'] = array_values( $vuls_arr );
|
|
}
|
|
return $arr_items;
|
|
}
|
|
|
|
/**
|
|
* Save vulnerabilities in DB
|
|
*/
|
|
public function saveVulnerabilities() {
|
|
$existing = $this->settings->get();
|
|
$db_data = array();
|
|
$history_log_obj = new OCVMHistoryLog();
|
|
//TODO: delete the entries of plugins/themes/core from $existing data if any of them dont exist now.
|
|
// This is required to clean up stale data and to avoid sending/showing irrelevant mails/notifications.
|
|
if ( ! empty( $this->scan_data['plugins'] ) ) {
|
|
$db_data['plugins'] = $this->arrayIterator( $this->scan_data['plugins'] );
|
|
}
|
|
|
|
if ( ! empty( $this->scan_data['themes'] ) ) {
|
|
$db_data['themes'] = $this->arrayIterator( $this->scan_data['themes'], 'themes' );
|
|
}
|
|
|
|
if ( ! empty( $this->scan_data['wp'] ) && ! empty( $this->scan_data['wp']['vulnerabilities'] ) ) {
|
|
|
|
$temp = array_unique( array_column( $this->scan_data['wp']['vulnerabilities'], 'vuln_type' ) );
|
|
$unique_vul = array_intersect_key( $this->scan_data['wp']['vulnerabilities'], $temp );
|
|
shuffle( $unique_vul );
|
|
|
|
foreach ( $unique_vul as $k => $v ) {
|
|
|
|
//check is fixed version is missing
|
|
if ( $v['fixed_in'] === '' ) {
|
|
error_log( 'Fixed in missing for WP' );
|
|
$this->items_without_fixed_in['wp'] = '';
|
|
$this->isFixVersionMissing = true;
|
|
}
|
|
//round cvss score at two decimal points
|
|
$unique_vul[ $k ]['cvss_score'] = sprintf( '%.2f', $unique_vul[ $k ]['cvss_score'] );
|
|
}
|
|
|
|
$wp_vuls = $unique_vul;
|
|
|
|
$db_data['wp']['installed_version'] = $this->scan_data['wp']['installed_version'];
|
|
$db_data['wp']['fixed_in'] = max( array_column( $wp_vuls, 'fixed_in' ) );
|
|
$db_data['wp']['vulnerabilities'] = $wp_vuls;
|
|
$db_data['wp']['name'] = 'WordPress Core';
|
|
}
|
|
|
|
//check is new vulnerability exist
|
|
$this->isNewVulnerabilityFound( $db_data, $existing );
|
|
|
|
if ( empty( $existing['vulnerabilities'] ) ) {
|
|
$existing['vulnerabilities'] = $db_data;
|
|
} else {
|
|
$this->last_scan_data = $this->extractVulnerableItems( $existing['vulnerabilities'] );
|
|
|
|
// if existing vulnerabilities are not in latest scan (updated, deleted, or deactivated), push to VM log
|
|
$fixed_vuls = $history_log_obj->extractFixedVulnerabilities( $existing['vulnerabilities'], $db_data );
|
|
|
|
if ( count( $fixed_vuls ) > 0 ) {
|
|
error_log( 'Fixed vulnerabilities found to push in log' );
|
|
$history_log_obj->iterateVulnerabilitiesForLog( $fixed_vuls );
|
|
} else {
|
|
error_log( 'No fixed vulnerabilities found so far' );
|
|
}
|
|
|
|
$existing['vulnerabilities'] = $db_data;
|
|
}
|
|
|
|
// save all vulnerabilities
|
|
$existing['vulnerabilities'] = $db_data;
|
|
|
|
$this->settings->update( $existing );
|
|
}
|
|
|
|
/**
|
|
* Check is found any new vulnerability
|
|
* @param $new_vul
|
|
* @param $existing_vul
|
|
* @return void
|
|
*/
|
|
public function isNewVulnerabilityFound( $new_vul, $existing_vul ) {
|
|
global $wp_version;
|
|
|
|
if ( ! is_array( $new_vul ) && ! is_array( $existing_vul ) ) {
|
|
return;
|
|
}
|
|
|
|
error_log( '~~~ Checking for new vulnerability ~~~' );
|
|
|
|
//Prepare default structure for vulnerability check
|
|
$new_vul = $new_vul + array(
|
|
'plugins' => array(),
|
|
'themes' => array(),
|
|
'wp' => array( 'vulnerabilities' => array() ),
|
|
);
|
|
$existing_vul['vulnerabilities'] = $existing_vul['vulnerabilities'] + array(
|
|
'plugins' => array(),
|
|
'themes' => array(),
|
|
'wp' => array( 'vulnerabilities' => array() ),
|
|
);
|
|
|
|
$pluginCheck = ( isset( $new_vul['plugins'] ) ) ? array_diff_key( $new_vul['plugins'], $existing_vul['vulnerabilities']['plugins'] ) : array();
|
|
|
|
//check new vulnerability for themes
|
|
$themeCheck = ( isset( $new_vul['themes'] ) ) ? array_diff_key( $new_vul['themes'], $existing_vul['vulnerabilities']['themes'] ) : array();
|
|
|
|
//check new vulnerability for WP
|
|
$existingWP = isset( $existing_vul['vulnerabilities']['wp']['vulnerabilities'] ) ? count( $existing_vul['vulnerabilities']['wp']['vulnerabilities'] ) : 0;
|
|
|
|
$newWP = ( isset( $new_vul['wp']['vulnerabilities'] ) ) ? count( $new_vul['wp']['vulnerabilities'] ) : 0;
|
|
|
|
//get new vulnerability regarding WP core
|
|
$wpCheck = $newWP - $existingWP;
|
|
|
|
//get the max fixed_in version
|
|
$ver = ( $newWP > 0 ) ? max( array_column( $new_vul['wp']['vulnerabilities'], 'fixed_in' ) ) : $wp_version;
|
|
$user_settings = $this->settings->get();
|
|
|
|
//check is installed WP and coming WP vulnerability fixed_in are same or empty
|
|
//then, override the WP vulnerability if found the same version during auto-update on
|
|
if ( version_compare( $wp_version, $ver ) >= 0 && 1 == $user_settings['settings']['auto_update'] ) {
|
|
$wpCheck = 0;
|
|
}
|
|
|
|
if ( count( $pluginCheck ) > 0 || count( $themeCheck ) > 0 || $wpCheck > 0 ) {
|
|
error_log( '~~~ New vulnerability found ~~~' );
|
|
$this->isNewVulnerabilityExist = true;
|
|
return;
|
|
}
|
|
error_log( '~~~ No new vulnerability found ~~~' );
|
|
}
|
|
|
|
/**
|
|
* Check and Display Vulnerabilities if any
|
|
*/
|
|
public function manageVulnerabilities(): void {
|
|
|
|
// return if wp core update is in progress/scheduled shortly
|
|
if (!$this->wp_core_updates_not_scheduled()) {
|
|
error_log('wp core update in-progress/scheduled shortly terminating VM scan.');
|
|
return;
|
|
}
|
|
|
|
error_log( 'Scan started!' );
|
|
|
|
self::collectVersions();
|
|
|
|
self::sendVersions();
|
|
|
|
self::processResponse();
|
|
|
|
if ( false !== $this->http_error ) {
|
|
error_log( 'Error found -- ' . $this->http_error );
|
|
return;
|
|
// stop execution and log error if required
|
|
}
|
|
|
|
if ( null === $this->scan_data ) {
|
|
error_log( 'No data found from API response -- ' . json_encode( $this->http_response ) );
|
|
return;
|
|
// stop execution and log error if required
|
|
}
|
|
|
|
if ( true !== self::vulnerabilityExists() ) {
|
|
error_log( 'No vulnerabilities found! All good! Exiting...' );
|
|
return;
|
|
}
|
|
|
|
error_log( 'Vulnerabilities found!' );
|
|
self::saveVulnerabilities();
|
|
|
|
// get user's preferences
|
|
$user_settings = $this->settings->get();
|
|
$notify_admins = new OCVMSendEmails();
|
|
|
|
//get daily email send status
|
|
$daily_email_sent = get_site_transient( 'ocvm_daily_email_sent' );
|
|
|
|
//Allow auto-update only for mWP
|
|
if ( 1 == $user_settings['settings']['auto_update'] && $this->settings->isPremium() ) {
|
|
|
|
// Auto-update items
|
|
$auto_update = new OCVMAutoUpdates();
|
|
$auto_update->updateItems();
|
|
|
|
// check user's preferences for email type, send vuls-fixed and vuls-found email
|
|
if (
|
|
1 === $user_settings['settings']['notify_all'] &&
|
|
1 === $user_settings['settings']['email_type']['email_fixed'] &&
|
|
current_action() === 'ocvm_scan'
|
|
) {
|
|
error_log( 'Sending vuls-fixed / vuls-found on ocvm_scan run as per requirement' );
|
|
$this->fixedAndNoAutoFixedEmail( $notify_admins, $auto_update );
|
|
}
|
|
} else {
|
|
|
|
// check user's preferences for email type
|
|
if (
|
|
1 === $user_settings['settings']['notify_all'] &&
|
|
1 === $user_settings['settings']['email_type']['email_detect']
|
|
) {
|
|
|
|
// send vuls-found email
|
|
// on new vulnerability found we will send always email
|
|
// ocvm_scan should run once a day if email is not sent for a day
|
|
// if email is already sent, then will skip sending email via ocvm_scan
|
|
// otherwise, we will skip sending email
|
|
if ( $this->isNewVulnerabilityExist ) {
|
|
error_log( 'Sending email on new vulnerability found.' );
|
|
$notify_admins->sendEmail();
|
|
( ! $daily_email_sent ) ? set_site_transient( 'ocvm_daily_email_sent', 'yes', 7 * DAY_IN_SECONDS ) : '';
|
|
} elseif ( current_action() === 'ocvm_scan' && ! $daily_email_sent ) {
|
|
error_log( 'Sending email on ocvm_scan run' );
|
|
$notify_admins->sendEmail();
|
|
//set site transient for 24hr
|
|
set_site_transient( 'ocvm_daily_email_sent', 'yes', 7 * DAY_IN_SECONDS );
|
|
} else {
|
|
error_log( 'Skip sending email because no new vulnerability found.' );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public function fixedAndNoAutoFixedEmail( $notify_admins, $auto_update ): void {
|
|
error_log( 'Sending email for vulnerability on the basis of condition' );
|
|
//send auto-update email for vulnerability fixed if no case of missing fixed version
|
|
if ( ! $this->isFixVersionMissing ) {
|
|
error_log( 'Sending email only for fixed vulnerability' );
|
|
$notify_admins->sendEmail( 'vulsFixed', $auto_update->updateAttempt );
|
|
return;
|
|
}
|
|
|
|
// Send vulsNotAutoFixed only if any fixed version is missing and weekly mail is not sent or new vul found
|
|
$daily_email_sent = get_site_transient( 'ocvm_daily_email_sent' );
|
|
if ( current_action() === 'ocvm_scan'
|
|
&& ( ! $daily_email_sent || ! $this->vulExistsInLastScan( $this->items_without_fixed_in, $this->last_scan_data ) )
|
|
) {
|
|
$notify_admins->sendEmail( 'vulsNotAutoFixed', $auto_update->updateAttempt );
|
|
set_site_transient( 'ocvm_daily_email_sent', 'yes', 7 * DAY_IN_SECONDS );
|
|
}
|
|
|
|
error_log( 'Sending email for vulnerability fix always' );
|
|
$notify_admins->sendEmail( 'vulsFixed', $auto_update->updateAttempt );
|
|
}
|
|
|
|
/**
|
|
* Set cron if not exists
|
|
*/
|
|
public function setCron() {
|
|
if ( ! wp_next_scheduled( $this->settings::wpcron_hook ) ) {
|
|
wp_schedule_event(
|
|
time(),
|
|
'daily',
|
|
// TODO: enable 24 hours duration before real deployment
|
|
// $this->settings->get()['scan_duration'],
|
|
$this->settings::wpcron_hook
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Prepare vulerable (last scan) items names, rmove `vulnerablities` and extra data
|
|
*
|
|
* @return array
|
|
*/
|
|
public function extractVulnerableItems( $vuls ): array {
|
|
$vul_items = array();
|
|
foreach ( $vuls as $item => $value ) {
|
|
// Get vulnerable plugins and themes slugs
|
|
if ( $item === 'plugins' || $item === 'themes' ) {
|
|
$vul_items[ $item ] = array_keys( $value );
|
|
} elseif ( $item === 'wp' ) {
|
|
$vul_items[ $item ] = '';
|
|
}
|
|
}
|
|
|
|
return $vul_items;
|
|
}
|
|
|
|
/**
|
|
* Check if all current i.e new vulnerable (missing fixed-in) items were already exists in last scan
|
|
* If exists (and weekly mail sent), we will prevent sending 'vulsNotAutoFixed' mail after auto update
|
|
*
|
|
* @return bool
|
|
*/
|
|
public function vulExistsInLastScan( $new_vuls, $old_vuls ): bool {
|
|
foreach ( $new_vuls as $type => $items ) {
|
|
// Return false if the 'plugins', 'themes' or 'wp' key found in new_vuls does not exists in old_vuls
|
|
if ( ! isset( $old_vuls[ $type ] ) ) {
|
|
return false;
|
|
}
|
|
|
|
// Return false any plugin/theme from new_vuls does not exists in old_vuls, else return true as all vuls found in last scan
|
|
foreach ( $items as $item ) {
|
|
if ( ! in_array( $item, $old_vuls[ $type ] ) ) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* Delete cron upon deactivation
|
|
*/
|
|
public function deleteCron() {
|
|
$timestamp = wp_next_scheduled( 'bl_cron_hook' );
|
|
wp_unschedule_event( $timestamp, 'bl_cron_hook' );
|
|
}
|
|
|
|
/**
|
|
* Schedule WPCron scan scheduling after 30sec for multiple events (activation, deactivation, updation, deletion)
|
|
* @param $plugin
|
|
* @param $network_wide
|
|
* @return void
|
|
*/
|
|
public function scheduleOCVMScan() {
|
|
wp_schedule_single_event( time() + 30, 'ocvm_scan' );
|
|
}
|
|
|
|
/**
|
|
* Schedule event after 30sec of auto update enabled
|
|
*
|
|
* @return void
|
|
*/
|
|
public function scheduleCronAfterAutoupdate() {
|
|
wp_schedule_single_event( time() + 30, 'ocvm_scan' );
|
|
}
|
|
|
|
/**
|
|
* Send version stats
|
|
*/
|
|
public function sendVersionStats( $ver = array() ): void {
|
|
if ( empty( $ver ) ) {
|
|
return;
|
|
}
|
|
|
|
// Add one.com features related data
|
|
$additional_info = $this->ocFeaturesInfo( $ver );
|
|
|
|
class_exists( 'OCPushStats' ) ?
|
|
OCPushStats::push_vul_monitor_stats( 'scan', 'setting', 'vulnerability_monitor', array( 'active_versions' => $additional_info ) ) :
|
|
'';
|
|
}
|
|
|
|
/**
|
|
* Add one.com features related essential info in VM Scan
|
|
*/
|
|
public function ocFeaturesInfo($ver) {
|
|
|
|
// Add ALP status
|
|
$alp_status = (string) get_site_option( 'onecom_login_masking', '' );
|
|
$ver['alp_status'] = $alp_status;
|
|
|
|
// add error page status
|
|
$error_class_path = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . 'fatal-error-handler.php';
|
|
$error_page = new Onecom_Error_Page();
|
|
$error_page_status = ( file_exists( $error_class_path ) && $error_page->is_onecom_plugin() ) ? '1' : '0';
|
|
$ver['error_page_status'] = $error_page_status;
|
|
|
|
// add cookie banner status
|
|
$settings = get_site_option( 'oc_cb_configuration' );
|
|
$cb_status = ( empty( $settings ) || empty( $settings['config'] ) ) ? '0' : $settings['config']['show'];
|
|
$ver['cookie_banner_status'] = $cb_status;
|
|
|
|
// add old cu consent
|
|
$old_consent = get_site_option( 'oc_cu_consent' );
|
|
$old_consent_status = false !== $old_consent ? $old_consent : '';
|
|
$ver['old_consent_status'] = $old_consent_status;
|
|
|
|
// add new cu consent
|
|
$new_consent = get_site_option( 'onecom_data_consent_status' );
|
|
$new_consent_status = false !== $new_consent ? $new_consent : '';
|
|
$ver['data_consent_status'] = $new_consent_status;
|
|
|
|
return $ver;
|
|
}
|
|
|
|
/**
|
|
* @return bool
|
|
* check if wp core update is running
|
|
*/
|
|
public function wp_core_updates_not_scheduled()
|
|
{
|
|
|
|
if (file_exists(ABSPATH . '.maintenance')) {
|
|
return false; // Update is in progress
|
|
}
|
|
|
|
// Check if update lock is active (via core_updater.lock)
|
|
$update_locked = get_option('core_updater.lock');
|
|
if ($update_locked) {
|
|
return false;
|
|
}
|
|
|
|
// Check if an automatic update is scheduled in the near future
|
|
$scheduled_event = wp_get_scheduled_event('wp_maybe_auto_update');
|
|
if ($scheduled_event) {
|
|
$time_until_next_update = $scheduled_event->timestamp - time();
|
|
if ($time_until_next_update > 0 && $time_until_next_update < 1800) { // Next 30 minutes
|
|
return false; // Update is scheduled soon
|
|
}
|
|
}
|
|
|
|
// No update in progress or scheduled soon
|
|
return true;
|
|
}
|
|
|
|
|
|
}
|