Make WordPress Core


Ignore:
Timestamp:
10/07/2015 11:38:22 PM (9 years ago)
Author:
johnbillion
Message:

Avoid stripping square brackets from URLs, and instead correctly encode them. Square brackets must be encoded in the path, path parameters, query parameters, and fragment, but must not be encoded in anything up to the domain and port.

Adds tests.

Fixes #16859

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/formatting.php

    r34770 r34920  
    21382138    $dest = $matches[2];
    21392139    $dest = 'http://' . $dest;
    2140     $dest = esc_url($dest);
    2141     if ( empty($dest) )
    2142         return $matches[0];
    21432140
    21442141    // removed trailing [.,;:)] from URL
     
    21472144        $dest = substr($dest, 0, strlen($dest)-1);
    21482145    }
     2146
     2147    $dest = esc_url($dest);
     2148    if ( empty($dest) )
     2149        return $matches[0];
     2150
    21492151    return $matches[1] . "<a href=\"$dest\" rel=\"nofollow\">$dest</a>$ret";
    21502152}
     
    33533355
    33543356    $url = str_replace( ' ', '%20', $url );
    3355     $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\\x80-\\xff]|i', '', $url);
     3357    $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\|*\'()\[\]\\x80-\\xff]|i', '', $url);
    33563358
    33573359    if ( '' === $url ) {
     
    33663368    $url = str_replace(';//', '://', $url);
    33673369    /* If the URL doesn't appear to contain a scheme, we
    3368      * presume it needs http:// appended (unless a relative
     3370     * presume it needs http:// prepended (unless a relative
    33693371     * link starting with /, # or ? or a php file).
    33703372     */
     
    33783380        $url = str_replace( '&amp;', '&#038;', $url );
    33793381        $url = str_replace( "'", '&#039;', $url );
     3382    }
     3383
     3384    if ( ( false !== strpos( $url, '[' ) ) || ( false !== strpos( $url, ']' ) ) ) {
     3385
     3386        $parsed = parse_url( $url );
     3387        $front  = '';
     3388
     3389        if ( isset( $parsed['scheme'] ) ) {
     3390            $front .= $parsed['scheme'] . '://';
     3391        } elseif ( '/' === $url[0] ) {
     3392            $front .= '//';
     3393        }
     3394
     3395        if ( isset( $parsed['user'] ) ) {
     3396            $front .= $parsed['user'];
     3397        }
     3398
     3399        if ( isset( $parsed['pass'] ) ) {
     3400            $front .= ':' . $parsed['pass'];
     3401        }
     3402
     3403        if ( isset( $parsed['user'] ) || isset( $parsed['pass'] ) ) {
     3404            $front .= '@';
     3405        }
     3406
     3407        if ( isset( $parsed['host'] ) ) {
     3408            $front .= $parsed['host'];
     3409        }
     3410
     3411        if ( isset( $parsed['port'] ) ) {
     3412            $front .= ':' . $parsed['port'];
     3413        }
     3414
     3415        $end_dirty = str_replace( $front, '', $url );
     3416        $end_clean = str_replace( array( '[', ']' ), array( '%5B', '%5D' ), $end_dirty );
     3417        $url       = str_replace( $end_dirty, $end_clean, $url );
     3418
    33803419    }
    33813420
Note: See TracChangeset for help on using the changeset viewer.