Leave already-encoded characters alone (Fixes #473)

This commit is contained in:
Gregory Schier 2017-09-09 12:26:13 +00:00
parent 4afb7bc55c
commit 8e64995b07
3 changed files with 20 additions and 27 deletions

2
.nvmrc
View File

@ -1 +1 @@
v8
8

View File

@ -150,6 +150,11 @@ describe('prepareUrlForSending()', () => {
expect(url2).toBe('https://google.com/%40%3B%2C%26%5E');
});
it('leaves already encoded characters alone', () => {
const url = misc.prepareUrlForSending('https://google.com/%2B%2A%2F>');
expect(url).toBe('https://google.com/%2B%2A%2F%3E');
});
it('doesn\'t encode if last param set', () => {
const url = misc.prepareUrlForSending('https://google.com/%%?foo=%%', false);
expect(url).toBe('https://google.com/%%?foo=%%');

View File

@ -110,45 +110,33 @@ export function flexibleEncodeComponent (str: string, ignore: string = ''): stri
// Sometimes spaces screw things up because of url.parse
str = str.replace(/%20/g, ' ');
const ignoredChars = ignore.split('');
// Handle all already-encoded characters so we don't touch them
str = str.replace(/%([0-9a-fA-F]{2})/g, '__ENC__$1');
// Do a special encode of ignored chars, so they aren't touched.
// This first pass, surrounds them with a special tag (anything unique
// will work), so it can change them back later
// Example: will replace %40 with __LEAVE_40_LEAVE__, and we'll change
// it back to %40 at the end.
for (const c of ignoredChars) {
for (const c of ignore) {
const code = encodeURIComponent(c).replace('%', '');
// Replace encoded versions
const re = new RegExp(encodeURIComponent(c), 'g');
str = str.replace(re, `__ENCODED_${code}_ENCODED__`);
// Replace raw versions
const re2 = new RegExp(`[${c}]`, 'g');
str = str.replace(re2, `__RAW_${code}_RAW__`);
}
try {
str = decodeURIComponent(str);
} catch (e) {
// Malformed (probably not encoded) so assume it's decoded already
const re2 = new RegExp(escapeRegex(c), 'g');
str = str.replace(re2, `__RAW__${code}`);
}
// Encode it
str = encodeURIComponent(str);
// Put back the raw version of the ignored chars
for (const match of str.match(/__RAW__([0-9a-fA-F]{2})/g) || []) {
const code = match.replace('__RAW__', '');
str = str.replace(match, decodeURIComponent(`%${code}`));
}
// Put back the encoded version of the ignored chars
for (const c of ignoredChars) {
const code = encodeURIComponent(c).replace('%', '');
// Put back encoded versions
const re = new RegExp(`__ENCODED_${code}_ENCODED__`, 'g');
str = str.replace(re, encodeURIComponent(c));
// Put back raw versions
const re2 = new RegExp(`__RAW_${code}_RAW__`, 'g');
str = str.replace(re2, c);
for (const match of str.match(/__ENC__([0-9a-fA-F]{2})/g) || []) {
const code = match.replace('__ENC__', '');
str = str.replace(match, `%${code}`);
}
return str;