<?php
/**
 * Detect email-security-scanner prefetches so they don't consume single-use magic tokens.
 *
 * Why: Corporate gateways (Outlook Safe Links, Mimecast, Proofpoint, Microsoft Defender ATP)
 * fetch URLs server-side to scan them. With single-use tokens this silently burns the link
 * before the real user clicks. We treat HEAD requests and known scanner UAs as non-consuming.
 *
 * @package KaizenCoders\MagicLink
 */

namespace KaizenCoders\MagicLink;

class ScannerDetector {

	/**
	 * Substrings (case-insensitive) we look for in the User-Agent header.
	 *
	 * @var array
	 */
	private static $signatures = array(
		'GoogleImageProxy',
		'YahooMailProxy',
		'Mimecast',
		'Proofpoint',
		'Microsoft Office Protection',
		'Microsoft Outlook',
		'OutlookSafeLinks',
		'Barracuda',
		'Symantec',
		'BitDefender',
		'Trend Micro',
		'Sophos',
		'Avast',
		'McAfee',
		'Forcepoint',
		'WebShield',
		'URLDefense',
		'Slackbot-LinkExpanding',
		'Twitterbot',
		'facebookexternalhit',
		'LinkedInBot',
		'WhatsApp',
		'TelegramBot',
		'DiscordBot',
		'SkypeUriPreview',
		'preview',
	);

	/**
	 * True when the current request looks like a scanner prefetch.
	 *
	 * @param  string $method     HTTP method (e.g. 'GET', 'HEAD', 'POST').
	 * @param  string $user_agent Raw user-agent header value.
	 *
	 * @return bool
	 */
	public static function is_scanner( $method, $user_agent ) {
		$method = strtoupper( (string) $method );

		if ( 'HEAD' === $method || 'OPTIONS' === $method ) {
			return true;
		}

		if ( '' === (string) $user_agent ) {
			return false;
		}

		foreach ( self::$signatures as $needle ) {
			if ( stripos( $user_agent, $needle ) !== false ) {
				return true;
			}
		}

		return false;
	}

	/**
	 * Convenience wrapper that reads from $_SERVER.
	 *
	 * @return bool
	 */
	public static function is_current_request_scanner() {
		$method = isset( $_SERVER['REQUEST_METHOD'] ) ? $_SERVER['REQUEST_METHOD'] : 'GET';
		$ua     = isset( $_SERVER['HTTP_USER_AGENT'] ) ? $_SERVER['HTTP_USER_AGENT'] : '';

		return self::is_scanner( $method, $ua );
	}
}
