Make WordPress Core

Ticket #43187: 43187.10.diff

File 43187.10.diff, 9.3 KB (added by azaozz, 7 years ago)
  • src/wp-includes/default-filters.php

     
    104104        add_filter( $filter, 'balanceTags', 50 );
    105105}
    106106
     107// Add proper rel values for links with target.
     108foreach ( array( 'title_save_pre', 'content_save_pre', 'excerpt_save_pre', 'content_filtered_save_pre', 'pre_comment_content' ) as $filter ) {
     109        add_filter( $filter, 'wp_targeted_link_rel' );
     110};
     111
    107112// Format strings for display.
    108113foreach ( array( 'comment_author', 'term_name', 'link_name', 'link_description', 'link_notes', 'bloginfo', 'wp_title', 'widget_title' ) as $filter ) {
    109114        add_filter( $filter, 'wptexturize' );
  • src/wp-includes/formatting.php

     
    30243024}
    30253025
    30263026/**
     3027 * Adds rel noreferrer and noopener to all HTML A elements that have a target.
     3028 *
     3029 * @param string $text Content that may contain HTML A elements.
     3030 * @return string Converted content.
     3031 */
     3032function wp_targeted_link_rel( $text ) {
     3033        $text = preg_replace_callback( '|<a\s([^>]*target\s*=[^>]*)>|i', 'wp_targeted_link_rel_callback', $text );
     3034        return $text;
     3035}
     3036
     3037/**
     3038 * Callback to add rel="noreferrer noopener" string to HTML A element.
     3039 *
     3040 * Will not duplicate existing noreferrer and noopener values
     3041 * to prevent from invalidating the HTML.
     3042 *
     3043 * @param array $matches Single Match
     3044 * @return string HTML A Element with rel noreferrer noopener in addition to any existing values
     3045 */
     3046function wp_targeted_link_rel_callback( $matches ) {
     3047        $link_html = $matches[1];
     3048        $rel_match = array();
     3049
     3050        /**
     3051         * Filters the rel values that are added to links with `target` attribute.
     3052         *
     3053         * @since 5.0.0
     3054         *
     3055         * @param string The rel values.
     3056         * @param string $link_html The matched content of the link tag including all HTML attributes.
     3057         */
     3058        $rel = apply_filters( 'wp_targeted_link_rel', 'noopener noreferrer', $link_html );
     3059
     3060        // Value with delimiters, spaces around are optional.
     3061        $attr_regex  = '|rel\s*=\s*?(\\\\{0,1}["\'])(.*?)\\1|i';
     3062        preg_match( $attr_regex, $link_html, $rel_match );
     3063
     3064        if ( empty( $rel_match[0] ) ) {
     3065                // No delimiters, try with a single value and spaces, because `rel =  va"lue` is totally fine...
     3066                $attr_regex  = '|rel\s*=(\s*)([^\s]*)|i';
     3067                preg_match( $attr_regex, $link_html, $rel_match );
     3068        }
     3069
     3070        if ( ! empty( $rel_match[0] ) ) {
     3071                $parts = preg_split( '|\s+|', strtolower( $rel_match[2] ) );
     3072                $parts = array_map( 'esc_attr', $parts );
     3073                $needed = explode( ' ', $rel );
     3074                $parts = array_unique( array_merge( $parts, $needed ) );
     3075                $delimiter = trim( $rel_match[1] ) ? $rel_match[1] : '"';
     3076                $rel = 'rel=' . $delimiter . trim( implode( ' ', $parts ) ) . $delimiter;
     3077                $link_html = str_replace( $rel_match[0], $rel, $link_html );
     3078        } else {
     3079                $link_html .= " rel=\"$rel\"";
     3080        }
     3081
     3082        return "<a $link_html>";
     3083}
     3084
     3085/**
    30273086 * Convert one smiley code to the icon graphic file equivalent.
    30283087 *
    30293088 * Callback handler for convert_smilies().
  • tests/phpunit/tests/formatting/WPTargetedLinkRel.php

     
     1<?php
     2
     3/**
     4 * @group formatting
     5 * @ticket 43187
     6 */
     7class Tests_Targeted_Link_Rel extends WP_UnitTestCase {
     8
     9        public function test_add_to_links_with_target_blank() {
     10                $content  = '<p>Links: <a href="/" target="_blank">No rel</a></p>';
     11                $expected = '<p>Links: <a href="/" target="_blank" rel="noopener noreferrer">No rel</a></p>';
     12                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     13        }
     14
     15        public function test_add_to_links_with_target_foo() {
     16                $content  = '<p>Links: <a href="/" target="foo">No rel</a></p>';
     17                $expected = '<p>Links: <a href="/" target="foo" rel="noopener noreferrer">No rel</a></p>';
     18                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     19        }
     20
     21        public function test_target_as_first_attribute() {
     22                $content  = '<p>Links: <a target="_blank" href="#">No rel</a></p>';
     23                $expected = '<p>Links: <a target="_blank" href="#" rel="noopener noreferrer">No rel</a></p>';
     24                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     25        }
     26
     27        public function test_add_to_existing_rel() {
     28                $content  = '<p>Links: <a href="/" rel="existing values" target="_blank">Existing rel</a></p>';
     29                $expected = '<p>Links: <a href="/" rel="existing values noopener noreferrer" target="_blank">Existing rel</a></p>';
     30                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     31        }
     32
     33        public function test_no_duplicate_values_added() {
     34                $content  = '<p>Links: <a href="/" rel="existing noopener values" target="_blank">Existing rel</a></p>';
     35                $expected = '<p>Links: <a href="/" rel="existing noopener values noreferrer" target="_blank">Existing rel</a></p>';
     36                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     37        }
     38
     39        public function test_rel_with_single_quote_delimiter() {
     40                $content  = '<p>Links: <a href="/" rel=\'existing values\' target="_blank">Existing rel</a></p>';
     41                $expected = '<p>Links: <a href="/" rel=\'existing values noopener noreferrer\' target="_blank">Existing rel</a></p>';
     42                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     43        }
     44
     45        public function test_rel_with_no_delimiter() {
     46                $content  = '<p>Links: <a href="/" rel=existing target="_blank">Existing rel</a></p>';
     47                $expected = '<p>Links: <a href="/" rel="existing noopener noreferrer" target="_blank">Existing rel</a></p>';
     48                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     49        }
     50
     51        public function test_rel_value_spaced_and_no_delimiter() {
     52                $content  = '<p>Links: <a href="/" rel = existing target="_blank">Existing rel</a></p>';
     53                $expected = '<p>Links: <a href="/" rel="existing noopener noreferrer" target="_blank">Existing rel</a></p>';
     54                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     55        }
     56
     57        public function test_rel_value_spaced_and_no_delimiter_and_values_to_escape() {
     58                $content  = '<p>Links: <a href="/" rel = existing"value target="_blank">Existing rel</a></p>';
     59                $expected = '<p>Links: <a href="/" rel="existing&quot;value noopener noreferrer" target="_blank">Existing rel</a></p>';
     60                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     61        }
     62
     63        public function test_escaped_quotes() {
     64                $content  = '<p>Links: <a href=\"/\" rel=\"existing values\" target=\"_blank\">Existing rel</a></p>';
     65                $expected = '<p>Links: <a href=\"/\" rel=\"existing values noopener noreferrer\" target=\"_blank\">Existing rel</a></p>';
     66                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     67        }
     68
     69        public function test_ignore_links_with_no_target() {
     70                $content  = '<p>Links: <a href="/" target="_blank">Change me</a> <a href="/">Do not change me</a></p>';
     71                $expected = '<p>Links: <a href="/" target="_blank" rel="noopener noreferrer">Change me</a> <a href="/">Do not change me</a></p>';
     72                $this->assertEquals( $expected, wp_targeted_link_rel( $content ) );
     73        }
     74}
  • tests/phpunit/tests/rest-api/rest-attachments-controller.php

     
    10151015                                                'rendered' => '<a href="#">link</a>',
    10161016                                        ),
    10171017                                        'description' => array(
    1018                                                 'raw'      => '<a href="#" target="_blank">link</a>',
    1019                                                 'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     1018                                                'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     1019                                                'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    10201020                                        ),
    10211021                                        'caption'     => array(
    1022                                                 'raw'      => '<a href="#" target="_blank">link</a>',
    1023                                                 'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     1022                                                'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     1023                                                'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    10241024                                        ),
    10251025                                ),
    10261026                        ),
  • tests/phpunit/tests/rest-api/rest-posts-controller.php

     
    31853185                                                'rendered' => '<a href="#">link</a>',
    31863186                                        ),
    31873187                                        'content' => array(
    3188                                                 'raw'      => '<a href="#" target="_blank">link</a>',
    3189                                                 'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     3188                                                'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     3189                                                'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    31903190                                        ),
    31913191                                        'excerpt' => array(
    3192                                                 'raw'      => '<a href="#" target="_blank">link</a>',
    3193                                                 'rendered' => '<p><a href="#" target="_blank">link</a></p>',
     3192                                                'raw'      => '<a href="#" target="_blank" rel="noopener noreferrer">link</a>',
     3193                                                'rendered' => '<p><a href="#" target="_blank" rel="noopener noreferrer">link</a></p>',
    31943194                                        ),
    31953195                                ),
    31963196                        ),