@@ -437,105 +437,111 @@ function validateHostname(self, rest, hostname) {
437
437
}
438
438
}
439
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.
440
444
function autoEscapeStr ( rest ) {
441
- var newRest = '' ;
442
- var lastPos = 0 ;
445
+ var escaped = '' ;
446
+ var lastEscapedPos = 0 ;
443
447
for ( var i = 0 ; i < rest . length ; ++ i ) {
444
- // Automatically escape all delimiters and unwise characters from RFC 2396
445
- // 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.
446
450
switch ( rest . charCodeAt ( i ) ) {
447
451
case 9 : // '\t'
448
- if ( i - lastPos > 0 )
449
- newRest += rest . slice ( lastPos , i ) ;
450
- newRest += '%09' ;
451
- 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 ;
452
457
break ;
453
458
case 10 : // '\n'
454
- if ( i - lastPos > 0 )
455
- newRest += rest . slice ( lastPos , i ) ;
456
- newRest += '%0A' ;
457
- lastPos = i + 1 ;
459
+ if ( i > lastEscapedPos )
460
+ escaped += rest . slice ( lastEscapedPos , i ) ;
461
+ escaped += '%0A' ;
462
+ lastEscapedPos = i + 1 ;
458
463
break ;
459
464
case 13 : // '\r'
460
- if ( i - lastPos > 0 )
461
- newRest += rest . slice ( lastPos , i ) ;
462
- newRest += '%0D' ;
463
- lastPos = i + 1 ;
465
+ if ( i > lastEscapedPos )
466
+ escaped += rest . slice ( lastEscapedPos , i ) ;
467
+ escaped += '%0D' ;
468
+ lastEscapedPos = i + 1 ;
464
469
break ;
465
470
case 32 : // ' '
466
- if ( i - lastPos > 0 )
467
- newRest += rest . slice ( lastPos , i ) ;
468
- newRest += '%20' ;
469
- lastPos = i + 1 ;
471
+ if ( i > lastEscapedPos )
472
+ escaped += rest . slice ( lastEscapedPos , i ) ;
473
+ escaped += '%20' ;
474
+ lastEscapedPos = i + 1 ;
470
475
break ;
471
476
case 34 : // '"'
472
- if ( i - lastPos > 0 )
473
- newRest += rest . slice ( lastPos , i ) ;
474
- newRest += '%22' ;
475
- lastPos = i + 1 ;
477
+ if ( i > lastEscapedPos )
478
+ escaped += rest . slice ( lastEscapedPos , i ) ;
479
+ escaped += '%22' ;
480
+ lastEscapedPos = i + 1 ;
476
481
break ;
477
482
case 39 : // '\''
478
- if ( i - lastPos > 0 )
479
- newRest += rest . slice ( lastPos , i ) ;
480
- newRest += '%27' ;
481
- lastPos = i + 1 ;
483
+ if ( i > lastEscapedPos )
484
+ escaped += rest . slice ( lastEscapedPos , i ) ;
485
+ escaped += '%27' ;
486
+ lastEscapedPos = i + 1 ;
482
487
break ;
483
488
case 60 : // '<'
484
- if ( i - lastPos > 0 )
485
- newRest += rest . slice ( lastPos , i ) ;
486
- newRest += '%3C' ;
487
- lastPos = i + 1 ;
489
+ if ( i > lastEscapedPos )
490
+ escaped += rest . slice ( lastEscapedPos , i ) ;
491
+ escaped += '%3C' ;
492
+ lastEscapedPos = i + 1 ;
488
493
break ;
489
494
case 62 : // '>'
490
- if ( i - lastPos > 0 )
491
- newRest += rest . slice ( lastPos , i ) ;
492
- newRest += '%3E' ;
493
- lastPos = i + 1 ;
495
+ if ( i > lastEscapedPos )
496
+ escaped += rest . slice ( lastEscapedPos , i ) ;
497
+ escaped += '%3E' ;
498
+ lastEscapedPos = i + 1 ;
494
499
break ;
495
500
case 92 : // '\\'
496
- if ( i - lastPos > 0 )
497
- newRest += rest . slice ( lastPos , i ) ;
498
- newRest += '%5C' ;
499
- lastPos = i + 1 ;
501
+ if ( i > lastEscapedPos )
502
+ escaped += rest . slice ( lastEscapedPos , i ) ;
503
+ escaped += '%5C' ;
504
+ lastEscapedPos = i + 1 ;
500
505
break ;
501
506
case 94 : // '^'
502
- if ( i - lastPos > 0 )
503
- newRest += rest . slice ( lastPos , i ) ;
504
- newRest += '%5E' ;
505
- lastPos = i + 1 ;
507
+ if ( i > lastEscapedPos )
508
+ escaped += rest . slice ( lastEscapedPos , i ) ;
509
+ escaped += '%5E' ;
510
+ lastEscapedPos = i + 1 ;
506
511
break ;
507
512
case 96 : // '`'
508
- if ( i - lastPos > 0 )
509
- newRest += rest . slice ( lastPos , i ) ;
510
- newRest += '%60' ;
511
- lastPos = i + 1 ;
513
+ if ( i > lastEscapedPos )
514
+ escaped += rest . slice ( lastEscapedPos , i ) ;
515
+ escaped += '%60' ;
516
+ lastEscapedPos = i + 1 ;
512
517
break ;
513
518
case 123 : // '{'
514
- if ( i - lastPos > 0 )
515
- newRest += rest . slice ( lastPos , i ) ;
516
- newRest += '%7B' ;
517
- lastPos = i + 1 ;
519
+ if ( i > lastEscapedPos )
520
+ escaped += rest . slice ( lastEscapedPos , i ) ;
521
+ escaped += '%7B' ;
522
+ lastEscapedPos = i + 1 ;
518
523
break ;
519
524
case 124 : // '|'
520
- if ( i - lastPos > 0 )
521
- newRest += rest . slice ( lastPos , i ) ;
522
- newRest += '%7C' ;
523
- lastPos = i + 1 ;
525
+ if ( i > lastEscapedPos )
526
+ escaped += rest . slice ( lastEscapedPos , i ) ;
527
+ escaped += '%7C' ;
528
+ lastEscapedPos = i + 1 ;
524
529
break ;
525
530
case 125 : // '}'
526
- if ( i - lastPos > 0 )
527
- newRest += rest . slice ( lastPos , i ) ;
528
- newRest += '%7D' ;
529
- lastPos = i + 1 ;
531
+ if ( i > lastEscapedPos )
532
+ escaped += rest . slice ( lastEscapedPos , i ) ;
533
+ escaped += '%7D' ;
534
+ lastEscapedPos = i + 1 ;
530
535
break ;
531
536
}
532
537
}
533
- if ( lastPos === 0 )
538
+ if ( lastEscapedPos === 0 ) // Nothing has been escaped.
534
539
return ;
535
- if ( lastPos < rest . length )
536
- return newRest + rest . slice ( lastPos ) ;
537
- else
538
- 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 ;
539
545
}
540
546
541
547
// format a parsed object into a url string
0 commit comments