From a79563ac9326847d86f4f778436ddc644a47a47d Mon Sep 17 00:00:00 2001 From: Alesandro Ortiz Date: Sun, 20 Dec 2020 20:59:07 -0500 Subject: [PATCH 1/3] Simplify host parsing fix * Attempt to simplify host parsing fix made in 4f45faf by normalizing backslashes into forward slashes before parsing authority. * Add test case. Two test cases currently fail because they expect host/hostname mutators to throw exceptions when they contain backslashes. Will address after discussion in PR. --- src/URI.js | 18 ++++++++---------- test/urls.js | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/src/URI.js b/src/URI.js index 715c097..9eb7ce3 100644 --- a/src/URI.js +++ b/src/URI.js @@ -549,13 +549,6 @@ string = ''; } - // Copy chrome, IE, opera backslash-handling behavior. - // Back slashes before the query string get converted to forward slashes - // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 - // See: https://code.google.com/p/chromium/issues/detail?id=25916 - // https://github.com/medialize/URI.js/pull/233 - string = string.replace(/\\/g, '/'); - // extract host:port var pos = string.indexOf('/'); var bracketPos; @@ -607,19 +600,24 @@ return string.substring(pos) || '/'; }; URI.parseAuthority = function(string, parts) { + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + // https://github.com/medialize/URI.js/pull/233 + string = string.replace(/\\/g, '/'); + string = URI.parseUserinfo(string, parts); return URI.parseHost(string, parts); }; URI.parseUserinfo = function(string, parts) { // extract username:password - var firstBackSlash = string.indexOf('\\'); var firstSlash = string.indexOf('/'); - var slash = firstBackSlash === -1 ? firstSlash : (firstSlash !== -1 ? Math.min(firstBackSlash, firstSlash): firstSlash) var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); var t; // authority@ must come before /path or \path - if (pos > -1 && (slash === -1 || pos < slash)) { + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { t = string.substring(0, pos).split(':'); parts.username = t[0] ? URI.decode(t[0]) : null; t.shift(); diff --git a/test/urls.js b/test/urls.js index 5e0c06e..14255c1 100644 --- a/test/urls.js +++ b/test/urls.js @@ -2033,6 +2033,55 @@ var urls = [{ idn: false, punycode: false } + }, { + name: 'backslashes authority, no ending slash', + url: 'https://attacker.com\\@example.com', + _url: 'https://attacker.com/@example.com', + parts: { + protocol: 'https', + username: null, + password: null, + hostname: 'attacker.com', + port: null, + path: '/@example.com', + query: null, + fragment: null + }, + accessors: { + protocol: 'https', + username: '', + password: '', + port: '', + path: '/@example.com', + query: '', + fragment: '', + resource: '/@example.com', + authority: 'attacker.com', + origin: 'https://attacker.com', + userinfo: '', + subdomain: '', + domain: 'attacker.com', + tld: 'com', + directory: '/', + filename: '@example.com', + suffix: 'com', + hash: '', + search: '', + host: 'attacker.com', + hostname: 'attacker.com' + }, + is: { + urn: false, + url: true, + relative: false, + name: true, + sld: false, + ip: false, + ip4: false, + ip6: false, + idn: false, + punycode: false + } } ]; From 944822ae32a0984e13bad4452b5cfac158c22218 Mon Sep 17 00:00:00 2001 From: Alesandro Ortiz Date: Mon, 21 Dec 2020 14:11:02 -0500 Subject: [PATCH 2/3] Revert URI.js commit a79563a --- src/URI.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/URI.js b/src/URI.js index 9eb7ce3..715c097 100644 --- a/src/URI.js +++ b/src/URI.js @@ -549,6 +549,13 @@ string = ''; } + // Copy chrome, IE, opera backslash-handling behavior. + // Back slashes before the query string get converted to forward slashes + // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 + // See: https://code.google.com/p/chromium/issues/detail?id=25916 + // https://github.com/medialize/URI.js/pull/233 + string = string.replace(/\\/g, '/'); + // extract host:port var pos = string.indexOf('/'); var bracketPos; @@ -600,24 +607,19 @@ return string.substring(pos) || '/'; }; URI.parseAuthority = function(string, parts) { - // Copy chrome, IE, opera backslash-handling behavior. - // Back slashes before the query string get converted to forward slashes - // See: https://github.com/joyent/node/blob/386fd24f49b0e9d1a8a076592a404168faeecc34/lib/url.js#L115-L124 - // See: https://code.google.com/p/chromium/issues/detail?id=25916 - // https://github.com/medialize/URI.js/pull/233 - string = string.replace(/\\/g, '/'); - string = URI.parseUserinfo(string, parts); return URI.parseHost(string, parts); }; URI.parseUserinfo = function(string, parts) { // extract username:password + var firstBackSlash = string.indexOf('\\'); var firstSlash = string.indexOf('/'); + var slash = firstBackSlash === -1 ? firstSlash : (firstSlash !== -1 ? Math.min(firstBackSlash, firstSlash): firstSlash) var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); var t; // authority@ must come before /path or \path - if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { + if (pos > -1 && (slash === -1 || pos < slash)) { t = string.substring(0, pos).split(':'); parts.username = t[0] ? URI.decode(t[0]) : null; t.shift(); From f72e41b844acd65a31a8c7b6bf1ad60795c1946d Mon Sep 17 00:00:00 2001 From: Alesandro Ortiz Date: Mon, 21 Dec 2020 14:23:12 -0500 Subject: [PATCH 3/3] Apply rodneyrehm's patch Apply patch from https://github.com/medialize/URI.js/pull/403#issuecomment-749111466 --- src/URI.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/URI.js b/src/URI.js index 715c097..92c0481 100644 --- a/src/URI.js +++ b/src/URI.js @@ -612,19 +612,22 @@ }; URI.parseUserinfo = function(string, parts) { // extract username:password + var _string = string var firstBackSlash = string.indexOf('\\'); + if (firstBackSlash !== -1) { + string = string.replace(/\\/g, '/') + } var firstSlash = string.indexOf('/'); - var slash = firstBackSlash === -1 ? firstSlash : (firstSlash !== -1 ? Math.min(firstBackSlash, firstSlash): firstSlash) var pos = string.lastIndexOf('@', firstSlash > -1 ? firstSlash : string.length - 1); var t; // authority@ must come before /path or \path - if (pos > -1 && (slash === -1 || pos < slash)) { + if (pos > -1 && (firstSlash === -1 || pos < firstSlash)) { t = string.substring(0, pos).split(':'); parts.username = t[0] ? URI.decode(t[0]) : null; t.shift(); parts.password = t[0] ? URI.decode(t.join(':')) : null; - string = string.substring(pos + 1); + string = _string.substring(pos + 1); } else { parts.username = null; parts.password = null;