<?php
namespace iThemesSecurity\Site_Scanner;
final class Factory {
const ENTRIES = [ 'vulnerabilities', 'blacklist', 'malware' ];
/**
* Makes a scan result for a log item.
*
* @param int $log_id The log id.
*
* @return Scan|\WP_Error
*/
public function for_log_id( $log_id ) {
$log_type = \ITSEC_Modules::get_setting( 'global', 'log_type' );
if ( 'file' === $log_type ) {
return new \WP_Error( 'itsec_site_scanner_factory_invalid_log_type', __( 'Logs must be stored in the database to retrieve past scans.', 'better-wp-security' ) );
}
$entry = \ITSEC_Log::get_entry( $log_id );
return $this->for_log_item( $entry );
}
/**
* Makes a scan result for a log item.
*
* @param array $log
*
* @return Scan|\WP_Error
*/
public function for_log_item( $log ) {
$valid = \ITSEC_Site_Scanner_Util::is_log_item_valid_scan( $log );
if ( is_wp_error( $valid ) ) {
return $valid;
}
if ( ! isset( $log['data']['results'] ) ) {
return new \WP_Error( 'itsec_site_scanner_factory_malformed_log_item', __( 'Log item is malformed.', 'better-wp-security' ) );
}
$id = (int) $log['id'];
$code = $log['code'];
$time = new \DateTimeImmutable( $log['init_timestamp'], new \DateTimeZone( 'UTC' ) );
$results = $log['data']['results'];
if ( is_wp_error( $results ) ) {
return Scan::as_error( $id, $code, '', $time, $results );
}
$url = isset( $results['url'] ) ? $results['url'] : '';
$entries = ! empty( $results['entries'] ) ? $this->make_entries( $results['entries'] ) : [];
$errors = ! empty( $results['errors'] ) ? $results['errors'] : [];
return new Scan( $id, $code, $url, $time, $entries, $errors );
}
/**
* Makes a Scan object from the API response.
*
* @param array|\WP_Error $response
*
* @return Scan
*/
public function for_api_response( $response ) {
$id = 0;
$code = \ITSEC_Site_Scanner_Util::get_scan_result_code( $response );
$time = new \DateTimeImmutable( 'now', new \DateTimeZone( 'UTC' ) );
if ( is_wp_error( $response ) ) {
$url = isset( $response->get_error_data()['url'] ) ? $response->get_error_data()['url'] : '';
return Scan::as_error( $id, $code, $url, $time, $response );
}
$url = isset( $response['url'] ) ? $response['url'] : '';
$entries = ! empty( $response['entries'] ) ? $this->make_entries( $response['entries'] ) : [];
$errors = ! empty( $response['errors'] ) ? $response['errors'] : [];
return new Scan( $id, $code, $url, $time, $entries, $errors );
}
/**
* Make a list of entries from the scan data.
*
* @param array $data
*
* @return Entry[]
*/
protected function make_entries( array $data ) {
$entries = [];
foreach ( self::ENTRIES as $slug ) {
if ( ! isset( $data[ $slug ] ) ) {
continue;
}
$entry = $this->{"make_{$slug}"}( $data[ $slug ] );
if ( $entry instanceof Entry ) {
$entries[] = $entry;
}
}
return $entries;
}
/**
* Make a vulnerability entry from the scan data.
*
* @param array $data
*
* @return Entry
*/
protected function make_vulnerabilities( $data ) {
if ( ! $data || ! is_array( $data ) ) {
return new Entry( 'vulnerabilities', __( 'Known Vulnerabilities', 'better-wp-security' ), Status::CLEAN );
}
$issues = [];
foreach ( $data as $vulnerability ) {
$link = \ITSEC_Site_Scanner_Util::authenticate_vulnerability_link( $vulnerability['link'] );
foreach ( $vulnerability['issues'] as $issue ) {
if ( empty( $issue['id'] ) ) {
continue;
}
$issues[] = new Vulnerability_Issue( $vulnerability, $issue['id'], $link );
}
}
return new Entry( 'vulnerabilities', __( 'Known Vulnerabilities', 'better-wp-security' ), Status::WARN, $issues );
}
/**
* Make a blacklist entry from the scan data.
*
* @param array $data
*
* @return Entry
*/
protected function make_blacklist( $data ) {
$issues = [];
$status = Status::CLEAN;
if ( $data && is_array( $data ) ) {
foreach ( $data as $details ) {
$issue = new Blacklist_Issue( $details );
$issues[] = $issue;
if ( $issue->get_status() === Status::WARN ) {
$status = $issue->get_status();
}
}
}
return new Entry( 'blacklist', __( 'Blocklist', 'better-wp-security' ), $status, $issues );
}
/**
* Makes a malware entry from the scan data.
*
* @param array $data
*
* @return Entry
*/
protected function make_malware( $data ) {
if ( ! $data || ! is_array( $data ) ) {
return new Entry( 'malware', __( 'Malware', 'better-wp-security' ), Status::CLEAN );
}
$issues = [];
foreach ( $data as $malware ) {
$issues[] = new Malware_Issue( $malware );
}
return new Entry( 'malware', __( 'Malware', 'better-wp-security' ), Status::WARN );
}
}