| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2008 The WebRTC Project Authors. All rights reserved. | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license | |
| 5 * that can be found in the LICENSE file in the root of the source | |
| 6 * tree. An additional intellectual property rights grant can be found | |
| 7 * in the file PATENTS. All contributing project authors may | |
| 8 * be found in the AUTHORS file in the root of the source tree. | |
| 9 */ | |
| 10 | |
| 11 #include "webrtc/base/urlencode.h" | |
| 12 | |
| 13 #include "webrtc/base/checks.h" | |
| 14 #include "webrtc/base/stringutils.h" | |
| 15 | |
| 16 static int HexPairValue(const char * code) { | |
| 17 int value = 0; | |
| 18 for (const char * pch = code; pch < code + 2; ++pch) { | |
| 19 value <<= 4; | |
| 20 int digit = *pch; | |
| 21 if (digit >= '0' && digit <= '9') { | |
| 22 value += digit - '0'; | |
| 23 } | |
| 24 else if (digit >= 'A' && digit <= 'F') { | |
| 25 value += digit - 'A' + 10; | |
| 26 } | |
| 27 else if (digit >= 'a' && digit <= 'f') { | |
| 28 value += digit - 'a' + 10; | |
| 29 } | |
| 30 else { | |
| 31 return -1; | |
| 32 } | |
| 33 } | |
| 34 return value; | |
| 35 } | |
| 36 | |
| 37 static int InternalUrlDecode(const char *source, char *dest, | |
| 38 bool encode_space_as_plus) { | |
| 39 char * start = dest; | |
| 40 | |
| 41 while (*source) { | |
| 42 switch (*source) { | |
| 43 case '+': | |
| 44 if (encode_space_as_plus) { | |
| 45 *(dest++) = ' '; | |
| 46 } else { | |
| 47 *dest++ = *source; | |
| 48 } | |
| 49 break; | |
| 50 case '%': | |
| 51 if (source[1] && source[2]) { | |
| 52 int value = HexPairValue(source + 1); | |
| 53 if (value >= 0) { | |
| 54 *(dest++) = static_cast<char>(value); | |
| 55 source += 2; | |
| 56 } | |
| 57 else { | |
| 58 *dest++ = '?'; | |
| 59 } | |
| 60 } | |
| 61 else { | |
| 62 *dest++ = '?'; | |
| 63 } | |
| 64 break; | |
| 65 default: | |
| 66 *dest++ = *source; | |
| 67 } | |
| 68 source++; | |
| 69 } | |
| 70 | |
| 71 *dest = 0; | |
| 72 return static_cast<int>(dest - start); | |
| 73 } | |
| 74 | |
| 75 static bool IsValidUrlChar(char ch, bool unsafe_only) { | |
| 76 if (unsafe_only) { | |
| 77 return !(ch <= ' ' || strchr("\\\"^&`<>[]{}", ch)); | |
| 78 } else { | |
| 79 return isalnum(ch) || strchr("-_.!~*'()", ch); | |
| 80 } | |
| 81 } | |
| 82 | |
| 83 namespace rtc { | |
| 84 | |
| 85 int UrlDecode(const char *source, char *dest) { | |
| 86 return InternalUrlDecode(source, dest, true); | |
| 87 } | |
| 88 | |
| 89 int UrlDecodeWithoutEncodingSpaceAsPlus(const char *source, char *dest) { | |
| 90 return InternalUrlDecode(source, dest, false); | |
| 91 } | |
| 92 | |
| 93 int InternalUrlEncode(const char *source, char *dest, unsigned int max, | |
| 94 bool encode_space_as_plus, bool unsafe_only) { | |
| 95 static const char *digits = "0123456789ABCDEF"; | |
| 96 if (max == 0) { | |
| 97 return 0; | |
| 98 } | |
| 99 | |
| 100 char *start = dest; | |
| 101 while (static_cast<unsigned>(dest - start) < max && *source) { | |
| 102 unsigned char ch = static_cast<unsigned char>(*source); | |
| 103 if (*source == ' ' && encode_space_as_plus && !unsafe_only) { | |
| 104 *dest++ = '+'; | |
| 105 } else if (IsValidUrlChar(ch, unsafe_only)) { | |
| 106 *dest++ = *source; | |
| 107 } else { | |
| 108 if (static_cast<unsigned>(dest - start) + 4 > max) { | |
| 109 break; | |
| 110 } | |
| 111 *dest++ = '%'; | |
| 112 *dest++ = digits[(ch >> 4) & 0x0F]; | |
| 113 *dest++ = digits[ ch & 0x0F]; | |
| 114 } | |
| 115 source++; | |
| 116 } | |
| 117 RTC_DCHECK_LT(static_cast<unsigned int>(dest - start), max); | |
| 118 *dest = 0; | |
| 119 | |
| 120 return static_cast<int>(dest - start); | |
| 121 } | |
| 122 | |
| 123 int UrlEncode(const char *source, char *dest, unsigned max) { | |
| 124 return InternalUrlEncode(source, dest, max, true, false); | |
| 125 } | |
| 126 | |
| 127 int UrlEncodeWithoutEncodingSpaceAsPlus(const char *source, char *dest, | |
| 128 unsigned max) { | |
| 129 return InternalUrlEncode(source, dest, max, false, false); | |
| 130 } | |
| 131 | |
| 132 int UrlEncodeOnlyUnsafeChars(const char *source, char *dest, unsigned max) { | |
| 133 return InternalUrlEncode(source, dest, max, false, true); | |
| 134 } | |
| 135 | |
| 136 std::string | |
| 137 InternalUrlDecodeString(const std::string & encoded, | |
| 138 bool encode_space_as_plus) { | |
| 139 size_t needed_length = encoded.length() + 1; | |
| 140 char* buf = STACK_ARRAY(char, needed_length); | |
| 141 InternalUrlDecode(encoded.c_str(), buf, encode_space_as_plus); | |
| 142 return buf; | |
| 143 } | |
| 144 | |
| 145 std::string | |
| 146 UrlDecodeString(const std::string & encoded) { | |
| 147 return InternalUrlDecodeString(encoded, true); | |
| 148 } | |
| 149 | |
| 150 std::string | |
| 151 UrlDecodeStringWithoutEncodingSpaceAsPlus(const std::string & encoded) { | |
| 152 return InternalUrlDecodeString(encoded, false); | |
| 153 } | |
| 154 | |
| 155 std::string | |
| 156 InternalUrlEncodeString(const std::string & decoded, | |
| 157 bool encode_space_as_plus, | |
| 158 bool unsafe_only) { | |
| 159 int needed_length = static_cast<int>(decoded.length()) * 3 + 1; | |
| 160 char* buf = STACK_ARRAY(char, needed_length); | |
| 161 InternalUrlEncode(decoded.c_str(), buf, needed_length, | |
| 162 encode_space_as_plus, unsafe_only); | |
| 163 return buf; | |
| 164 } | |
| 165 | |
| 166 std::string | |
| 167 UrlEncodeString(const std::string & decoded) { | |
| 168 return InternalUrlEncodeString(decoded, true, false); | |
| 169 } | |
| 170 | |
| 171 std::string | |
| 172 UrlEncodeStringWithoutEncodingSpaceAsPlus(const std::string & decoded) { | |
| 173 return InternalUrlEncodeString(decoded, false, false); | |
| 174 } | |
| 175 | |
| 176 std::string | |
| 177 UrlEncodeStringForOnlyUnsafeChars(const std::string & decoded) { | |
| 178 return InternalUrlEncodeString(decoded, false, true); | |
| 179 } | |
| 180 | |
| 181 } // namespace rtc | |
| OLD | NEW |