Projekt

Obecné

Profil

Stáhnout (2.17 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2
var token = '%[a-f0-9]{2}';
3
var singleMatcher = new RegExp(token, 'gi');
4
var multiMatcher = new RegExp('(' + token + ')+', 'gi');
5

    
6
function decodeComponents(components, split) {
7
	try {
8
		// Try to decode the entire string first
9
		return decodeURIComponent(components.join(''));
10
	} catch (err) {
11
		// Do nothing
12
	}
13

    
14
	if (components.length === 1) {
15
		return components;
16
	}
17

    
18
	split = split || 1;
19

    
20
	// Split the array in 2 parts
21
	var left = components.slice(0, split);
22
	var right = components.slice(split);
23

    
24
	return Array.prototype.concat.call([], decodeComponents(left), decodeComponents(right));
25
}
26

    
27
function decode(input) {
28
	try {
29
		return decodeURIComponent(input);
30
	} catch (err) {
31
		var tokens = input.match(singleMatcher);
32

    
33
		for (var i = 1; i < tokens.length; i++) {
34
			input = decodeComponents(tokens, i).join('');
35

    
36
			tokens = input.match(singleMatcher);
37
		}
38

    
39
		return input;
40
	}
41
}
42

    
43
function customDecodeURIComponent(input) {
44
	// Keep track of all the replacements and prefill the map with the `BOM`
45
	var replaceMap = {
46
		'%FE%FF': '\uFFFD\uFFFD',
47
		'%FF%FE': '\uFFFD\uFFFD'
48
	};
49

    
50
	var match = multiMatcher.exec(input);
51
	while (match) {
52
		try {
53
			// Decode as big chunks as possible
54
			replaceMap[match[0]] = decodeURIComponent(match[0]);
55
		} catch (err) {
56
			var result = decode(match[0]);
57

    
58
			if (result !== match[0]) {
59
				replaceMap[match[0]] = result;
60
			}
61
		}
62

    
63
		match = multiMatcher.exec(input);
64
	}
65

    
66
	// Add `%C2` at the end of the map to make sure it does not replace the combinator before everything else
67
	replaceMap['%C2'] = '\uFFFD';
68

    
69
	var entries = Object.keys(replaceMap);
70

    
71
	for (var i = 0; i < entries.length; i++) {
72
		// Replace all decoded components
73
		var key = entries[i];
74
		input = input.replace(new RegExp(key, 'g'), replaceMap[key]);
75
	}
76

    
77
	return input;
78
}
79

    
80
module.exports = function (encodedURI) {
81
	if (typeof encodedURI !== 'string') {
82
		throw new TypeError('Expected `encodedURI` to be of type `string`, got `' + typeof encodedURI + '`');
83
	}
84

    
85
	try {
86
		encodedURI = encodedURI.replace(/\+/g, ' ');
87

    
88
		// Try the built in decoder first
89
		return decodeURIComponent(encodedURI);
90
	} catch (err) {
91
		// Fallback to a more advanced decoder
92
		return customDecodeURIComponent(encodedURI);
93
	}
94
};
(1-1/4)