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