jenkins-bot has submitted this change and it was merged.

Change subject: mediawiki.util: Use correct encoding for fragment in getUrl
......................................................................


mediawiki.util: Use correct encoding for fragment in getUrl

Introduce mw.util.escapeId with same encoding as Sanitizer::escapeId.

Add more tests to getUrl:
* empty title
* several characters for encoding test

Bug: T103553
Bug: T103661
Change-Id: I15d8c48b9ea4a144a0938353c5b265cb6b6a159b
---
M resources/src/mediawiki/mediawiki.util.js
M tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
2 files changed, 56 insertions(+), 7 deletions(-)

Approvals:
  Bartosz Dziewoński: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/resources/src/mediawiki/mediawiki.util.js 
b/resources/src/mediawiki/mediawiki.util.js
index 7b45248..f9810f9 100644
--- a/resources/src/mediawiki/mediawiki.util.js
+++ b/resources/src/mediawiki/mediawiki.util.js
@@ -59,6 +59,18 @@
                },
 
                /**
+                * Encode the string like Sanitizer::escapeId in PHP
+                *
+                * @param {string} str String to be encoded.
+                */
+               escapeId: function ( str ) {
+                       str = String( str );
+                       return util.rawurlencode( str.replace( / /g, '_' ) )
+                               .replace( /%3A/g, ':' )
+                               .replace( /%/g, '.' );
+               },
+
+               /**
                 * Encode page titles for use in a URL
                 *
                 * We want / and : to be included as literal characters in our 
title URLs
@@ -98,28 +110,28 @@
                        var titleFragmentStart,
                                url,
                                fragment = '',
-                               pageName = util.wikiUrlencode( typeof str === 
'string' ? str : mw.config.get( 'wgPageName' ) );
+                               pageName = typeof str === 'string' ? str : 
mw.config.get( 'wgPageName' );
 
                        // Find any fragment should one exist
                        if ( typeof str === 'string' ) {
-                               titleFragmentStart = pageName.indexOf( '%23' );
+                               titleFragmentStart = pageName.indexOf( '#' );
                                if ( titleFragmentStart !== -1 ) {
-                                       fragment = pageName.slice( 
titleFragmentStart + 3 );
+                                       fragment = pageName.slice( 
titleFragmentStart + 1 );
                                        // Exclude the fragment from the page 
name
                                        pageName = pageName.slice( 0, 
titleFragmentStart );
                                }
                        }
 
-                       url = mw.config.get( 'wgArticlePath' ).replace( '$1', 
pageName );
+                       url = mw.config.get( 'wgArticlePath' ).replace( '$1', 
util.wikiUrlencode( pageName ) );
 
                        // Add query string if necessary
                        if ( params && !$.isEmptyObject( params ) ) {
                                url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' 
) + $.param( params );
                        }
 
-                       // Insert the already URL-encoded fragment should it 
exist, replacing % with .
+                       // Append the encoded fragment
                        if ( fragment.length > 0 ) {
-                               url += '#' + fragment.replace( /%/g, '.' );
+                               url += '#' + util.escapeId( fragment );
                        }
 
                        return url;
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js 
b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
index 75dd8cd..0b98106 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js
@@ -92,6 +92,31 @@
                assert.equal( mw.util.rawurlencode( 'Test:A & B/Here' ), 
'Test%3AA%20%26%20B%2FHere' );
        } );
 
+       QUnit.test( 'escapeId', 17, function ( assert ) {
+               mw.config.set( 'wgExperimentalHtmlIds', false );
+               $.each( {
+                       '+': '.2B',
+                       '&': '.26',
+                       '=': '.3D',
+                       ':': ':',
+                       ';': '.3B',
+                       '@': '.40',
+                       $: '.24',
+                       '-_.': '-_.',
+                       '!': '.21',
+                       '*': '.2A',
+                       '/': '.2F',
+                       '[]': '.5B.5D',
+                       '<>': '.3C.3E',
+                       '\'': '.27',
+                       '§': '.C2.A7',
+                       'Test:A & B/Here': 'Test:A_.26_B.2FHere',
+                       'A&B&amp;C&amp;amp;D&amp;amp;amp;E': 
'A.26B.26amp.3BC.26amp.3Bamp.3BD.26amp.3Bamp.3Bamp.3BE'
+               }, function ( input, output ) {
+                       assert.equal( mw.util.escapeId( input ), output );
+               } );
+       } );
+
        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
@@ -111,7 +136,7 @@
                } );
        } );
 
-       QUnit.test( 'getUrl', 8, function ( assert ) {
+       QUnit.test( 'getUrl', 12, function ( assert ) {
                // Not part of startUp module
                mw.config.set( 'wgArticlePath', '/wiki/$1' );
                mw.config.set( 'wgPageName', 'Foobar' );
@@ -135,11 +160,23 @@
                href = mw.util.getUrl( 'Foo:Sandbox#Fragment', { action: 'edit' 
} );
                assert.equal( href, '/wiki/Foo:Sandbox?action=edit#Fragment', 
'advanced title with query string and fragment' );
 
+               href = mw.util.getUrl( 'Foo:Sandbox#', { action: 'edit' } );
+               assert.equal( href, '/wiki/Foo:Sandbox?action=edit', 'title 
with query string and empty fragment' );
+
+               href = mw.util.getUrl( '#Fragment' );
+               assert.equal( href, '/wiki/#Fragment', 'epmty title with 
fragment' );
+
+               href = mw.util.getUrl( '#Fragment', { action: 'edit' } );
+               assert.equal( href, '/wiki/?action=edit#Fragment', 'epmty title 
with query string and fragment' );
+
                href = mw.util.getUrl( 'Foo:Sandbox \xC4#Fragment \xC4', { 
action: 'edit' } );
                assert.equal( href, 
'/wiki/Foo:Sandbox_%C3%84?action=edit#Fragment_.C3.84', 'title with query 
string, fragment, and special characters' );
 
                href = mw.util.getUrl( 'Foo:%23#Fragment', { action: 'edit' } );
                assert.equal( href, '/wiki/Foo:%2523?action=edit#Fragment', 
'title containing %23 (#), fragment, and a query string' );
+
+               href = mw.util.getUrl( '#+&=:;@$-_.!*/[]<>\'§', { action: 
'edit' } );
+               assert.equal( href, 
'/wiki/?action=edit#.2B.26.3D:.3B.40.24-_..21.2A.2F.5B.5D.3C.3E.27.C2.A7', 
'fragment with various characters' );
        } );
 
        QUnit.test( 'wikiScript', 4, function ( assert ) {

-- 
To view, visit https://gerrit.wikimedia.org/r/260328
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I15d8c48b9ea4a144a0938353c5b265cb6b6a159b
Gerrit-PatchSet: 2
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Gerrit Patch Uploader <[email protected]>
Gerrit-Reviewer: Bartosz Dziewoński <[email protected]>
Gerrit-Reviewer: Daniel Friesen <[email protected]>
Gerrit-Reviewer: Edokter <[email protected]>
Gerrit-Reviewer: Fomafix
Gerrit-Reviewer: Gerrit Patch Uploader <[email protected]>
Gerrit-Reviewer: Jack Phoenix <[email protected]>
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to