'', 'created' => 0, 'previous' => '', 'previous_until' => 0, ), $stored ); } /** * Current token, created when missing and replaced every hour. * * @return string */ public static function get() { $stored = self::stored(); if ( strlen( $stored['current'] ) < 32 || time() - (int) $stored['created'] > self::LIFETIME ) { $stored = self::rotate(); } return $stored['current']; } /** * Replaces the token now (after each whole-site pass). The previous one keeps * working for a while, so a check already running isn't cut off. * * @return array Stored tokens. */ public static function rotate() { $old = self::stored(); $stored = array( 'current' => wp_generate_password( 40, false, false ), 'created' => time(), 'previous' => strlen( $old['current'] ) >= 32 ? $old['current'] : '', 'previous_until' => time() + self::GRACE, ); set_transient( self::TRANSIENT, $stored, self::LIFETIME + self::GRACE ); return $stored; } /** * Whether a token matches. * * @param string $token Token from the request. * @return bool */ public static function verify( $token ) { $stored = self::stored(); $token = (string) $token; $valid = '' !== $stored['current'] && time() - (int) $stored['created'] <= self::LIFETIME + self::GRACE && hash_equals( $stored['current'], $token ); if ( ! $valid && '' !== $stored['previous'] && time() < (int) $stored['previous_until'] ) { $valid = hash_equals( $stored['previous'], $token ); } /** * Filters whether a scan token is valid. Fixlight Pro accepts the secret * it shares with its hosted crawler, so the crawler can also check pages * with fixes off. * * @param bool $valid Whether the token matches Fixlight's own token. * @param string $token Token from the request. */ return (bool) apply_filters( 'fixlight_scan_token_valid', $valid, $token ); } }