13.85.24.90' => '', // GT Metrix - San Antonio, TX 4. '13.85.82.26' => '', // GT Metrix - San Antonio, TX 5. '40.74.242.253' => '', // GT Metrix - San Antonio, TX 6. '40.74.243.13' => '', // GT Metrix - San Antonio, TX 7. '40.74.243.176' => '', // GT Metrix - San Antonio, TX 8. '104.214.48.247' => '', // GT Metrix - San Antonio, TX 9. '157.55.189.189' => '', // GT Metrix - San Antonio, TX 10. '104.214.110.135' => '', // GT Metrix - San Antonio, TX 11. '70.37.83.240' => '', // GT Metrix - San Antonio, TX 12. '65.52.36.250' => '', // GT Metrix - San Antonio, TX 13. '13.78.216.56' => '', // GT Metrix - Cheyenne, WY. '52.162.212.163' => '', // GT Metrix - Chicago, IL. '23.96.34.105' => '', // GT Metrix - Danville, VA. '65.52.113.236' => '', // GT Metrix - San Francisco, CA. '172.255.61.34' => '', // GT Metrix - London 1. '172.255.61.35' => '', // GT Metrix - London 2. '172.255.61.36' => '', // GT Metrix - London 3. '172.255.61.37' => '', // GT Metrix - London 4. '172.255.61.38' => '', // GT Metrix - London 5. '172.255.61.39' => '', // GT Metrix - London 6. '172.255.61.40' => '', // GT Metrix - London 7. '52.237.235.185' => '', // GT Metrix - Sydney 1. '52.237.250.73' => '', // GT Metrix - Sydney 2. '52.237.236.145' => '', // GT Metrix - Sydney 3. '104.41.2.19' => '', // GT Metrix - São Paulo 1. '191.235.98.164' => '', // GT Metrix - São Paulo 2. '191.235.99.221' => '', // GT Metrix - São Paulo 3. '191.232.194.51' => '', // GT Metrix - São Paulo 4. '104.211.143.8' => '', // GT Metrix - Mumbai 1. '104.211.165.53' => '', // GT Metrix - Mumbai 2. '52.172.14.87' => '', // GT Metrix - Chennai. '40.83.89.214' => '', // GT Metrix - Hong Kong 1. '52.175.57.81' => '', // GT Metrix - Hong Kong 2. '20.188.63.151' => '', // GT Metrix - Paris. '20.52.36.49' => '', // GT Metrix - Frankfurt. '52.246.165.153' => '', // GT Metrix - Tokyo. '51.144.102.233' => '', // GT Metrix - Amsterdam. '13.76.97.224' => '', // GT Metrix - Singapore. '102.133.169.66' => '', // GT Metrix - Johannesburg. '52.231.199.170' => '', // GT Metrix - Busan. '13.53.162.7' => '', // GT Metrix - Stockholm. '40.123.218.94' => '', // GT Metrix - Dubai. ]; if ( isset( $ips[ $this->get_ip() ] ) ) { return self::memoize( __FUNCTION__, [], true ); } if ( ! $this->config->get_server_input( 'HTTP_USER_AGENT' ) ) { return self::memoize( __FUNCTION__, [], false ); } $user_agent = preg_match( '#PingdomPageSpeed|DareBoost|Google|PTST|Chrome-Lighthouse|WP Rocket#i', $this->config->get_server_input( 'HTTP_USER_AGENT' ) ); return self::memoize( __FUNCTION__, [], (bool) $user_agent ); } /** * Determines if SSL is used. * This is basically a copy of the WP function, where $_SERVER is not used directly. * * @since 3.3 * @author Grégory Viguier * * @return bool True if SSL, otherwise false. */ public function is_ssl() { if ( null !== $this->config->get_server_input( 'HTTPS' ) ) { if ( 'on' === strtolower( $this->config->get_server_input( 'HTTPS' ) ) ) { return true; } if ( '1' === (string) $this->config->get_server_input( 'HTTPS' ) ) { return true; } } elseif ( '443' === (string) $this->config->get_server_input( 'SERVER_PORT' ) ) { return true; } return false; } /** ----------------------------------------------------------------------------------------- */ /** REQUEST URI AND METHOD ================================================================== */ /** ----------------------------------------------------------------------------------------- */ /** * Get the request URI. * * @since 3.3 * @author Grégory Viguier * * @return string */ public function get_raw_request_uri() { if ( '' === $this->config->get_server_input( 'REQUEST_URI', '' ) ) { return ''; } return '/' . ltrim( $this->config->get_server_input( 'REQUEST_URI' ), '/' ); } /** * Get the request URI without the query strings. * * @since 3.3 * @author Grégory Viguier * * @return string */ public function get_request_uri_base() { $request_uri = $this->get_raw_request_uri(); if ( ! $request_uri ) { return ''; } $request_uri = explode( '?', $request_uri ); return reset( $request_uri ); } /** * Get the request URI. The query string is sorted and some parameters are removed. * * @since 3.3 * @author Grégory Viguier * * @return string */ public function get_clean_request_uri() { $request_uri = $this->get_request_uri_base(); $request_uri = $this->remove_dot_segments( $request_uri ); if ( ! $request_uri ) { return ''; } $query_string = $this->get_query_string(); if ( ! $query_string ) { return $request_uri; } return $request_uri . '?' . $query_string; } /** * Get the request method. * * @since 3.3 * @author Grégory Viguier * * @return string */ public function get_request_method() { if ( '' === $this->config->get_server_input( 'REQUEST_METHOD', '' ) ) { return ''; } return strtoupper( $this->config->get_server_input( 'REQUEST_METHOD' ) ); } /** * Remove dot segments from a path * * @param string $input Path to process. * * @return string */ private function remove_dot_segments( string $input ) { $output = ''; while ( strpos( $input, './' ) !== false || strpos( $input, '/.' ) !== false || '.' === $input || '..' === $input ) { /** * A: If the input buffer begins with a prefix of "../" or "./", * then remove that prefix from the input buffer; otherwise, */ if ( strpos( $input, '../' ) === 0 ) { $input = substr( $input, 3 ); } elseif ( strpos( $input, './' ) === 0 ) { $input = substr( $input, 2 ); } /** * B: if the input buffer begins with a prefix of "/./" or "/.", * where "." is a complete path segment, then replace that prefix * with "/" in the input buffer; otherwise, */ elseif ( strpos( $input, '/./' ) === 0 ) { $input = substr( $input, 2 ); } elseif ( '/.' === $input ) { $input = '/'; } /** * C: if the input buffer begins with a prefix of "/../" or "/..", * where ".." is a complete path segment, then replace that prefix * with "/" in the input buffer and remove the last segment and its * preceding "/" (if any) from the output buffer; otherwise, */ elseif ( strpos( $input, '/../' ) === 0 ) { $input = substr( $input, 3 ); $output = substr_replace( $output, '', strrpos( $output, '/' ) ); } elseif ( '/..' === $input ) { $input = '/'; $output = substr_replace( $output, '', strrpos( $output, '/' ) ); } /** * D: if the input buffer consists only of "." or "..", then remove * that from the input buffer; otherwise, */ elseif ( '.' === $input || '..' === $input ) { $input = ''; } /** * E: move the first path segment in the input buffer to the end of * the output buffer, including the initial "/" character (if any) * and any subsequent characters up to, but not including, the next * "/" character or the end of the input buffer */ elseif ( strpos( $input, '/', 1 ) !== false ) { $pos = strpos( $input, '/', 1 ); $output .= substr( $input, 0, $pos ); $input = substr_replace( $input, '', 0, $pos ); } else { $output .= $input; $input = ''; } } return $output . $input; } /** ----------------------------------------------------------------------------------------- */ /** QUERY STRING ============================================================================ */ /** ----------------------------------------------------------------------------------------- */ /** * Get the query string as an array. Parameters are sorted and some are removed. * * @since 3.3 * @author Grégory Viguier * * @return array */ public function get_query_params() { if ( ! self::$get ) { return []; } // Remove some parameters. $params = array_diff_key( self::$get, $this->config->get_config( 'cache_ignored_parameters' ) ); if ( $params ) { ksort( $params ); } return $params; } /** * Get the query string with sorted parameters, and some other removed. * * @since 3.3 * @author Grégory Viguier * * @return string */ public function get_query_string() { return http_build_query( $this->get_query_params() ); } /** * Get the original query string * * @since 3.11.4 * * @return string */ public function get_original_query_string() { return http_build_query( $this->get_get() ); } /** ----------------------------------------------------------------------------------------- */ /** PROPERTY GETTERS ======================================================================== */ /** ----------------------------------------------------------------------------------------- */ /** * Get the `cookies` property. * * @since 3.3 * @author Grégory Viguier * * @return array */ public function get_cookies() { return self::$cookies; } /** * Get the `post` property. * * @since 3.3 * @author Grégory Viguier * * @return array */ public function get_post() { return self::$post; } /** * Get the `get` property. * * @since 3.3 * @author Grégory Viguier * * @return array */ public function get_get() { return self::$get; } /** ----------------------------------------------------------------------------------------- */ /** ERRORS ================================================================================== */ /** ----------------------------------------------------------------------------------------- */ /** * Set an "error". * * @since 3.3 * @author Grégory Viguier * * @param string $message A message. * @param array $data Related data. */ protected function set_error( $message, $data = [] ) { $this->last_error = [ 'message' => $message, 'data' => (array) $data, ]; } /** * Get the last "error". * * @since 3.3 * @author Grégory Viguier * * @return array */ public function get_last_error() { return array_merge( [ 'message' => '', 'data' => [], ], (array) $this->last_error ); } }