= $limit ) { return false; } // The window starts at the first attempt and is not extended by the // ones after it. A caller who is refused at the limit waits out what // is left of the window rather than restarting it with every try, // which is what makes the ceiling a ceiling. set_transient( $key, $seen + 1, $window ); return true; } /** * Forgets one caller's count. For tests, and for a support request. * * @param string $bucket What was being limited. */ public static function forget( string $bucket ): void { delete_transient( self::PREFIX . $bucket . '_' . self::caller() ); } /** * Who is asking, as a hash that means nothing outside this window. * * `REMOTE_ADDR` and nothing else. `X-Forwarded-For` is written by whoever * is calling unless a proxy in front of us overwrites it, so trusting it * would let the very caller being counted hand us a new identity per * request. Sites behind a reverse proxy that puts the real address * somewhere else can say so through the filter below; the default has to * be the value that cannot be forged. */ private static function caller(): string { $address = isset( $_SERVER['REMOTE_ADDR'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REMOTE_ADDR'] ) ) : ''; /** * Filters the address a rate limit is counted against. * * For sites behind a proxy or load balancer that puts the visitor's * address in a header it controls — and only where that header cannot * be set by the visitor. * * @param string $address The address, as PHP sees it. */ $address = (string) apply_filters( 'sharelyai_client_address', $address ); return substr( md5( $address . '|' . wp_salt() ), 0, 16 ); } }