Do not encode "'" as %27 (redirect loop in Opera 12)

Similar to 7b4df0e12e,
but for apostrophe instead of tilde and for Opera
instead of Chrome.

Bug: T106793
Change-Id: Ic54390434cebcc76a6c8ab49acc164d36e0cdff6
This commit is contained in:
Bartosz Dziewoński 2015-08-20 18:38:04 +02:00 committed by Timo Tijhof
parent 27ef2cee00
commit a89a21990e
8 changed files with 31 additions and 30 deletions

View file

@ -404,14 +404,15 @@ function wfRandomString( $length = 32 ) {
* 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).
* cause a redirect loop (T105265). Similarly, encoding ' causes a
* redirect loop on Opera 12 (T106793).
*
* 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 /
* paths and not in queries (and we don't distinguish here);
* 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.
@ -430,7 +431,7 @@ function wfUrlencode( $s ) {
}
if ( is_null( $needle ) ) {
$needle = array( '%3B', '%40', '%24', '%21', '%2A', '%28', '%29', '%2C', '%2F', '%7E' );
$needle = array( '%3B', '%40', '%24', '%21', '%2A', '%27', '%28', '%29', '%2C', '%2F', '%7E' );
if ( !isset( $_SERVER['SERVER_SOFTWARE'] ) ||
( strpos( $_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS/7' ) === false )
) {
@ -441,7 +442,7 @@ function wfUrlencode( $s ) {
$s = urlencode( $s );
$s = str_ireplace(
$needle,
array( ';', '@', '$', '!', '*', '(', ')', ',', '/', '~', ':' ),
array( ';', '@', '$', '!', '*', '\'', '(', ')', ',', '/', '~', ':' ),
$s
);

View file

@ -939,7 +939,10 @@ class Linker {
$href = self::getUploadUrl( $title, $query );
return '<a href="' . htmlspecialchars( $href ) . '" class="new" title="' .
// @todo FIXME: If we don't to escape apostrophes (single quotes) here (using ENT_QUOTES),
// then double apostrophes will be parsed as italics somewhere later in the parser,
// and break everything horribly
return '<a href="' . htmlspecialchars( $href, ENT_QUOTES ) . '" class="new" title="' .
htmlspecialchars( $title->getPrefixedText(), ENT_QUOTES ) . '">' .
$encLabel . '</a>';
}

View file

@ -78,6 +78,7 @@
.replace( /%24/g, '$' )
.replace( /%21/g, '!' )
.replace( /%2A/g, '*' )
.replace( /%27/g, '\'' )
.replace( /%28/g, '(' )
.replace( /%29/g, ')' )
.replace( /%2C/g, ',' )

View file

@ -5711,7 +5711,7 @@ Plain ''italic'''s plain
###
### Tables
###
### some content taken from http://meta.wikimedia.org/wiki/MediaWiki_User%27s_Guide:_Using_tables
### some content taken from http://meta.wikimedia.org/wiki/MediaWiki_User's_Guide:_Using_tables
###
# This should not produce <table></table> as <table><tr><td></td></tr></table>
@ -7368,7 +7368,7 @@ Link containing double-single-quotes '' (bug 4598)
!! wikitext
[[Lista d''e paise d''o munno]]
!! html/php
<p><a href="/index.php?title=Lista_d%27%27e_paise_d%27%27o_munno&amp;action=edit&amp;redlink=1" class="new" title="Lista d''e paise d''o munno (page does not exist)">Lista d''e paise d''o munno</a>
<p><a href="/index.php?title=Lista_d''e_paise_d''o_munno&amp;action=edit&amp;redlink=1" class="new" title="Lista d''e paise d''o munno (page does not exist)">Lista d''e paise d''o munno</a>
</p>
!! html/parsoid
<p><a rel="mw:WikiLink" href="./Lista_d''e_paise_d''o_munno" title="Lista d''e paise d''o munno">Lista d''e paise d''o munno</a></p>
@ -7405,10 +7405,10 @@ Link with double quotes in title part (literal) and alternate part (interpreted)
[[''Pentecoste''|''Pentecoste'']]
!! html/php
<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Denys_Savchenko_%27%27Pentecoste%27%27.jpg" class="new" title="File:Denys Savchenko &#39;&#39;Pentecoste&#39;&#39;.jpg">File:Denys Savchenko <i>Pentecoste</i>.jpg</a>
</p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">''Pentecoste''</a>
</p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">Pentecoste</a>
</p><p><a href="/index.php?title=%27%27Pentecoste%27%27&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)"><i>Pentecoste</i></a>
<p><a href="/index.php?title=Special:Upload&amp;wpDestFile=Denys_Savchenko_&#39;&#39;Pentecoste&#39;&#39;.jpg" class="new" title="File:Denys Savchenko &#39;&#39;Pentecoste&#39;&#39;.jpg">File:Denys Savchenko <i>Pentecoste</i>.jpg</a>
</p><p><a href="/index.php?title=''Pentecoste''&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">''Pentecoste''</a>
</p><p><a href="/index.php?title=''Pentecoste''&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)">Pentecoste</a>
</p><p><a href="/index.php?title=''Pentecoste''&amp;action=edit&amp;redlink=1" class="new" title="''Pentecoste'' (page does not exist)"><i>Pentecoste</i></a>
</p>
!! html/parsoid
<p><span class="mw-default-size" typeof="mw:Error mw:Image" data-mw='{"errors":[{"key":"missing-image","message":"This image does not exist."}]}'><a href="./File:Denys_Savchenko_''Pentecoste''.jpg"><img resource="./File:Denys_Savchenko_''Pentecoste''.jpg" src="./Special:FilePath/Denys_Savchenko_''Pentecoste''.jpg" height="220" width="220"/></a></span></p>
@ -14033,7 +14033,7 @@ Link to category
!! wikitext
[[:Category:MediaWiki User's Guide]]
!! html
<p><a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">Category:MediaWiki User's Guide</a>
<p><a href="/wiki/Category:MediaWiki_User's_Guide" title="Category:MediaWiki User's Guide">Category:MediaWiki User's Guide</a>
</p>
!! end
@ -14044,7 +14044,7 @@ cat
!! wikitext
[[Category:MediaWiki User's Guide]]
!! html
<a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
<a href="/wiki/Category:MediaWiki_User's_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
!! end
!! test
@ -14063,7 +14063,7 @@ cat
!! wikitext
[[Category:MediaWiki User's Guide|Foo]]
!! html
<a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
<a href="/wiki/Category:MediaWiki_User's_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
!! end
!! test
@ -14073,7 +14073,7 @@ cat
!! wikitext
[[Category:MediaWiki User's Guide|MediaWiki User's Guide]]
!! html
<a href="/wiki/Category:MediaWiki_User%27s_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
<a href="/wiki/Category:MediaWiki_User's_Guide" title="Category:MediaWiki User's Guide">MediaWiki User's Guide</a>
!! end
!! test
@ -19025,7 +19025,7 @@ language=sr cat
!! wikitext
[[Category:МедиаWики Усер'с Гуиде]]
!! html
<a href="/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%98%D0%B0:MediaWiki_User%27s_Guide" title="Категорија:MediaWiki User's Guide">MediaWiki User's Guide</a>
<a href="/wiki/%D0%9A%D0%B0%D1%82%D0%B5%D0%B3%D0%BE%D1%80%D0%B8%D1%98%D0%B0:MediaWiki_User's_Guide" title="Категорија:MediaWiki User's Guide">MediaWiki User's Guide</a>
!! end
@ -20981,7 +20981,7 @@ File:foobar.jpg|caption|alt=galleryalt|link=" onclick="alert('malicious javascri
!! html
<ul class="gallery mw-gallery-traditional">
<li class="gallerybox" style="width: 155px"><div style="width: 155px">
<div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(%27malicious_javascript_code!%27);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="thumb" style="width: 150px;"><div style="margin:68px auto;"><a href="/wiki/%22_onclick%3D%22alert(&#39;malicious_javascript_code!&#39;);"><img alt="galleryalt" src="http://example.com/images/thumb/3/3a/Foobar.jpg/120px-Foobar.jpg" width="120" height="14" srcset="http://example.com/images/thumb/3/3a/Foobar.jpg/180px-Foobar.jpg 1.5x, http://example.com/images/thumb/3/3a/Foobar.jpg/240px-Foobar.jpg 2x" /></a></div></div>
<div class="gallerytext">
<p>caption
</p>

View file

@ -105,8 +105,8 @@ class WfUrlencodeTest extends MediaWikiTestCase {
// remaining chars do not need encoding
array(
';@$-_.!*',
';@$-_.!*',
';@$-_.!*\'',
';@$-_.!*\'',
),
### Other tests
@ -118,9 +118,6 @@ class WfUrlencodeTest extends MediaWikiTestCase {
// Other 'funnies' chars
array( '[]', '%5B%5D' ),
array( '<>', '%3C%3E' ),
// Apostrophe is encoded
array( '\'', '%27' ),
);
}
}

View file

@ -232,7 +232,7 @@ class LinkerTest extends MediaWikiLangTestCase {
null,
),
array(
'<a class="external" rel="nofollow" href="//en.example.org/w/Foo%27bar">Foo\'bar</a>',
'<a class="external" rel="nofollow" href="//en.example.org/w/Foo\'bar">Foo\'bar</a>',
"[[Foo'bar]]",
'enwiki',
),

View file

@ -388,7 +388,7 @@
'Bar in anchor'
);
expectedSpecialCharacters = '<a title="&quot;Who&quot; wants to be a millionaire &amp; live on &#039;Exotic Island&#039;?" href="/wiki/%22Who%22_wants_to_be_a_millionaire_%26_live_on_%27Exotic_Island%27%3F">&quot;Who&quot; wants to be a millionaire &amp; live on &#039;Exotic Island&#039;?</a>';
expectedSpecialCharacters = '<a title="&quot;Who&quot; wants to be a millionaire &amp; live on &#039;Exotic Island&#039;?" href="/wiki/%22Who%22_wants_to_be_a_millionaire_%26_live_on_&#039;Exotic_Island&#039;%3F">&quot;Who&quot; wants to be a millionaire &amp; live on &#039;Exotic Island&#039;?</a>';
mw.messages.set( 'special-characters', '[[' + specialCharactersPageName + ']]' );
assert.htmlEqual(

View file

@ -92,7 +92,7 @@
assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 'Test%3AA%20%26%20B%2FHere' );
} );
QUnit.test( 'wikiUrlencode', 11, function ( assert ) {
QUnit.test( 'wikiUrlencode', 10, function ( assert ) {
assert.equal( mw.util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' );
// See also wfUrlencodeTest.php#provideURLS
$.each( {
@ -100,12 +100,11 @@
'&': '%26',
'=': '%3D',
':': ':',
';@$-_.!*': ';@$-_.!*',
';@$-_.!*\'': ';@$-_.!*\'',
'/': '/',
'~': '~',
'[]': '%5B%5D',
'<>': '%3C%3E',
'\'': '%27'
'<>': '%3C%3E'
}, function ( input, output ) {
assert.equal( mw.util.wikiUrlencode( input ), output );
} );