@@ -437,105 +437,111 @@ function validateHostname(self, rest, hostname) {
437437 }
438438}
439439
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.
440444function autoEscapeStr ( rest ) {
441- var newRest = '' ;
442- var lastPos = 0 ;
445+ var escaped = '' ;
446+ var lastEscapedPos = 0 ;
443447 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.
446450 switch ( rest . charCodeAt ( i ) ) {
447451 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 ;
452457 break ;
453458 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 ;
458463 break ;
459464 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 ;
464469 break ;
465470 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 ;
470475 break ;
471476 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 ;
476481 break ;
477482 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 ;
482487 break ;
483488 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 ;
488493 break ;
489494 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 ;
494499 break ;
495500 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 ;
500505 break ;
501506 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 ;
506511 break ;
507512 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 ;
512517 break ;
513518 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 ;
518523 break ;
519524 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 ;
524529 break ;
525530 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 ;
530535 break ;
531536 }
532537 }
533- if ( lastPos === 0 )
538+ if ( lastEscapedPos === 0 ) // Nothing has been escaped.
534539 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 ;
539545}
540546
541547// format a parsed object into a url string
0 commit comments