As of
155d555b83eca640, we now redirect variations on hex escapes
into their canonical form. This was causing '~' to be redirected
to %7E. However google chrome seems to canonicalize %7E back
into ~, causing a redirect loop.
RFC 3986 says ~ is unreserved, so not hex encoding it should be
fine. To quote: "For consistency, percent-encoded octets in the
ranges of...tilde (%7E) should not be created by URI producers"
Bug: T105265
Change-Id: I01556eee496e2fb540de8ff09c082c1fedddb5f7
+ * RFC 1738 says ~ is unsafe, however RFC 3986 considers it an unreserved
+ * character which should not be encoded. More importantly, google chrome
+ * always converts %7E back to ~, and converting it in this function can
+ * cause a redirect loop (T105265).
+ *
* But + is not safe because it's used to indicate a space; &= are only safe in
* paths and not in queries (and we don't distinguish here); ' seems kind of
* scary; and urlencode() doesn't touch -_. to begin with. Plus, although /
* is reserved, we don't care. So the list we unescape is:
*
* But + is not safe because it's used to indicate a space; &= are only safe in
* paths and not in queries (and we don't distinguish here); ' seems kind of
* scary; and urlencode() doesn't touch -_. to begin with. Plus, although /
* is reserved, we don't care. So the list we unescape is:
*
*
* However, IIS7 redirects fail when the url contains a colon (Bug 22709),
* so no fancy : for IIS7.
*
* However, IIS7 redirects fail when the url contains a colon (Bug 22709),
* so no fancy : for IIS7.
}
if ( is_null( $needle ) ) {
}
if ( is_null( $needle ) ) {
- $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F' );
+ $needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F', '%7E' );
if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
) {
if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
) {
$s = urlencode( $s );
$s = str_ireplace(
$needle,
$s = urlencode( $s );
$s = str_ireplace(
$needle,
- array( ';', '@', '$', '!', '*', '(', ')', ',', '/', ':' ),
+ array( ';', '@', '$', '!', '*', '(', ')', ',', '/', '~', ':' ),
.replace( /%29/g, ')' )
.replace( /%2C/g, ',' )
.replace( /%2F/g, '/' )
.replace( /%29/g, ')' )
.replace( /%2C/g, ',' )
.replace( /%2F/g, '/' )
+ .replace( /%7E/g, '~' )
.replace( /%3A/g, ':' );
},
.replace( /%3A/g, ':' );
},
!! wikitext
[[Foo~bar]]
!! html/php
!! wikitext
[[Foo~bar]]
!! html/php
-<p><a href="/wiki/Foo%7Ebar" title="Foo~bar">Foo~bar</a>
+<p><a href="/wiki/Foo~bar" title="Foo~bar">Foo~bar</a>
</p>
!! html/parsoid
<p><a rel="mw:WikiLink" href="./Foo~bar" title="Foo~bar">Foo~bar</a></p>
</p>
!! html/parsoid
<p><a rel="mw:WikiLink" href="./Foo~bar" title="Foo~bar">Foo~bar</a></p>
### Other tests
// slash remain unchanged. %2F seems to break things
array( '/', '/' ),
### Other tests
// slash remain unchanged. %2F seems to break things
array( '/', '/' ),
+ // T105265
+ array( '~', '~' ),
// Other 'funnies' chars
array( '[]', '%5B%5D' ),
// Other 'funnies' chars
array( '[]', '%5B%5D' ),
assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
} );
assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
} );
- QUnit.test( 'wikiUrlencode', 10, function ( assert ) {
+ QUnit.test( 'wikiUrlencode', 11, function ( assert ) {
assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
// See also wfUrlencodeTest.php#provideURLS
$.each( {
assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
// See also wfUrlencodeTest.php#provideURLS
$.each( {
':': ':',
';@$-_.!*': ';@$-_.!*',
'/': '/',
':': ':',
';@$-_.!*': ';@$-_.!*',
'/': '/',
'[]': '%5B%5D',
'<>': '%3C%3E',
'\'': '%27'
'[]': '%5B%5D',
'<>': '%3C%3E',
'\'': '%27'