Skip to content

Commit fc35354

Browse files
committed
General: Improve parsing of sent HTTP Content-Type header to detect HTML response.
This improves adherence to the HTTP spec in extracting the header name and value. Developed in #10293 Follow-up to [60936]. Props dmsnell, westonruter. See #43258. git-svn-id: https://develop.svn.wordpress.org/trunk@60973 602fd350-edb4-49c9-b593-d223f7449a82
1 parent b84fc32 commit fc35354

File tree

2 files changed

+30
-5
lines changed

2 files changed

+30
-5
lines changed

src/wp-includes/template.php

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -926,13 +926,24 @@ function wp_finalize_template_enhancement_output_buffer( string $output, int $ph
926926
$is_html_content_type = null;
927927
$html_content_types = array( 'text/html', 'application/xhtml+xml' );
928928
foreach ( headers_list() as $header ) {
929-
$header_parts = preg_split( '/\s*[:;]\s*/', strtolower( $header ) );
929+
$header_parts = explode( ':', strtolower( $header ), 2 );
930930
if (
931-
is_array( $header_parts ) &&
932-
count( $header_parts ) >= 2 &&
931+
count( $header_parts ) === 2 &&
933932
'content-type' === $header_parts[0]
934933
) {
935-
$is_html_content_type = in_array( $header_parts[1], $html_content_types, true );
934+
/*
935+
* This is looking for very specific content types, therefore it
936+
* doesn’t need to fully parse the header’s value. Instead, it needs
937+
* only assert that the content type is one of the static HTML types.
938+
*
939+
* Example:
940+
*
941+
* Content-Type: text/html; charset=utf8
942+
* Content-Type: text/html ;charset=latin4
943+
* Content-Type:application/xhtml+xml
944+
*/
945+
$media_type = trim( strtok( $header_parts[1], ';' ), " \t" );
946+
$is_html_content_type = in_array( $media_type, $html_content_types, true );
936947
break; // PHP only sends the first Content-Type header in the list.
937948
}
938949
}

tests/phpunit/tests/template.php

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -597,6 +597,9 @@ static function ( string $buffer ) use ( &$filter_args ): string {
597597
PHP_INT_MAX
598598
);
599599

600+
$this->assertCount( 0, headers_list(), 'Expected no headers to have been sent during unit tests.' );
601+
ini_set( 'default_mimetype', 'text/html' ); // Since sending a header won't work.
602+
600603
$initial_ob_level = ob_get_level();
601604
$this->assertTrue( wp_start_template_enhancement_output_buffer(), 'Expected wp_start_template_enhancement_output_buffer() to return true indicating the output buffer started.' );
602605
$this->assertSame( 1, did_action( 'wp_template_enhancement_output_buffer_started' ), 'Expected the wp_template_enhancement_output_buffer_started action to have fired.' );
@@ -676,6 +679,9 @@ static function ( string $buffer ) use ( &$applied_filter ): string {
676679
}
677680
);
678681

682+
$this->assertCount( 0, headers_list(), 'Expected no headers to have been sent during unit tests.' );
683+
ini_set( 'default_mimetype', 'text/html' ); // Since sending a header won't work.
684+
679685
$initial_ob_level = ob_get_level();
680686
$this->assertTrue( wp_start_template_enhancement_output_buffer(), 'Expected wp_start_template_enhancement_output_buffer() to return true indicating the output buffer started.' );
681687
$this->assertSame( 1, did_action( 'wp_template_enhancement_output_buffer_started' ), 'Expected the wp_template_enhancement_output_buffer_started action to have fired.' );
@@ -740,6 +746,9 @@ static function ( string $buffer ) use ( &$called_filter ): string {
740746
}
741747
);
742748

749+
$this->assertCount( 0, headers_list(), 'Expected no headers to have been sent during unit tests.' );
750+
ini_set( 'default_mimetype', 'application/xhtml+xml' ); // Since sending a header won't work.
751+
743752
$initial_ob_level = ob_get_level();
744753
$this->assertTrue( wp_start_template_enhancement_output_buffer(), 'Expected wp_start_template_enhancement_output_buffer() to return true indicating the output buffer started.' );
745754
$this->assertSame( 1, did_action( 'wp_template_enhancement_output_buffer_started' ), 'Expected the wp_template_enhancement_output_buffer_started action to have fired.' );
@@ -749,15 +758,18 @@ static function ( string $buffer ) use ( &$called_filter ): string {
749758
<!DOCTYPE html>
750759
<html lang="en">
751760
<head>
761+
<meta charset="utf-8">
752762
<title>Unprocessed</title>
753763
</head>
754764
<body>
755765
<h1>Hello World!</h1>
756766
<!-- ... -->
757767
<?php ob_clean(); // Clean the buffer started by wp_start_template_enhancement_output_buffer(), allowing the following document to replace the above.. ?>
768+
<?php echo '<?xml version="1.0" encoding="UTF-8"?>'; ?>
758769
<!DOCTYPE html>
759-
<html lang="en">
770+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
760771
<head>
772+
<meta charset="utf-8" />
761773
<title>Template Replaced</title>
762774
</head>
763775
<body>
@@ -799,7 +811,9 @@ public function test_wp_start_template_enhancement_output_buffer_for_json(): voi
799811
$this->assertSame( 1, did_action( 'wp_template_enhancement_output_buffer_started' ), 'Expected the wp_template_enhancement_output_buffer_started action to have fired.' );
800812
$this->assertSame( $initial_ob_level + 1, ob_get_level(), 'Expected the output buffer level to have been incremented.' );
801813

814+
$this->assertCount( 0, headers_list(), 'Expected no headers to have been sent during unit tests.' );
802815
ini_set( 'default_mimetype', 'application/json' ); // Since sending a header won't work.
816+
803817
$json = wp_json_encode(
804818
array(
805819
'success' => true,

0 commit comments

Comments
 (0)