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 |