From 3c0470d504e5f691635cbf9c89e1a38d995d88e3 Mon Sep 17 00:00:00 2001 From: Mr. Stradivarius Date: Fri, 4 Feb 2022 11:33:14 +0900 Subject: [PATCH] Escape output in Import.toJs We need to escape JavaScript strings, JavaScript comments, and URL components. For the first two, we make our own custom functions based on the js-string-escape library. For the last one, we can use encodeURIComponent. --- MediaWiki:Gadget-script-installer-core.js | 61 +++++++++++++++++++++-- 1 file changed, 57 insertions(+), 4 deletions(-) diff --git a/MediaWiki:Gadget-script-installer-core.js b/MediaWiki:Gadget-script-installer-core.js index dc9de4b..1c352cf 100644 --- a/MediaWiki:Gadget-script-installer-core.js +++ b/MediaWiki:Gadget-script-installer-core.js @@ -141,12 +141,13 @@ Import.prototype.toJs = function () { var dis = this.disabled ? "//" : "", url = this.url; + switch( this.type ) { - case 0: return dis + "importScript('" + this.page + "'); // Backlink: [[" + this.page + "]]"; - case 1: url = "//" + this.wiki + ".org/w/index.php?title=" + - this.page + "&action=raw&ctype=text/javascript"; + case 0: return dis + "importScript('" + escapeForJsString( this.page ) + "'); // Backlink: [[" + escapeForJsComment( this.page ) + "]]"; + case 1: url = "//" + encodeURIComponent( this.wiki ) + ".org/w/index.php?title=" + + encodeURIComponent( this.page ) + "&action=raw&ctype=text/javascript"; /* FALL THROUGH */ - case 2: return dis + "mw.loader.load('" + url + "');"; + case 2: return dis + "mw.loader.load('" + escapeForJsString( url ) + "');"; } } @@ -677,6 +678,58 @@ return s.replace( /[-\/\\^$*+?.()|[\]{}]/g, '\\$&' ); } + /** + * Escape a string for use in a JavaScript string literal. + * This function is adapted from + * https://github.com/joliss/js-string-escape/blob/6887a69003555edf5c6caaa75f2592228558c595/index.js + * (released under the MIT licence). + */ + function escapeForJsString( s ) { + return s.replace( /["'\\\n\r\u2028\u2029]/g, function ( character ) { + // Escape all characters not included in SingleStringCharacters and + // DoubleStringCharacters on + // http://www.ecma-international.org/ecma-262/5.1/#sec-7.8.4 + switch ( character ) { + case '"': + case "'": + case '\\': + return '\\' + character + // Four possible LineTerminator characters need to be escaped: + case '\n': + return '\\n' + case '\r': + return '\\r' + case '\u2028': + return '\\u2028' + case '\u2029': + return '\\u2029' + } + } ); + } + + /** + * Escape a string for use in an inline JavaScript comment (comments that + * start with two slashes "//"). + * This function is adapted from + * https://github.com/joliss/js-string-escape/blob/6887a69003555edf5c6caaa75f2592228558c595/index.js + * (released under the MIT licence). + */ + function escapeForJsComment( s ) { + return s.replace( /[\n\r\u2028\u2029]/g, function ( character ) { + switch ( character ) { + // Escape possible LineTerminator characters + case '\n': + return '\\n' + case '\r': + return '\\r' + case '\u2028': + return '\\u2028' + case '\u2029': + return '\\u2029' + } + } ); + } + function getFullTarget ( target ) { return USER_NAMESPACE_NAME + ":" + mw.config.get( "wgUserName" ) + "/" + target + ".js"; -- 2.25.1