mirror of
https://github.com/gosticks/wordpress-develop.git
synced 2025-10-16 12:05:38 +00:00
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
324 lines
10 KiB
PHP
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 );
|
|
};
|
|
}
|
|
}
|