- for(char ch='A';ch <= 'Z';++ch)\r
- UNESCAPED_US_ASCII_CHARS[ch] = true;\r
- for(char ch='a';ch <= 'z';++ch)\r
- UNESCAPED_US_ASCII_CHARS[ch] = true;\r
- for(char ch='0';ch <= '9';++ch)\r
- UNESCAPED_US_ASCII_CHARS[ch] = true;\r
- UNESCAPED_US_ASCII_CHARS[';'] = true;\r
- UNESCAPED_US_ASCII_CHARS['?'] = true;\r
- UNESCAPED_US_ASCII_CHARS[':'] = true;\r
- UNESCAPED_US_ASCII_CHARS['@'] = true;\r
- UNESCAPED_US_ASCII_CHARS['='] = true;\r
- UNESCAPED_US_ASCII_CHARS['+'] = true;\r
- UNESCAPED_US_ASCII_CHARS['$'] = true;\r
- UNESCAPED_US_ASCII_CHARS['.'] = true;\r
- UNESCAPED_US_ASCII_CHARS[','] = true;\r
- UNESCAPED_US_ASCII_CHARS['-'] = true;\r
- UNESCAPED_US_ASCII_CHARS['_'] = true;\r
- UNESCAPED_US_ASCII_CHARS['!'] = true;\r
- UNESCAPED_US_ASCII_CHARS['~'] = true;\r
- UNESCAPED_US_ASCII_CHARS['*'] = true;\r
- UNESCAPED_US_ASCII_CHARS['\''] = true;\r
- UNESCAPED_US_ASCII_CHARS['('] = true;\r
- UNESCAPED_US_ASCII_CHARS[')'] = true;\r
- UNESCAPED_US_ASCII_CHARS['['] = true;\r
- UNESCAPED_US_ASCII_CHARS[']'] = true;\r
+ ESCAPED_US_ASCII_CHARS[' '] = true;\r
+ // IMPORTANT NOTE: every time escape is invoked, all input needs to be escaped,\r
+ // i.e. escape("%01") should result in "%2501", not "%01".\r
+ // escape and unescape form a bijection, where neither\r
+ // of them is an idempotent operation. \r
+ ESCAPED_US_ASCII_CHARS['%'] = true;\r
+ // '#' and '/' are URL segment/fragment delimiters, need to be escaped in names.\r
+ ESCAPED_US_ASCII_CHARS['#'] = true;\r
+ ESCAPED_US_ASCII_CHARS['/'] = true;\r
+ // Escape '&' characters to avoid them being interpreted as SGML entities.\r
+ ESCAPED_US_ASCII_CHARS['&'] = true;\r