<?php

final class ITSEC_Malware_Scanner {
	protected static $transient_name = 'itsec_cached_sucuri_scan';
	
	public static function scan() {
		global $itsec_logger;
		
		
		$results = self::get_scan_results();
		
		if ( is_array( $results ) && isset( $results['cached'] ) && $results['cached'] ) {
			return $results;
		}
		
		
		$user = wp_get_current_user();
		$itsec_logger->log_event( 'malware', 3, $results, ITSEC_Lib::get_ip(), $user->user_login, $user->ID );
		
		return $results;
	}
	
	protected static function get_scan_results() {
		$response = get_site_transient( self::$transient_name );
		$cached = true;
		
		if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE' ) && ITSEC_TEST_MALWARE_SCAN_SKIP_CACHE ) {
			$cached = false;
			$response = false;
		}
		
		
		if ( false === $response ) {
			$cached = false;
			
			$scanner_url = 'http://sitecheck.sucuri.net/';
			$site_url = apply_filters( 'itsec_test_malware_scan_site_url', get_site_url() );
			
			if ( defined( 'ITSEC_TEST_MALWARE_SCAN_SITE_URL' ) ) {
				$site_url = ITSEC_TEST_MALWARE_SCAN_SITE_URL;
			}
			
			$site_url = preg_replace( '|^https?://|i', '', $site_url );
			
			$query_args = array(
				'scan'  => $site_url,
				'p'     => 'ithemes',
				'clear' => 1,
				'json'  => 1,
				'time'  => time(),
			);
			
			$key = apply_filters( 'itsec_sucuri_key', '' );
			
			if ( defined( 'ITSEC_SUCURI_KEY' ) ) {
				$key = ITSEC_SUCURI_KEY;
			}
			
			if ( ! empty( $key ) ) {
				$query_args['k'] = $key;
			}
			
			$scan_url = "$scanner_url?" . http_build_query( $query_args );
			
			$req_args = array(
				'timeout' => 300,
			);
			
			if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
				$req_args['sslverify'] = false;
				
				// Ensure that another plugin isn't preventing the disabling of sslverify from working.
				add_filter( 'https_local_ssl_verify', '__return_false', 999999 );
				add_filter( 'https_ssl_verify', '__return_false', 999999 );
			}
			
			$response = wp_remote_get( $scan_url, $req_args );
			
			if ( defined( 'ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY' ) && ITSEC_TEST_MALWARE_SCAN_DISABLE_SSLVERIFY ) {
				remove_filter( 'https_local_ssl_verify', '__return_false', 999999 );
				remove_filter( 'https_ssl_verify', '__return_false', 999999 );
			}
			
			if ( is_wp_error( $response ) ) {
				return $response;
			}
		}
		
		
		if (
			! is_array( $response ) ||
			! array_key_exists( 'body', $response ) ||
			! array_key_exists( 'headers', $response ) ||
			! array_key_exists( 'response', $response ) ||
			! isset( $response['headers']['content-type'] )
		) {
			return new WP_Error( 'itsec-malware-scanner-malformed-wp-remote-get-response', __( 'The response from the wp_remote_get function was malformed. This could indicate an issue with WordPress.', 'better-wp-security' ) );
		}
		
		
		$body = @json_decode( $response['body'], true );
		
		if ( is_null( $body ) ) {
			if ( 'application/json' === $response['headers']['content-type'] ) {
				return new WP_Error( 'itsec-malware-scanner-invalid-json-data-in-scan-response', __( 'The scan did not complete successfully. The Sucuri server should send its response in JSON encoding. The response indicates that the encoding is JSON, but the data could not be decoded. This problem could be due to a temporary Sucuri server issue or a compatibility issue on your server. If the problem continues, please contact iThemes Security support.', 'better-wp-security' ), $response );
			} else {
				return new WP_Error( 'itsec-malware-scanner-invalid-content-type-in-scan-response', sprintf( __( 'The scan did not complete successfully. The Sucuri server should send its response in JSON encoding. The data received from the Sucuri server could not be decoded. In addition, a content type of <code>%s</code> was received when a content type of <code>application/json</code> was expected. This could indicate a temporary issue with the Sucuri servers.', 'better-wp-security' ), esc_html( $response['headers']['content-type'] ) ), $response );
			}
		} else if ( ! is_array( $body ) ) {
			if ( 'ERROR' === substr( $response['body'], 0, 5 ) ) {
				return new WP_Error( 'itsec-malware-scanner-error-received', sprintf( __( 'The scan did not complete successfully. Sucuri sent the following error: %s', 'better-wp-security' ), $response['body'] ), $response );
			}
			
			return new WP_Error( 'itsec-malware-scanner-unknown-scan-error', sprintf( __( 'An unknown error prevented the scan from completing successfully. The Sucuri server responded with a <code>%s</code> error code.', 'better-wp-security' ), $response['response']['code'] ), $response );
		}
		
		
		if ( ! $cached ) {
			set_site_transient( self::$transient_name, $response, 10 * MINUTE_IN_SECONDS );
		}
		
		if ( is_array( $body ) ) {
			$body['cached'] = $cached;
		}
		
		return $body;
	}
}
