Skip to content

Commit 7b0b8a6

Browse files
authoredFeb 13, 2022
Merge pull request #223 from unshiftio/fix/at-sign-handling-in-userinfo
Correctly handle userinfo containing the at sign
2 parents e4a5807 + 9be7ee8 commit 7b0b8a6

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
@@ -306,7 +306,11 @@ function Url(address, location, parser) {
306306
if (parse !== parse) {
307307
url[key] = address;
308308
} else if ('string' === typeof parse) {
309-
if (~(index = address.indexOf(parse))) {
309+
index = parse === '@'
310+
? address.lastIndexOf(parse)
311+
: address.indexOf(parse);
312+
313+
if (~index) {
310314
if ('number' === typeof instruction[2]) {
311315
url[key] = address.slice(0, index);
312316
address = address.slice(index + instruction[2]);
@@ -372,10 +376,21 @@ function Url(address, location, parser) {
372376
// Parse down the `auth` for the username and password.
373377
//
374378
url.username = url.password = '';
379+
375380
if (url.auth) {
376-
instruction = url.auth.split(':');
377-
url.username = instruction[0];
378-
url.password = instruction[1] || '';
381+
index = url.auth.indexOf(':');
382+
383+
if (~index) {
384+
url.username = url.auth.slice(0, index);
385+
url.username = encodeURIComponent(decodeURIComponent(url.username));
386+
387+
url.password = url.auth.slice(index + 1);
388+
url.password = encodeURIComponent(decodeURIComponent(url.password))
389+
} else {
390+
url.username = encodeURIComponent(decodeURIComponent(url.auth));
391+
}
392+
393+
url.auth = url.password ? url.username +':'+ url.password : url.username;
379394
}
380395

381396
url.origin = url.protocol !== 'file:' && isSpecial(url.protocol) && url.host
@@ -467,9 +482,17 @@ function set(part, value, fn) {
467482
break;
468483

469484
case 'auth':
470-
var splits = value.split(':');
471-
url.username = splits[0];
472-
url.password = splits.length === 2 ? splits[1] : '';
485+
var index = value.indexOf(':');
486+
487+
if (~index) {
488+
url.username = value.slice(0, index);
489+
url.username = encodeURIComponent(decodeURIComponent(url.username));
490+
491+
url.password = value.slice(index + 1);
492+
url.password = encodeURIComponent(decodeURIComponent(url.password));
493+
} else {
494+
url.username = encodeURIComponent(decodeURIComponent(value));
495+
}
473496
}
474497

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

‎test/test.js

+68
Original file line numberDiff line numberDiff line change
@@ -723,6 +723,54 @@ describe('url-parse', function () {
723723
assume(parsed.hostname).equals('www.example.com');
724724
assume(parsed.href).equals(url);
725725
});
726+
727+
it('handles @ in username', function () {
728+
var url = 'http://user@@www.example.com/'
729+
, parsed = parse(url);
730+
731+
assume(parsed.protocol).equals('http:');
732+
assume(parsed.auth).equals('user%40');
733+
assume(parsed.username).equals('user%40');
734+
assume(parsed.password).equals('');
735+
assume(parsed.hostname).equals('www.example.com');
736+
assume(parsed.pathname).equals('/');
737+
assume(parsed.href).equals('http://user%40@www.example.com/');
738+
739+
url = 'http://user%40@www.example.com/';
740+
parsed = parse(url);
741+
742+
assume(parsed.protocol).equals('http:');
743+
assume(parsed.auth).equals('user%40');
744+
assume(parsed.username).equals('user%40');
745+
assume(parsed.password).equals('');
746+
assume(parsed.hostname).equals('www.example.com');
747+
assume(parsed.pathname).equals('/');
748+
assume(parsed.href).equals('http://user%40@www.example.com/');
749+
});
750+
751+
it('handles @ in password', function () {
752+
var url = 'http://user@:pas:s@@www.example.com/'
753+
, parsed = parse(url);
754+
755+
assume(parsed.protocol).equals('http:');
756+
assume(parsed.auth).equals('user%40:pas%3As%40');
757+
assume(parsed.username).equals('user%40');
758+
assume(parsed.password).equals('pas%3As%40');
759+
assume(parsed.hostname).equals('www.example.com');
760+
assume(parsed.pathname).equals('/');
761+
assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');
762+
763+
url = 'http://user%40:pas%3As%40@www.example.com/'
764+
parsed = parse(url);
765+
766+
assume(parsed.protocol).equals('http:');
767+
assume(parsed.auth).equals('user%40:pas%3As%40');
768+
assume(parsed.username).equals('user%40');
769+
assume(parsed.password).equals('pas%3As%40');
770+
assume(parsed.hostname).equals('www.example.com');
771+
assume(parsed.pathname).equals('/');
772+
assume(parsed.href).equals('http://user%40:pas%3As%40@www.example.com/');
773+
});
726774
});
727775

728776
it('accepts multiple ???', function () {
@@ -1158,6 +1206,26 @@ describe('url-parse', function () {
11581206
assume(data.username).equals('');
11591207
assume(data.password).equals('quux');
11601208
assume(data.href).equals('https://:quux@example.com/');
1209+
1210+
assume(data.set('auth', 'user@:pass@')).equals(data);
1211+
assume(data.username).equals('user%40');
1212+
assume(data.password).equals('pass%40');
1213+
assume(data.href).equals('https://user%40:pass%40@example.com/');
1214+
1215+
assume(data.set('auth', 'user%40:pass%40')).equals(data);
1216+
assume(data.username).equals('user%40');
1217+
assume(data.password).equals('pass%40');
1218+
assume(data.href).equals('https://user%40:pass%40@example.com/');
1219+
1220+
assume(data.set('auth', 'user:pass:word')).equals(data);
1221+
assume(data.username).equals('user');
1222+
assume(data.password).equals('pass%3Aword');
1223+
assume(data.href).equals('https://user:pass%3Aword@example.com/');
1224+
1225+
assume(data.set('auth', 'user:pass%3Aword')).equals(data);
1226+
assume(data.username).equals('user');
1227+
assume(data.password).equals('pass%3Aword');
1228+
assume(data.href).equals('https://user:pass%3Aword@example.com/');
11611229
});
11621230

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

0 commit comments

Comments
 (0)
Please sign in to comment.