wordpress-develop/tests/phpunit/tests/https-detection.php
Sergey Biryukov fd6c5606b1 Coding Standards: Include one space after function keyword for closures.
Note: This is enforced by WPCS 3.0.0.

Reference: [https://github.com/WordPress/WordPress-Coding-Standards/pull/2328 WPCS: PR #2328 Core: properly check formatting of function declaration statements].

Props jrf.
See #59161, #58831.

git-svn-id: https://develop.svn.wordpress.org/trunk@56559 602fd350-edb4-49c9-b593-d223f7449a82
2023-09-12 15:21:02 +00:00

324 lines
10 KiB
PHP

<?php
/**
* @group https-detection
*/
class Tests_HTTPS_Detection extends WP_UnitTestCase {
private $last_request_url;
public function set_up() {
parent::set_up();
remove_all_filters( 'option_home' );
remove_all_filters( 'option_siteurl' );
remove_all_filters( 'home_url' );
remove_all_filters( 'site_url' );
}
/**
* @ticket 47577
*/
public function test_wp_is_using_https() {
update_option( 'home', 'http://example.com/' );
update_option( 'siteurl', 'http://example.com/' );
$this->assertFalse( wp_is_using_https() );
// Expect false if only one of the two relevant URLs is HTTPS.
update_option( 'siteurl', 'https://example.com/' );
$this->assertFalse( wp_is_using_https() );
update_option( 'home', 'https://example.com/' );
$this->assertTrue( wp_is_using_https() );
// Test that the manually included 'site_url' filter works as expected
// by using it to set the URL to use HTTP.
add_filter( 'site_url', $this->filter_set_url_scheme( 'http' ) );
$this->assertFalse( wp_is_using_https() );
}
/**
* @ticket 47577
*/
public function test_wp_is_https_supported() {
// The function works with cached errors, so only test that here.
$wp_error = new WP_Error();
// No errors, so HTTPS is supported.
update_option( 'https_detection_errors', $wp_error->errors );
$this->assertTrue( wp_is_https_supported() );
// Errors, so HTTPS is not supported.
$wp_error->add( 'ssl_verification_failed', 'SSL verification failed.' );
update_option( 'https_detection_errors', $wp_error->errors );
$this->assertFalse( wp_is_https_supported() );
}
/**
* @ticket 47577
* @ticket 52484
*/
public function test_wp_update_https_detection_errors() {
// Set HTTP URL, the request below should use its HTTPS version.
update_option( 'home', 'http://example.com/' );
add_filter( 'pre_http_request', array( $this, 'record_request_url' ), 10, 3 );
// If initial request succeeds, all good.
add_filter( 'pre_http_request', array( $this, 'mock_success_with_sslverify' ), 10, 2 );
wp_update_https_detection_errors();
$this->assertSame( array(), get_option( 'https_detection_errors' ) );
// If initial request fails and request without SSL verification succeeds,
// return 'ssl_verification_failed' error.
add_filter( 'pre_http_request', array( $this, 'mock_error_with_sslverify' ), 10, 2 );
add_filter( 'pre_http_request', array( $this, 'mock_success_without_sslverify' ), 10, 2 );
wp_update_https_detection_errors();
$this->assertSame(
array( 'ssl_verification_failed' => array( __( 'SSL verification failed.' ) ) ),
get_option( 'https_detection_errors' )
);
// If both initial request and request without SSL verification fail,
// return 'https_request_failed' error.
add_filter( 'pre_http_request', array( $this, 'mock_error_with_sslverify' ), 10, 2 );
add_filter( 'pre_http_request', array( $this, 'mock_error_without_sslverify' ), 10, 2 );
wp_update_https_detection_errors();
$this->assertSame(
array( 'https_request_failed' => array( __( 'HTTPS request failed.' ) ) ),
get_option( 'https_detection_errors' )
);
// If request succeeds, but response is not 200, return error with
// 'bad_response_code' error code.
add_filter( 'pre_http_request', array( $this, 'mock_not_found' ), 10, 2 );
wp_update_https_detection_errors();
$this->assertSame(
array( 'bad_response_code' => array( 'Not Found' ) ),
get_option( 'https_detection_errors' )
);
// If request succeeds, but response was not generated by this
// WordPress site, return error with 'bad_response_source' error code.
add_filter( 'pre_http_request', array( $this, 'mock_bad_source' ), 10, 2 );
wp_update_https_detection_errors();
$this->assertSame(
array( 'bad_response_source' => array( 'It looks like the response did not come from this site.' ) ),
get_option( 'https_detection_errors' )
);
// Check that the requests are made to the correct URL.
$this->assertSame( 'https://example.com/', $this->last_request_url );
}
/**
* @ticket 47577
*/
public function test_pre_wp_update_https_detection_errors() {
// Override to enforce no errors being detected.
add_filter(
'pre_wp_update_https_detection_errors',
static function () {
return new WP_Error();
}
);
wp_update_https_detection_errors();
$this->assertSame( array(), get_option( 'https_detection_errors' ) );
// Override to enforce an error being detected.
add_filter(
'pre_wp_update_https_detection_errors',
static function () {
return new WP_Error(
'ssl_verification_failed',
'Bad SSL certificate.'
);
}
);
wp_update_https_detection_errors();
$this->assertSame(
array( 'ssl_verification_failed' => array( 'Bad SSL certificate.' ) ),
get_option( 'https_detection_errors' )
);
}
/**
* @ticket 47577
*/
public function test_wp_schedule_https_detection() {
wp_schedule_https_detection();
$this->assertSame( 'twicedaily', wp_get_schedule( 'wp_https_detection' ) );
}
/**
* @ticket 47577
*/
public function test_wp_cron_conditionally_prevent_sslverify() {
// If URL is not using HTTPS, don't set 'sslverify' to false.
$request = array(
'url' => 'http://example.com/',
'args' => array( 'sslverify' => true ),
);
$this->assertSame( $request, wp_cron_conditionally_prevent_sslverify( $request ) );
// If URL is using HTTPS, set 'sslverify' to false.
$request = array(
'url' => 'https://example.com/',
'args' => array( 'sslverify' => true ),
);
$expected = $request;
$expected['args']['sslverify'] = false;
$this->assertSame( $expected, wp_cron_conditionally_prevent_sslverify( $request ) );
}
/**
* @ticket 47577
* @ticket 52542
*/
public function test_wp_is_local_html_output_via_rsd_link() {
// HTML includes RSD link.
$head_tag = get_echo( 'rsd_link' );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML includes modified RSD link but same URL.
$head_tag = str_replace( ' />', '>', get_echo( 'rsd_link' ) );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML includes RSD link with alternative URL scheme.
$head_tag = get_echo( 'rsd_link' );
$head_tag = false !== strpos( $head_tag, 'https://' ) ? str_replace( 'https://', 'http://', $head_tag ) : str_replace( 'http://', 'https://', $head_tag );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML does not include RSD link.
$html = $this->get_sample_html_string();
$this->assertFalse( wp_is_local_html_output( $html ) );
}
/**
* @ticket 47577
*/
public function test_wp_is_local_html_output_via_rest_link() {
remove_action( 'wp_head', 'rsd_link' );
// HTML includes REST API link.
$head_tag = get_echo( 'rest_output_link_wp_head' );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML includes modified REST API link but same URL.
$head_tag = str_replace( ' />', '>', get_echo( 'rest_output_link_wp_head' ) );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML includes REST API link with alternative URL scheme.
$head_tag = get_echo( 'rest_output_link_wp_head' );
$head_tag = false !== strpos( $head_tag, 'https://' ) ? str_replace( 'https://', 'http://', $head_tag ) : str_replace( 'http://', 'https://', $head_tag );
$html = $this->get_sample_html_string( $head_tag );
$this->assertTrue( wp_is_local_html_output( $html ) );
// HTML does not include REST API link.
$html = $this->get_sample_html_string();
$this->assertFalse( wp_is_local_html_output( $html ) );
}
/**
* @ticket 47577
*/
public function test_wp_is_local_html_output_cannot_determine() {
remove_action( 'wp_head', 'rsd_link' );
remove_action( 'wp_head', 'rest_output_link_wp_head' );
// The HTML here doesn't matter because all hooks are removed.
$html = $this->get_sample_html_string();
$this->assertNull( wp_is_local_html_output( $html ) );
}
public function record_request_url( $response, $parsed_args, $url ) {
$this->last_request_url = $url;
return $response;
}
public function mock_success_with_sslverify( $response, $parsed_args ) {
if ( ! empty( $parsed_args['sslverify'] ) ) {
return $this->mock_success();
}
return $response;
}
public function mock_error_with_sslverify( $response, $parsed_args ) {
if ( ! empty( $parsed_args['sslverify'] ) ) {
return $this->mock_error();
}
return $response;
}
public function mock_success_without_sslverify( $response, $parsed_args ) {
if ( empty( $parsed_args['sslverify'] ) ) {
return $this->mock_success();
}
return $response;
}
public function mock_error_without_sslverify( $response, $parsed_args ) {
if ( empty( $parsed_args['sslverify'] ) ) {
return $this->mock_error();
}
return $response;
}
public function mock_not_found() {
return array(
'body' => '<!DOCTYPE html><html><head><title>404</title></head><body>Not Found</body></html>',
'response' => array(
'code' => 404,
'message' => 'Not Found',
),
);
}
public function mock_bad_source() {
// Looks like a success response, but is not generated by WordPress (e.g. missing RSD link).
return array(
'body' => $this->get_sample_html_string(),
'response' => array(
'code' => 200,
'message' => 'OK',
),
);
}
private function mock_success() {
// Success response containing RSD link.
return array(
'body' => $this->get_sample_html_string( get_echo( 'rsd_link' ) ),
'response' => array(
'code' => 200,
'message' => 'OK',
),
);
}
private function mock_error() {
return new WP_Error( 'bad_ssl_certificate', 'Bad SSL certificate.' );
}
private function get_sample_html_string( $head_tag = '' ) {
return '<!DOCTYPE html><html><head><title>Page Title</title>' . $head_tag . '</head><body>Page Content.</body></html>';
}
/**
* Returns a filter callback that expects a URL and will set the URL scheme
* to the provided $scheme.
*
* @param string $scheme URL scheme to set.
* @return callable Filter callback.
*/
private function filter_set_url_scheme( $scheme ) {
return static function ( $url ) use ( $scheme ) {
return set_url_scheme( $url, $scheme );
};
}
}