Changeset 60919
- Timestamp:
- 10/09/2025 11:36:10 PM (5 weeks ago)
- Location:
- trunk
- Files:
-
- 4 edited
-
src/wp-includes/html-api/class-wp-html-processor.php (modified) (1 diff)
-
src/wp-includes/html-api/class-wp-html-tag-processor.php (modified) (4 diffs)
-
tests/phpunit/tests/block-supports/wpRenderBackgroundSupport.php (modified) (5 diffs)
-
tests/phpunit/tests/html-api/wpHtmlTagProcessor.php (modified) (6 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/html-api/class-wp-html-processor.php
r60887 r60919 5291 5291 * Updates or creates a new attribute on the currently matched tag with the passed value. 5292 5292 * 5293 * For boolean attributes special handling is provided: 5293 * This function handles all necessary HTML encoding. Provide normal, unescaped string values. 5294 * The HTML API will encode the strings appropriately so that the browser will interpret them 5295 * as the intended value. 5296 * 5297 * Example: 5298 * 5299 * // Renders “Eggs & Milk” in a browser, encoded as `<abbr title="Eggs & Milk">`. 5300 * $processor->set_attribute( 'title', 'Eggs & Milk' ); 5301 * 5302 * // Renders “Eggs & Milk” in a browser, encoded as `<abbr title="Eggs &amp; Milk">`. 5303 * $processor->set_attribute( 'title', 'Eggs & Milk' ); 5304 * 5305 * // Renders `true` as `<abbr title>`. 5306 * $processor->set_attribute( 'title', true ); 5307 * 5308 * // Renders without the attribute for `false` as `<abbr>`. 5309 * $processor->set_attribute( 'title', false ); 5310 * 5311 * Special handling is provided for boolean attribute values: 5294 5312 * - When `true` is passed as the value, then only the attribute name is added to the tag. 5295 5313 * - When `false` is passed, the attribute gets removed if it existed before. 5296 5314 * 5297 * For string attributes, the value is escaped using the `esc_attr` function.5298 *5299 5315 * @since 6.6.0 Subclassed for the HTML Processor. 5316 * @since 6.9.0 Escapes all character references instead of trying to avoid double-escaping. 5300 5317 * 5301 5318 * @param string $name The attribute name to target. -
trunk/src/wp-includes/html-api/class-wp-html-tag-processor.php
r60887 r60919 3747 3747 * } 3748 3748 * 3749 * This function handles all necessary HTML encoding. Provide normal, unescaped string values. 3750 * The HTML API will encode the strings appropriately so that the browser will interpret them 3751 * as the intended value. 3752 * 3753 * Example: 3754 * 3755 * // Renders as “Eggs & Milk” in a browser, encoded as `<p>Eggs & Milk</p>`. 3756 * $processor->set_modifiable_text( 'Eggs & Milk' ); 3757 * 3758 * // Renders as “Eggs & Milk” in a browser, encoded as `<p>Eggs &amp; Milk</p>`. 3759 * $processor->set_modifiable_text( 'Eggs & Milk' ); 3760 * 3749 3761 * @since 6.7.0 3762 * @since 6.9.0 Escapes all character references instead of trying to avoid double-escaping. 3750 3763 * 3751 3764 * @param string $plaintext_content New text content to represent in the matched token. 3752 *3753 3765 * @return bool Whether the text was able to update. 3754 3766 */ … … 3758 3770 $this->text_starts_at, 3759 3771 $this->text_length, 3760 htmlspecialchars( $plaintext_content, ENT_QUOTES | ENT_HTML5 ) 3772 strtr( 3773 $plaintext_content, 3774 array( 3775 '<' => '<', 3776 '>' => '>', 3777 '&' => '&', 3778 '"' => '"', 3779 "'" => ''', 3780 ) 3781 ) 3761 3782 ); 3762 3783 … … 3872 3893 * Updates or creates a new attribute on the currently matched tag with the passed value. 3873 3894 * 3874 * For boolean attributes special handling is provided: 3895 * This function handles all necessary HTML encoding. Provide normal, unescaped string values. 3896 * The HTML API will encode the strings appropriately so that the browser will interpret them 3897 * as the intended value. 3898 * 3899 * Example: 3900 * 3901 * // Renders “Eggs & Milk” in a browser, encoded as `<abbr title="Eggs & Milk">`. 3902 * $processor->set_attribute( 'title', 'Eggs & Milk' ); 3903 * 3904 * // Renders “Eggs & Milk” in a browser, encoded as `<abbr title="Eggs &amp; Milk">`. 3905 * $processor->set_attribute( 'title', 'Eggs & Milk' ); 3906 * 3907 * // Renders `true` as `<abbr title>`. 3908 * $processor->set_attribute( 'title', true ); 3909 * 3910 * // Renders without the attribute for `false` as `<abbr>`. 3911 * $processor->set_attribute( 'title', false ); 3912 * 3913 * Special handling is provided for boolean attribute values: 3875 3914 * - When `true` is passed as the value, then only the attribute name is added to the tag. 3876 3915 * - When `false` is passed, the attribute gets removed if it existed before. 3877 3916 * 3878 * For string attributes, the value is escaped using the `esc_attr` function.3879 *3880 3917 * @since 6.2.0 3881 3918 * @since 6.2.1 Fix: Only create a single update for multiple calls with case-variant attribute names. 3919 * @since 6.9.0 Escapes all character references instead of trying to avoid double-escaping. 3882 3920 * 3883 3921 * @param string $name The attribute name to target. … … 3951 3989 $comparable_name = strtolower( $name ); 3952 3990 3953 /* 3954 * Escape URL attributes.3991 /** 3992 * Escape attribute values appropriately. 3955 3993 * 3956 3994 * @see https://html.spec.whatwg.org/#attributes-3 3957 3995 */ 3958 $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes(), true ) ? esc_url( $value ) : esc_attr( $value ); 3996 $escaped_new_value = in_array( $comparable_name, wp_kses_uri_attributes(), true ) 3997 ? esc_url( $value ) 3998 : strtr( 3999 $value, 4000 array( 4001 '<' => '<', 4002 '>' => '>', 4003 '&' => '&', 4004 '"' => '"', 4005 "'" => ''', 4006 ) 4007 ); 3959 4008 3960 4009 // If the escaping functions wiped out the update, reject it and indicate it was rejected. -
trunk/tests/phpunit/tests/block-supports/wpRenderBackgroundSupport.php
r60727 r60919 139 139 ), 140 140 ), 141 'expected_wrapper' => '<div class="has-background" style="background-image:url(& #039;https://example.com/image.jpg');background-size:cover;">Content</div>',141 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', 142 142 'wrapper' => '<div>Content</div>', 143 143 ), … … 156 156 'backgroundAttachment' => 'fixed', 157 157 ), 158 'expected_wrapper' => '<div class="has-background" style="background-image:url(& #039;https://example.com/image.jpg');background-position:50% 50%;background-repeat:no-repeat;background-size:contain;background-attachment:fixed;">Content</div>',158 'expected_wrapper' => '<div class="has-background" style="background-image:url('https://example.com/image.jpg');background-position:50% 50%;background-repeat:no-repeat;background-size:contain;background-attachment:fixed;">Content</div>', 159 159 'wrapper' => '<div>Content</div>', 160 160 ), … … 170 170 ), 171 171 ), 172 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;background-image:url(& #039;https://example.com/image.jpg');background-size:cover;">Content</div>',172 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', 173 173 'wrapper' => '<div class="wp-block-test" style="color: red">Content</div>', 174 174 ), … … 184 184 ), 185 185 ), 186 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;font-size: 15px;background-image:url(& #039;https://example.com/image.jpg');background-size:cover;">Content</div>',186 'expected_wrapper' => '<div class="wp-block-test has-background" style="color: red;font-size: 15px;background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', 187 187 'wrapper' => '<div class="wp-block-test" style="color: red;font-size: 15px;">Content</div>', 188 188 ), … … 199 199 ), 200 200 ), 201 'expected_wrapper' => '<div class="has-background" classname="wp-block-test" style="background-image:url(& #039;https://example.com/image.jpg');background-size:cover;">Content</div>',201 'expected_wrapper' => '<div class="has-background" classname="wp-block-test" style="background-image:url('https://example.com/image.jpg');background-size:cover;">Content</div>', 202 202 'wrapper' => '<div classname="wp-block-test" style>Content</div>', 203 203 ), -
trunk/tests/phpunit/tests/html-api/wpHtmlTagProcessor.php
r60887 r60919 842 842 * @param string $attribute_value A value with potential XSS exploit. 843 843 */ 844 public function test_set_attribute_prevents_xss( $attribute_value ) {844 public function test_set_attribute_prevents_xss( $attribute_value, $escaped_attribute_value = null ) { 845 845 $processor = new WP_HTML_Tag_Processor( '<div></div>' ); 846 846 $processor->next_tag(); … … 862 862 list( , $actual_value ) = $match; 863 863 864 $this->assertSame( '"' . esc_attr( $attribute_value ). '"', $actual_value, 'Entities were not properly escaped in the attribute value' );864 $this->assertSame( '"' . $escaped_attribute_value . '"', $actual_value, 'Entities were not properly escaped in the attribute value' ); 865 865 } 866 866 … … 872 872 public static function data_set_attribute_prevents_xss() { 873 873 return array( 874 array( '"' ), 875 array( '"' ), 876 array( '&' ), 877 array( '&' ), 878 array( '€' ), 879 array( "'" ), 880 array( '<>' ), 881 array( '"";' ), 882 array( '" onclick="alert(\'1\');"><span onclick=""></span><script>alert("1")</script>' ), 874 array( '"', '"' ), 875 array( '"', '&quot;' ), 876 array( '&', '&' ), 877 array( '&', '&amp;' ), 878 array( '€', '&euro;' ), 879 array( "'", ''' ), 880 array( '<>', '<>' ), 881 array( '"";', '&quot";' ), 882 array( 883 '" onclick="alert(\'1\');"><span onclick=""></span><script>alert("1")</script>', 884 '" onclick="alert('1');"><span onclick=""></span><script>alert("1")</script>', 885 ), 883 886 ); 884 887 } … … 904 907 'get_attribute() (called after get_updated_html()) did not return attribute added via set_attribute()' 905 908 ); 909 } 910 911 /** 912 * Ensure that attribute values that appear to contain HTML character references are correctly 913 * encoded and preserve the original value. 914 * 915 * @ticket 64054 916 */ 917 public function test_set_attribute_encodes_html_character_references() { 918 $original = 'HTML character references: < > &'; 919 $processor = new WP_HTML_Tag_Processor( '<span>' ); 920 $processor->next_tag(); 921 $processor->set_attribute( 'data-attr', $original ); 922 $this->assertSame( $original, $processor->get_attribute( 'data-attr' ) ); 923 $this->assertEqualHTML( '<span data-attr="HTML character references: &lt; &gt; &amp;">', $processor->get_updated_html() ); 906 924 } 907 925 … … 2787 2805 $processor->add_class( 'secondTag' ); 2788 2806 2789 $this->assert Same(2807 $this->assertEqualHTML( 2790 2808 $expected, 2791 2809 $processor->get_updated_html(), 2810 '<body>', 2792 2811 'Did not properly update attributes and classnames given malformed input' 2793 2812 ); … … 2807 2826 'HTML tag opening inside attribute value' => array( 2808 2827 'input' => '<pre id="<code" class="wp-block-code <code is poetry>"><code>This <is> a <strong is="true">thing.</code></pre><span>test</span>', 2809 'expected' => '<pre foo="bar" id="<code" class="wp-block-code <code is poetry& gt; firstTag"><code class="secondTag">This <is> a <strong is="true">thing.</code></pre><span>test</span>',2828 'expected' => '<pre foo="bar" id="<code" class="wp-block-code <code is poetry&gt; firstTag"><code class="secondTag">This <is> a <strong is="true">thing.</code></pre><span>test</span>', 2810 2829 ), 2811 2830 'HTML tag brackets in attribute values and data markup' => array( 2812 2831 'input' => '<pre id="<code->-block->" class="wp-block-code <code is poetry>"><code>This <is> a <strong is="true">thing.</code></pre><span>test</span>', 2813 'expected' => '<pre foo="bar" id="<code->-block->" class="wp-block-code <code is poetry& gt; firstTag"><code class="secondTag">This <is> a <strong is="true">thing.</code></pre><span>test</span>',2832 'expected' => '<pre foo="bar" id="<code->-block->" class="wp-block-code <code is poetry&gt; firstTag"><code class="secondTag">This <is> a <strong is="true">thing.</code></pre><span>test</span>', 2814 2833 ), 2815 2834 'Single and double quotes in attribute value' => array(
Note: See TracChangeset
for help on using the changeset viewer.