diff options
author | Timothy Gu <timothygu99@gmail.com> | 2017-02-03 22:06:04 -0800 |
---|---|---|
committer | Timothy Gu <timothygu99@gmail.com> | 2017-02-14 12:13:11 -0800 |
commit | c6b12d0984cc2891433b57cf344b433059681667 (patch) | |
tree | 676f8de002d49b555ca931c05410e7e227da7cd2 /lib/url.js | |
parent | b738cbcdd381a3bcef0111d75d5081bec70d8ce4 (diff) | |
download | android-node-v8-c6b12d0984cc2891433b57cf344b433059681667.tar.gz android-node-v8-c6b12d0984cc2891433b57cf344b433059681667.tar.bz2 android-node-v8-c6b12d0984cc2891433b57cf344b433059681667.zip |
url: fix surrogate handling in encodeAuth()
Also factor out common parts in querystring and url.
PR-URL: https://github.com/nodejs/node/pull/11161
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Brian White <mscdex@mscdex.net>
Diffstat (limited to 'lib/url.js')
-rw-r--r-- | lib/url.js | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/lib/url.js b/lib/url.js index 57f04d5f3f..5d59d3c10f 100644 --- a/lib/url.js +++ b/lib/url.js @@ -10,8 +10,8 @@ function importPunycode() { const { toASCII } = importPunycode(); +const { StorageObject, hexTable } = require('internal/querystring'); const internalUrl = require('internal/url'); -const encodeAuth = internalUrl.encodeAuth; exports.parse = urlParse; exports.resolve = urlResolve; exports.resolveObject = urlResolveObject; @@ -76,12 +76,6 @@ const slashedProtocol = { }; const querystring = require('querystring'); -// This constructor is used to store parsed query string values. Instantiating -// this is faster than explicitly calling `Object.create(null)` to get a -// "clean" empty object (tested with v8 v4.9). -function ParsedQueryString() {} -ParsedQueryString.prototype = Object.create(null); - function urlParse(url, parseQueryString, slashesDenoteHost) { if (url instanceof Url) return url; @@ -190,7 +184,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { } } else if (parseQueryString) { this.search = ''; - this.query = new ParsedQueryString(); + this.query = new StorageObject(); } return this; } @@ -380,7 +374,7 @@ Url.prototype.parse = function(url, parseQueryString, slashesDenoteHost) { } else if (parseQueryString) { // no query string, but parseQueryString still requested this.search = ''; - this.query = new ParsedQueryString(); + this.query = new StorageObject(); } var firstIdx = (questionIdx !== -1 && @@ -948,3 +942,75 @@ function spliceOne(list, index) { list[i] = list[k]; list.pop(); } + +// These characters do not need escaping: +// ! - . _ ~ +// ' ( ) * : +// digits +// alpha (uppercase) +// alpha (lowercase) +const noEscapeAuth = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 - 0x0F + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0x10 - 0x1F + 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, // 0x20 - 0x2F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, // 0x30 - 0x3F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x40 - 0x4F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, // 0x50 - 0x5F + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6F + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0 // 0x70 - 0x7F +]; + +function encodeAuth(str) { + // faster encodeURIComponent alternative for encoding auth uri components + var out = ''; + var lastPos = 0; + for (var i = 0; i < str.length; ++i) { + var c = str.charCodeAt(i); + + // ASCII + if (c < 0x80) { + if (noEscapeAuth[c] === 1) + continue; + if (lastPos < i) + out += str.slice(lastPos, i); + lastPos = i + 1; + out += hexTable[c]; + continue; + } + + if (lastPos < i) + out += str.slice(lastPos, i); + + // Multi-byte characters ... + if (c < 0x800) { + lastPos = i + 1; + out += hexTable[0xC0 | (c >> 6)] + hexTable[0x80 | (c & 0x3F)]; + continue; + } + if (c < 0xD800 || c >= 0xE000) { + lastPos = i + 1; + out += hexTable[0xE0 | (c >> 12)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + continue; + } + // Surrogate pair + ++i; + var c2; + if (i < str.length) + c2 = str.charCodeAt(i) & 0x3FF; + else + c2 = 0; + lastPos = i + 1; + c = 0x10000 + (((c & 0x3FF) << 10) | c2); + out += hexTable[0xF0 | (c >> 18)] + + hexTable[0x80 | ((c >> 12) & 0x3F)] + + hexTable[0x80 | ((c >> 6) & 0x3F)] + + hexTable[0x80 | (c & 0x3F)]; + } + if (lastPos === 0) + return str; + if (lastPos < str.length) + return out + str.slice(lastPos); + return out; +} |