|
@ -35,7 +35,7 @@ var protocolPattern = /^([a-z0-9.+-]+:)/i, |
|
|
// RFC 2396: characters reserved for delimiting URLs.
|
|
|
// RFC 2396: characters reserved for delimiting URLs.
|
|
|
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], |
|
|
delims = ['<', '>', '"', '`', ' ', '\r', '\n', '\t'], |
|
|
// RFC 2396: characters not allowed for various reasons.
|
|
|
// RFC 2396: characters not allowed for various reasons.
|
|
|
unwise = ['{', '}', '|', '\\', '^', '~', '[', ']', '`'].concat(delims), |
|
|
unwise = ['{', '}', '|', '\\', '^', '~', '`'].concat(delims), |
|
|
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
|
|
// Allowed by RFCs, but cause of XSS attacks. Always escape these.
|
|
|
autoEscape = ['\''], |
|
|
autoEscape = ['\''], |
|
|
// Characters that are never ever allowed in a hostname.
|
|
|
// Characters that are never ever allowed in a hostname.
|
|
@ -179,10 +179,15 @@ function urlParse(url, parseQueryString, slashesDenoteHost) { |
|
|
// so even if it's empty, it has to be present.
|
|
|
// so even if it's empty, it has to be present.
|
|
|
out.hostname = out.hostname || ''; |
|
|
out.hostname = out.hostname || ''; |
|
|
|
|
|
|
|
|
|
|
|
// if hostname begins with [ and ends with ]
|
|
|
|
|
|
// assume that it's an IPv6 address.
|
|
|
|
|
|
var ipv6Hostname = out.hostname[0] === '[' && |
|
|
|
|
|
out.hostname[out.hostname.length - 1] === ']'; |
|
|
|
|
|
|
|
|
// validate a little.
|
|
|
// validate a little.
|
|
|
if (out.hostname.length > hostnameMaxLen) { |
|
|
if (out.hostname.length > hostnameMaxLen) { |
|
|
out.hostname = ''; |
|
|
out.hostname = ''; |
|
|
} else { |
|
|
} else if (!ipv6Hostname) { |
|
|
var hostparts = out.hostname.split(/\./); |
|
|
var hostparts = out.hostname.split(/\./); |
|
|
for (var i = 0, l = hostparts.length; i < l; i++) { |
|
|
for (var i = 0, l = hostparts.length; i < l; i++) { |
|
|
var part = hostparts[i]; |
|
|
var part = hostparts[i]; |
|
@ -221,22 +226,32 @@ function urlParse(url, parseQueryString, slashesDenoteHost) { |
|
|
// hostnames are always lower case.
|
|
|
// hostnames are always lower case.
|
|
|
out.hostname = out.hostname.toLowerCase(); |
|
|
out.hostname = out.hostname.toLowerCase(); |
|
|
|
|
|
|
|
|
// IDNA Support: Returns a puny coded representation of "domain".
|
|
|
if (!ipv6Hostname) { |
|
|
// It only converts the part of the domain name that
|
|
|
// IDNA Support: Returns a puny coded representation of "domain".
|
|
|
// has non ASCII characters. I.e. it dosent matter if
|
|
|
// It only converts the part of the domain name that
|
|
|
// you call it with a domain that already is in ASCII.
|
|
|
// has non ASCII characters. I.e. it dosent matter if
|
|
|
var domainArray = out.hostname.split('.'); |
|
|
// you call it with a domain that already is in ASCII.
|
|
|
var newOut = []; |
|
|
var domainArray = out.hostname.split('.'); |
|
|
for (var i = 0; i < domainArray.length; ++i) { |
|
|
var newOut = []; |
|
|
var s = domainArray[i]; |
|
|
for (var i = 0; i < domainArray.length; ++i) { |
|
|
newOut.push(s.match(/[^A-Za-z0-9_-]/) ? |
|
|
var s = domainArray[i]; |
|
|
'xn--' + punycode.encode(s) : s); |
|
|
newOut.push(s.match(/[^A-Za-z0-9_-]/) ? |
|
|
|
|
|
'xn--' + punycode.encode(s) : s); |
|
|
|
|
|
} |
|
|
|
|
|
out.hostname = newOut.join('.'); |
|
|
} |
|
|
} |
|
|
out.hostname = newOut.join('.'); |
|
|
|
|
|
|
|
|
|
|
|
out.host = (out.hostname || '') + |
|
|
out.host = (out.hostname || '') + |
|
|
((out.port) ? ':' + out.port : ''); |
|
|
((out.port) ? ':' + out.port : ''); |
|
|
out.href += out.host; |
|
|
out.href += out.host; |
|
|
|
|
|
|
|
|
|
|
|
// strip [ and ] from the hostname
|
|
|
|
|
|
if (ipv6Hostname) { |
|
|
|
|
|
out.hostname = out.hostname.substr(1, out.hostname.length - 2); |
|
|
|
|
|
if (rest[0] !== '/') { |
|
|
|
|
|
rest = '/' + rest; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// now rest is set to the post-host stuff.
|
|
|
// now rest is set to the post-host stuff.
|
|
@ -323,20 +338,28 @@ function urlFormat(obj) { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
var protocol = obj.protocol || '', |
|
|
var protocol = obj.protocol || '', |
|
|
host = (obj.host !== undefined) ? auth + obj.host : |
|
|
|
|
|
obj.hostname !== undefined ? ( |
|
|
|
|
|
auth + obj.hostname + |
|
|
|
|
|
(obj.port ? ':' + obj.port : '') |
|
|
|
|
|
) : |
|
|
|
|
|
false, |
|
|
|
|
|
pathname = obj.pathname || '', |
|
|
pathname = obj.pathname || '', |
|
|
query = obj.query && |
|
|
hash = obj.hash || '', |
|
|
((typeof obj.query === 'object' && |
|
|
host = false, |
|
|
Object.keys(obj.query).length) ? |
|
|
query = ''; |
|
|
querystring.stringify(obj.query) : |
|
|
|
|
|
'') || '', |
|
|
if (obj.host !== undefined) { |
|
|
search = obj.search || (query && ('?' + query)) || '', |
|
|
host = auth + obj.host; |
|
|
hash = obj.hash || ''; |
|
|
} else if (obj.hostname !== undefined) { |
|
|
|
|
|
host = auth + (obj.hostname.indexOf(':') === -1 ? |
|
|
|
|
|
obj.hostname : |
|
|
|
|
|
'[' + obj.hostname + ']'); |
|
|
|
|
|
if (obj.port) { |
|
|
|
|
|
host += ':' + obj.port; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (obj.query && typeof obj.query === 'object' && |
|
|
|
|
|
Object.keys(obj.query).length) { |
|
|
|
|
|
query = querystring.stringify(obj.query); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var search = obj.search || (query && ('?' + query)) || ''; |
|
|
|
|
|
|
|
|
if (protocol && protocol.substr(-1) !== ':') protocol += ':'; |
|
|
if (protocol && protocol.substr(-1) !== ':') protocol += ':'; |
|
|
|
|
|
|
|
|