Skip to content

Commit 9be7ee8

Browse files
committedJan 30, 2022
[fix] Correctly handle userinfo containing the at sign
1 parent 82c4908 commit 9be7ee8

File tree

2 files changed

+98
-7
lines changed

2 files changed

+98
-7
lines changed
 

‎index.js

+30-7
Original file line numberDiff line numberDiff line change
@@ -304,7 +304,11 @@ function Url(address, location, parser) {
304304
if (parse !== parse) {
305305
url[key] = address;
306306
} else if ('string' === typeof parse) {
307-
if (~(index = address.indexOf(parse))) {
307+
index = parse === '@'
308+
? address.lastIndexOf(parse)
309+
: address.indexOf(parse);
310+
311+
if (~index) {
308312
if ('number' === typeof instruction[2]) {
309313
url[key] = address.slice(0, index);
310314
address = address.slice(index + instruction[2]);
@@ -370,10 +374,21 @@ function Url(address, location, parser) {
370374
// Parse down the `auth` for the username and password.
371375
//
372376
url.username = url.password = '';
377+
373378
if (url.auth) {
374-
instruction = url.auth.split(':');
375-
url.username = instruction[0];
376-
url.password = instruction[1] || '';
379+
index = url.auth.indexOf(':');
380+
381+
if (~index) {
382+
url.username = url.auth.slice(0, index);
383+
url.username = encodeURIComponent(decodeURIComponent(url.username));
384+
385+
url.password = url.auth.slice(index + 1);
386+
url.password = encodeURIComponent(decodeURIComponent(url.password))
387+
} else {
388+
url.username = encodeURIComponent(decodeURIComponent(url.auth));
389+
}
390+
391+
url.auth = url.password ? url.username +':'+ url.password : url.username;
377392
}
378393

379394
url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host
@@ -465,9 +480,17 @@ function set(part, value, fn) {
465480
break;
466481

467482
case 'auth':
468-
var splits = value.split(':');
469-
url.username = splits[0];
470-
url.password = splits.length === 2 ? splits[1] : '';
483+
var index = value.indexOf(':');
484+
485+
if (~index) {
486+
url.username = value.slice(0, index);
487+
url.username = encodeURIComponent(decodeURIComponent(url.username));
488+
489+
url.password = value.slice(index + 1);
490+
url.password = encodeURIComponent(decodeURIComponent(url.password));
491+
} else {
492+
url.username = encodeURIComponent(decodeURIComponent(value));
493+
}
471494
}
472495

473496
for (var i = 0; i < rules.length; i++) {

‎test/test.js

+68
Original file line numberDiff line numberDiff line change
@@ -689,6 +689,54 @@ describe('url-parse', function () {
689689
assume(parsed.hostname).equals('www.example.com');
690690
assume(parsed.href).equals(url);
691691
});
692+
693+
it('handles @ in username', function () {
694+
var url = 'http://user@@www.example.com/'
695+
, parsed = parse(url);
696+
697+
assume(parsed.protocol).equals('http:');
698+
assume(parsed.auth).equals('user%40');
699+
assume(parsed.username).equals('user%40');
700+
assume(parsed.password).equals('');
701+
assume(parsed.hostname).equals('www.example.com');
702+
assume(parsed.pathname).equals('/');
703+
assume(parsed.href).equals('http://user%40@www.example.com/');
704+
705+
url = 'http://user%40@www.example.com/';
706+
parsed = parse(url);
707+
708+
assume(parsed.protocol).equals('http:');
709+
assume(parsed.auth).equals('user%40');
710+
assume(parsed.username).equals('user%40');
711+
assume(parsed.password).equals('');
712+
assume(parsed.hostname).equals('www.example.com');
713+
assume(parsed.pathname).equals('/');
714+
assume(parsed.href).equals('http://user%40@www.example.com/');
715+
});
716+
717+
it('handles @ in password', function () {
718+
var url = 'http://user@:pas:s@@www.example.com/'
719+
, parsed = parse(url);
720+
721+
assume(parsed.protocol).equals('http:');
722+
assume(parsed.auth).equals('user%40:pas%3As%40');
723+
assume(parsed.username).equals('user%40');
724+
assume(parsed.password).equals('pas%3As%40');
725+
assume(parsed.hostname).equals('www.example.com');
726+
assume(parsed.pathname).equals('/');
727+
assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');
728+
729+
url = 'http://user%40:pas%3As%40@www.example.com/'
730+
parsed = parse(url);
731+
732+
assume(parsed.protocol).equals('http:');
733+
assume(parsed.auth).equals('user%40:pas%3As%40');
734+
assume(parsed.username).equals('user%40');
735+
assume(parsed.password).equals('pas%3As%40');
736+
assume(parsed.hostname).equals('www.example.com');
737+
assume(parsed.pathname).equals('/');
738+
assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');
739+
});
692740
});
693741

694742
it('accepts multiple ???', function () {
@@ -1124,6 +1172,26 @@ describe('url-parse', function () {
11241172
assume(data.username).equals('');
11251173
assume(data.password).equals('quux');
11261174
assume(data.href).equals('https://:quux@example.com/');
1175+
1176+
assume(data.set('auth', 'user@:pass@')).equals(data);
1177+
assume(data.username).equals('user%40');
1178+
assume(data.password).equals('pass%40');
1179+
assume(data.href).equals('https://user%40:pass%40@example.com/');
1180+
1181+
assume(data.set('auth', 'user%40:pass%40')).equals(data);
1182+
assume(data.username).equals('user%40');
1183+
assume(data.password).equals('pass%40');
1184+
assume(data.href).equals('https://user%40:pass%40@example.com/');
1185+
1186+
assume(data.set('auth', 'user:pass:word')).equals(data);
1187+
assume(data.username).equals('user');
1188+
assume(data.password).equals('pass%3Aword');
1189+
assume(data.href).equals('https://user:pass%3Aword@example.com/');
1190+
1191+
assume(data.set('auth', 'user:pass%3Aword')).equals(data);
1192+
assume(data.username).equals('user');
1193+
assume(data.password).equals('pass%3Aword');
1194+
assume(data.href).equals('https://user:pass%3Aword@example.com/');
11271195
});
11281196

11291197
it('updates other values', function () {

0 commit comments

Comments
 (0)
Please sign in to comment.