8000
We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
There was an error while loading. Please reload this page.
1 parent c4902e4 commit ea1c4e1Copy full SHA for ea1c4e1
lib/url.js
@@ -437,105 +437,111 @@ function validateHostname(self, rest, hostname) {
437
}
438
439
440
+// Automatically escape all delimiters and unwise characters from RFC 2396.
441
+// Also escape single quotes in case of an XSS attack.
442
+// Return undefined if the string doesn't need escaping,
443
+// otherwise return the escaped string.
444
function autoEscapeStr(rest) {
- var newRest = '';
- var lastPos = 0;
445
+ var escaped = '';
446
+ var lastEscapedPos = 0;
447
for (var i = 0; i < rest.length; ++i) {
- // Automatically escape all delimiters and unwise characters from RFC 2396
- // Also escape single quotes in case of an XSS attack
448
+ // Manual switching is faster than using a Map/Object.
449
+ // `escaped` contains substring up to the last escaped cahracter.
450
switch (rest.charCodeAt(i)) {
451
case 9: // '\t'
- if (i - lastPos > 0)
- newRest += rest.slice(lastPos, i);
- newRest += '%09';
- lastPos = i + 1;
452
+ // Concat if there are ordinary characters in the middle.
453
+ if (i > lastEscapedPos)
454
+ escaped += rest.slice(lastEscapedPos, i);
455
+ escaped += '%09';
456
+ lastEscapedPos = i + 1;
457
break;
458
case 10: // '\n'
- newRest += '%0A';
459
460
461
+ escaped += '%0A';
462
463
464
case 13: // '\r'
- newRest += '%0D';
465
466
467
+ escaped += '%0D';
468
469
470
case 32: // ' '
- newRest += '%20';
471
472
473
+ escaped += '%20';
474
475
476
case 34: // '"'
- newRest += '%22';
477
478
479
+ escaped += '%22';
480
481
482
case 39: // '\''
- newRest += '%27';
483
484
485
+ escaped += '%27';
486
487
488
case 60: // '<'
- newRest += '%3C';
489
490
491
+ escaped += '%3C';
492
493
494
case 62: // '>'
- newRest += '%3E';
495
496
497
+ escaped += '%3E';
498
499
500
case 92: // '\\'
- newRest += '%5C';
501
502
503
+ escaped += '%5C';
504
505
506
case 94: // '^'
- newRest += '%5E';
507
508
509
+ escaped += '%5E';
510
511
512
case 96: // '`'
- newRest += '%60';
513
514
515
+ escaped += '%60';
516
517
518
case 123: // '{'
- newRest += '%7B';
519
520
521
+ escaped += '%7B';
522
523
524
case 124: // '|'
- newRest += '%7C';
525
526
527
+ escaped += '%7C';
528
529
530
case 125: // '}'
- newRest += '%7D';
531
532
533
+ escaped += '%7D';
534
535
536
537
- if (lastPos === 0)
538
+ if (lastEscapedPos === 0) // Nothing has been escaped.
539
return;
- if (lastPos < rest.length)
- return newRest + rest.slice(lastPos);
- else
- return newRest;
540
+ // There are ordinary characters at the end.
541
+ if (lastEscapedPos < rest.length)
542
+ return escaped + rest.slice(lastEscapedPos);
543
+ else // The last character is escaped.
544
+ return escaped;
545
546
547
// format a parsed object into a url string
test/parallel/test-url.js
@@ -834,6 +834,20 @@ var parseTests = {
834
query: '@c'
835
},
836
837
+ 'http://a.b/\tbc\ndr\ref g"hq\'j<kl>?mn\\op^q=r`99{st|uv}wz': {
838
+ protocol: 'http:',
839
+ slashes: true,
840
+ host: 'a.b',
841
+ port: null,
842
+ hostname: 'a.b',
843
+ hash: null,
844
+ pathname: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E',
845
+ path: '/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
846
+ search: '?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
847
+ query: 'mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz',
848
+ href: 'http://a.b/%09bc%0Adr%0Def%20g%22hq%27j%3Ckl%3E?mn%5Cop%5Eq=r%6099%7Bst%7Cuv%7Dwz'
849
+ },
850
+
851
'http://a\r" \t\n<\'b:b@c\r\nd/e?f': {
852
protocol: 'http:',
853
slashes: true,