You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.2 KiB
94 lines
2.2 KiB
'use strict'; |
|
var token = '%[a-f0-9]{2}'; |
|
var singleMatcher = new RegExp(token, 'gi'); |
|
var multiMatcher = new RegExp('(' + token + ')+', 'gi'); |
|
|
|
function decodeComponents(components, split) { |
|
try { |
|
// Try to decode the entire string first |
|
return decodeURIComponent(components.join('')); |
|
} catch (err) { |
|
// Do nothing |
|
} |
|
|
|
if (components.length === 1) { |
|
return components; |
|
} |
|
|
|
split = split || 1; |
|
|
|
// Split the array in 2 parts |
|
var left = components.slice(0, split); |
|
var right = components.slice(split); |
|
|
|
return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right)); |
|
} |
|
|
|
function decode(input) { |
|
try { |
|
return decodeURIComponent(input); |
|
} catch (err) { |
|
var tokens = input.match(singleMatcher); |
|
|
|
for (var i = 1; i < tokens.length; i++) { |
|
input = decodeComponents(tokens, i).join(''); |
|
|
|
tokens = input.match(singleMatcher); |
|
} |
|
|
|
return input; |
|
} |
|
} |
|
|
|
function customDecodeURIComponent(input) { |
|
// Keep track of all the replacements and prefill the map with the `BOM` |
|
var replaceMap = { |
|
'%FE%FF': '\uFFFD\uFFFD', |
|
'%FF%FE': '\uFFFD\uFFFD' |
|
}; |
|
|
|
var match = multiMatcher.exec(input); |
|
while (match) { |
|
try { |
|
// Decode as big chunks as possible |
|
replaceMap[match[0]] = decodeURIComponent(match[0]); |
|
} catch (err) { |
|
var result = decode(match[0]); |
|
|
|
if (result !== match[0]) { |
|
replaceMap[match[0]] = result; |
|
} |
|
} |
|
|
|
match = multiMatcher.exec(input); |
|
} |
|
|
|
// Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else |
|
replaceMap['%C2'] = '\uFFFD'; |
|
|
|
var entries = Object.keys(replaceMap); |
|
|
|
for (var i = 0; i < entries.length; i++) { |
|
// Replace all decoded components |
|
var key = entries[i]; |
|
input = input.replace(new RegExp(key, 'g'), replaceMap[key]); |
|
} |
|
|
|
return input; |
|
} |
|
|
|
module.exports = function (encodedURI) { |
|
if (typeof encodedURI !== 'string') { |
|
throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`'); |
|
} |
|
|
|
try { |
|
encodedURI = encodedURI.replace(/\+/g, ' '); |
|
|
|
// Try the built in decoder first |
|
return decodeURIComponent(encodedURI); |
|
} catch (err) { |
|
// Fallback to a more advanced decoder |
|
return customDecodeURIComponent(encodedURI); |
|
} |
|
};
|
|
|