angelovcom.net

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

https-detection.php (6871B)


      1 <?php
      2 /**
      3  * HTTPS detection functions.
      4  *
      5  * @package WordPress
      6  * @since 5.7.0
      7  */
      8 
      9 /**
     10  * Checks whether the website is using HTTPS.
     11  *
     12  * This is based on whether both the home and site URL are using HTTPS.
     13  *
     14  * @since 5.7.0
     15  * @see wp_is_home_url_using_https()
     16  * @see wp_is_site_url_using_https()
     17  *
     18  * @return bool True if using HTTPS, false otherwise.
     19  */
     20 function wp_is_using_https() {
     21 	if ( ! wp_is_home_url_using_https() ) {
     22 		return false;
     23 	}
     24 
     25 	return wp_is_site_url_using_https();
     26 }
     27 
     28 /**
     29  * Checks whether the current site URL is using HTTPS.
     30  *
     31  * @since 5.7.0
     32  * @see home_url()
     33  *
     34  * @return bool True if using HTTPS, false otherwise.
     35  */
     36 function wp_is_home_url_using_https() {
     37 	return 'https' === wp_parse_url( home_url(), PHP_URL_SCHEME );
     38 }
     39 
     40 /**
     41  * Checks whether the current site's URL where WordPress is stored is using HTTPS.
     42  *
     43  * This checks the URL where WordPress application files (e.g. wp-blog-header.php or the wp-admin/ folder)
     44  * are accessible.
     45  *
     46  * @since 5.7.0
     47  * @see site_url()
     48  *
     49  * @return bool True if using HTTPS, false otherwise.
     50  */
     51 function wp_is_site_url_using_https() {
     52 	// Use direct option access for 'siteurl' and manually run the 'site_url'
     53 	// filter because `site_url()` will adjust the scheme based on what the
     54 	// current request is using.
     55 	/** This filter is documented in wp-includes/link-template.php */
     56 	$site_url = apply_filters( 'site_url', get_option( 'siteurl' ), '', null, null );
     57 
     58 	return 'https' === wp_parse_url( $site_url, PHP_URL_SCHEME );
     59 }
     60 
     61 /**
     62  * Checks whether HTTPS is supported for the server and domain.
     63  *
     64  * @since 5.7.0
     65  *
     66  * @return bool True if HTTPS is supported, false otherwise.
     67  */
     68 function wp_is_https_supported() {
     69 	$https_detection_errors = get_option( 'https_detection_errors' );
     70 
     71 	// If option has never been set by the Cron hook before, run it on-the-fly as fallback.
     72 	if ( false === $https_detection_errors ) {
     73 		wp_update_https_detection_errors();
     74 
     75 		$https_detection_errors = get_option( 'https_detection_errors' );
     76 	}
     77 
     78 	// If there are no detection errors, HTTPS is supported.
     79 	return empty( $https_detection_errors );
     80 }
     81 
     82 /**
     83  * Runs a remote HTTPS request to detect whether HTTPS supported, and stores potential errors.
     84  *
     85  * This internal function is called by a regular Cron hook to ensure HTTPS support is detected and maintained.
     86  *
     87  * @since 5.7.0
     88  * @access private
     89  */
     90 function wp_update_https_detection_errors() {
     91 	/**
     92 	 * Short-circuits the process of detecting errors related to HTTPS support.
     93 	 *
     94 	 * Returning a `WP_Error` from the filter will effectively short-circuit the default logic of trying a remote
     95 	 * request to the site over HTTPS, storing the errors array from the returned `WP_Error` instead.
     96 	 *
     97 	 * @since 5.7.0
     98 	 *
     99 	 * @param null|WP_Error $pre Error object to short-circuit detection,
    100 	 *                           or null to continue with the default behavior.
    101 	 */
    102 	$support_errors = apply_filters( 'pre_wp_update_https_detection_errors', null );
    103 	if ( is_wp_error( $support_errors ) ) {
    104 		update_option( 'https_detection_errors', $support_errors->errors );
    105 		return;
    106 	}
    107 
    108 	$support_errors = new WP_Error();
    109 
    110 	$response = wp_remote_request(
    111 		home_url( '/', 'https' ),
    112 		array(
    113 			'headers'   => array(
    114 				'Cache-Control' => 'no-cache',
    115 			),
    116 			'sslverify' => true,
    117 		)
    118 	);
    119 
    120 	if ( is_wp_error( $response ) ) {
    121 		$unverified_response = wp_remote_request(
    122 			home_url( '/', 'https' ),
    123 			array(
    124 				'headers'   => array(
    125 					'Cache-Control' => 'no-cache',
    126 				),
    127 				'sslverify' => false,
    128 			)
    129 		);
    130 
    131 		if ( is_wp_error( $unverified_response ) ) {
    132 			$support_errors->add(
    133 				'https_request_failed',
    134 				__( 'HTTPS request failed.' )
    135 			);
    136 		} else {
    137 			$support_errors->add(
    138 				'ssl_verification_failed',
    139 				__( 'SSL verification failed.' )
    140 			);
    141 		}
    142 
    143 		$response = $unverified_response;
    144 	}
    145 
    146 	if ( ! is_wp_error( $response ) ) {
    147 		if ( 200 !== wp_remote_retrieve_response_code( $response ) ) {
    148 			$support_errors->add( 'bad_response_code', wp_remote_retrieve_response_message( $response ) );
    149 		} elseif ( false === wp_is_local_html_output( wp_remote_retrieve_body( $response ) ) ) {
    150 			$support_errors->add( 'bad_response_source', __( 'It looks like the response did not come from this site.' ) );
    151 		}
    152 	}
    153 
    154 	update_option( 'https_detection_errors', $support_errors->errors );
    155 }
    156 
    157 /**
    158  * Schedules the Cron hook for detecting HTTPS support.
    159  *
    160  * @since 5.7.0
    161  * @access private
    162  */
    163 function wp_schedule_https_detection() {
    164 	if ( wp_installing() ) {
    165 		return;
    166 	}
    167 
    168 	if ( ! wp_next_scheduled( 'wp_https_detection' ) ) {
    169 		wp_schedule_event( time(), 'twicedaily', 'wp_https_detection' );
    170 	}
    171 }
    172 
    173 /**
    174  * Disables SSL verification if the 'cron_request' arguments include an HTTPS URL.
    175  *
    176  * This prevents an issue if HTTPS breaks, where there would be a failed attempt to verify HTTPS.
    177  *
    178  * @since 5.7.0
    179  * @access private
    180  *
    181  * @param array $request The Cron request arguments.
    182  * @return array $request The filtered Cron request arguments.
    183  */
    184 function wp_cron_conditionally_prevent_sslverify( $request ) {
    185 	if ( 'https' === wp_parse_url( $request['url'], PHP_URL_SCHEME ) ) {
    186 		$request['args']['sslverify'] = false;
    187 	}
    188 	return $request;
    189 }
    190 
    191 /**
    192  * Checks whether a given HTML string is likely an output from this WordPress site.
    193  *
    194  * This function attempts to check for various common WordPress patterns whether they are included in the HTML string.
    195  * Since any of these actions may be disabled through third-party code, this function may also return null to indicate
    196  * that it was not possible to determine ownership.
    197  *
    198  * @since 5.7.0
    199  * @access private
    200  *
    201  * @param string $html Full HTML output string, e.g. from a HTTP response.
    202  * @return bool|null True/false for whether HTML was generated by this site, null if unable to determine.
    203  */
    204 function wp_is_local_html_output( $html ) {
    205 	// 1. Check if HTML includes the site's Really Simple Discovery link.
    206 	if ( has_action( 'wp_head', 'rsd_link' ) ) {
    207 		$pattern = preg_replace( '#^https?:(?=//)#', '', esc_url( site_url( 'xmlrpc.php?rsd', 'rpc' ) ) ); // See rsd_link().
    208 		return false !== strpos( $html, $pattern );
    209 	}
    210 
    211 	// 2. Check if HTML includes the site's Windows Live Writer manifest link.
    212 	if ( has_action( 'wp_head', 'wlwmanifest_link' ) ) {
    213 		// Try both HTTPS and HTTP since the URL depends on context.
    214 		$pattern = preg_replace( '#^https?:(?=//)#', '', includes_url( 'wlwmanifest.xml' ) ); // See wlwmanifest_link().
    215 		return false !== strpos( $html, $pattern );
    216 	}
    217 
    218 	// 3. Check if HTML includes the site's REST API link.
    219 	if ( has_action( 'wp_head', 'rest_output_link_wp_head' ) ) {
    220 		// Try both HTTPS and HTTP since the URL depends on context.
    221 		$pattern = preg_replace( '#^https?:(?=//)#', '', esc_url( get_rest_url() ) ); // See rest_output_link_wp_head().
    222 		return false !== strpos( $html, $pattern );
    223 	}
    224 
    225 	// Otherwise the result cannot be determined.
    226 	return null;
    227 }