| 846 | |
| 847 | |
| 848 | string encode(const string& s, const string& additional_chars) |
| 849 | { |
| 850 | ostringstream out; |
| 851 | |
| 852 | foreach (unsigned char c, s) { |
| 853 | switch (c) { |
| 854 | // Reserved characters. |
| 855 | case '$': |
| 856 | case '&': |
| 857 | case '+': |
| 858 | case ',': |
| 859 | case '/': |
| 860 | case ':': |
| 861 | case ';': |
| 862 | case '=': |
| 863 | case '?': |
| 864 | case '@': |
| 865 | // Unsafe characters. |
| 866 | case ' ': |
| 867 | case '"': |
| 868 | case '<': |
| 869 | case '>': |
| 870 | case '#': |
| 871 | case '%': |
| 872 | case '{': |
| 873 | case '}': |
| 874 | case '|': |
| 875 | case '\\': |
| 876 | case '^': |
| 877 | case '~': |
| 878 | case '[': |
| 879 | case ']': |
| 880 | case '`': |
| 881 | // NOTE: The cast to unsigned int is needed. |
| 882 | out << '%' << std::setfill('0') << std::setw(2) << std::hex |
| 883 | << std::uppercase << (unsigned int) c; |
| 884 | break; |
| 885 | default: |
| 886 | // ASCII control characters and non-ASCII characters. |
| 887 | // NOTE: The cast to unsigned int is needed. |
| 888 | if (c < 0x20 || |
| 889 | c > 0x7F || |
| 890 | additional_chars.find_first_of(c) != string::npos) { |
| 891 | out << '%' << std::setfill('0') << std::setw(2) << std::hex |
| 892 | << std::uppercase << (unsigned int) c; |
| 893 | } else { |
| 894 | out << c; |
| 895 | } |
| 896 | break; |
| 897 | } |
| 898 | } |
| 899 | |
| 900 | return out.str(); |
| 901 | } |
| 902 | |
| 903 | |
| 904 | Try<string> decode(const string& s) |