OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // The rules for parsing content-types were borrowed from Firefox: | 5 // The rules for parsing content-types were borrowed from Firefox: |
6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 | 6 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 |
7 | 7 |
8 #include "net/http/http_util.h" | 8 #include "net/http/http_util.h" |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
11 | 11 |
12 #include "base/basictypes.h" | 12 #include "base/basictypes.h" |
13 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
15 #include "base/strings/string_piece.h" | 15 #include "base/strings/string_piece.h" |
16 #include "base/strings/string_tokenizer.h" | 16 #include "base/strings/string_tokenizer.h" |
17 #include "base/strings/string_util.h" | 17 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 18 #include "base/strings/stringprintf.h" |
19 #include "base/time/time.h" | 19 #include "base/time/time.h" |
20 | 20 |
21 | |
22 namespace net { | 21 namespace net { |
23 | 22 |
24 // Helpers -------------------------------------------------------------------- | 23 // Helpers -------------------------------------------------------------------- |
25 | 24 |
26 // Returns the index of the closing quote of the string, if any. |start| points | 25 // Returns the index of the closing quote of the string, if any. |start| points |
27 // at the opening quote. | 26 // at the opening quote. |
28 static size_t FindStringEnd(const std::string& line, size_t start, char delim) { | 27 static size_t FindStringEnd(const std::string& line, size_t start, char delim) { |
29 DCHECK_LT(start, line.length()); | 28 DCHECK_LT(start, line.length()); |
30 DCHECK_EQ(line[start], delim); | 29 DCHECK_EQ(line[start], delim); |
31 DCHECK((delim == '"') || (delim == '\'')); | 30 DCHECK((delim == '"') || (delim == '\'')); |
32 | 31 |
33 const char set[] = { delim, '\\', '\0' }; | 32 const char set[] = {delim, '\\', '\0'}; |
34 for (size_t end = line.find_first_of(set, start + 1); | 33 for (size_t end = line.find_first_of(set, start + 1); |
35 end != std::string::npos; end = line.find_first_of(set, end + 2)) { | 34 end != std::string::npos; |
| 35 end = line.find_first_of(set, end + 2)) { |
36 if (line[end] != '\\') | 36 if (line[end] != '\\') |
37 return end; | 37 return end; |
38 } | 38 } |
39 return line.length(); | 39 return line.length(); |
40 } | 40 } |
41 | 41 |
42 | |
43 // HttpUtil ------------------------------------------------------------------- | 42 // HttpUtil ------------------------------------------------------------------- |
44 | 43 |
45 // static | 44 // static |
46 size_t HttpUtil::FindDelimiter(const std::string& line, | 45 size_t HttpUtil::FindDelimiter(const std::string& line, |
47 size_t search_start, | 46 size_t search_start, |
48 char delimiter) { | 47 char delimiter) { |
49 do { | 48 do { |
50 // search_start points to the spot from which we should start looking | 49 // search_start points to the spot from which we should start looking |
51 // for the delimiter. | 50 // for the delimiter. |
52 const char delim_str[] = { delimiter, '"', '\'', '\0' }; | 51 const char delim_str[] = {delimiter, '"', '\'', '\0'}; |
53 size_t cur_delim_pos = line.find_first_of(delim_str, search_start); | 52 size_t cur_delim_pos = line.find_first_of(delim_str, search_start); |
54 if (cur_delim_pos == std::string::npos) | 53 if (cur_delim_pos == std::string::npos) |
55 return line.length(); | 54 return line.length(); |
56 | 55 |
57 char ch = line[cur_delim_pos]; | 56 char ch = line[cur_delim_pos]; |
58 if (ch == delimiter) { | 57 if (ch == delimiter) { |
59 // Found delimiter | 58 // Found delimiter |
60 return cur_delim_pos; | 59 return cur_delim_pos; |
61 } | 60 } |
62 | 61 |
(...skipping 30 matching lines...) Expand all Loading... |
93 if (type_end == std::string::npos) | 92 if (type_end == std::string::npos) |
94 type_end = content_type_str.length(); | 93 type_end = content_type_str.length(); |
95 | 94 |
96 size_t charset_val = 0; | 95 size_t charset_val = 0; |
97 size_t charset_end = 0; | 96 size_t charset_end = 0; |
98 bool type_has_charset = false; | 97 bool type_has_charset = false; |
99 | 98 |
100 // Iterate over parameters | 99 // Iterate over parameters |
101 size_t param_start = content_type_str.find_first_of(';', type_end); | 100 size_t param_start = content_type_str.find_first_of(';', type_end); |
102 if (param_start != std::string::npos) { | 101 if (param_start != std::string::npos) { |
103 base::StringTokenizer tokenizer(begin + param_start, content_type_str.end(), | 102 base::StringTokenizer tokenizer( |
104 ";"); | 103 begin + param_start, content_type_str.end(), ";"); |
105 tokenizer.set_quote_chars("\""); | 104 tokenizer.set_quote_chars("\""); |
106 while (tokenizer.GetNext()) { | 105 while (tokenizer.GetNext()) { |
107 std::string::const_iterator equals_sign = | 106 std::string::const_iterator equals_sign = |
108 std::find(tokenizer.token_begin(), tokenizer.token_end(), '='); | 107 std::find(tokenizer.token_begin(), tokenizer.token_end(), '='); |
109 if (equals_sign == tokenizer.token_end()) | 108 if (equals_sign == tokenizer.token_end()) |
110 continue; | 109 continue; |
111 | 110 |
112 std::string::const_iterator param_name_begin = tokenizer.token_begin(); | 111 std::string::const_iterator param_name_begin = tokenizer.token_begin(); |
113 std::string::const_iterator param_name_end = equals_sign; | 112 std::string::const_iterator param_name_end = equals_sign; |
114 TrimLWS(¶m_name_begin, ¶m_name_end); | 113 TrimLWS(¶m_name_begin, ¶m_name_end); |
115 | 114 |
116 std::string::const_iterator param_value_begin = equals_sign + 1; | 115 std::string::const_iterator param_value_begin = equals_sign + 1; |
117 std::string::const_iterator param_value_end = tokenizer.token_end(); | 116 std::string::const_iterator param_value_end = tokenizer.token_end(); |
118 DCHECK(param_value_begin <= tokenizer.token_end()); | 117 DCHECK(param_value_begin <= tokenizer.token_end()); |
119 TrimLWS(¶m_value_begin, ¶m_value_end); | 118 TrimLWS(¶m_value_begin, ¶m_value_end); |
120 | 119 |
121 if (LowerCaseEqualsASCII(param_name_begin, param_name_end, "charset")) { | 120 if (LowerCaseEqualsASCII(param_name_begin, param_name_end, "charset")) { |
122 // TODO(abarth): Refactor this function to consistently use iterators. | 121 // TODO(abarth): Refactor this function to consistently use iterators. |
123 charset_val = param_value_begin - begin; | 122 charset_val = param_value_begin - begin; |
124 charset_end = param_value_end - begin; | 123 charset_end = param_value_end - begin; |
125 type_has_charset = true; | 124 type_has_charset = true; |
126 } else if (LowerCaseEqualsASCII(param_name_begin, param_name_end, | 125 } else if (LowerCaseEqualsASCII( |
127 "boundary")) { | 126 param_name_begin, param_name_end, "boundary")) { |
128 if (boundary) | 127 if (boundary) |
129 boundary->assign(param_value_begin, param_value_end); | 128 boundary->assign(param_value_begin, param_value_end); |
130 } | 129 } |
131 } | 130 } |
132 } | 131 } |
133 | 132 |
134 if (type_has_charset) { | 133 if (type_has_charset) { |
135 // Trim leading and trailing whitespace from charset_val. We include | 134 // Trim leading and trailing whitespace from charset_val. We include |
136 // '(' in the trailing trim set to catch media-type comments, which are | 135 // '(' in the trailing trim set to catch media-type comments, which are |
137 // not at all standard, but may occur in rare cases. | 136 // not at all standard, but may occur in rare cases. |
138 charset_val = content_type_str.find_first_not_of(HTTP_LWS, charset_val); | 137 charset_val = content_type_str.find_first_not_of(HTTP_LWS, charset_val); |
139 charset_val = std::min(charset_val, charset_end); | 138 charset_val = std::min(charset_val, charset_end); |
140 char first_char = content_type_str[charset_val]; | 139 char first_char = content_type_str[charset_val]; |
141 if (first_char == '"' || first_char == '\'') { | 140 if (first_char == '"' || first_char == '\'') { |
142 charset_end = FindStringEnd(content_type_str, charset_val, first_char); | 141 charset_end = FindStringEnd(content_type_str, charset_val, first_char); |
143 ++charset_val; | 142 ++charset_val; |
144 DCHECK(charset_end >= charset_val); | 143 DCHECK(charset_end >= charset_val); |
145 } else { | 144 } else { |
146 charset_end = std::min(content_type_str.find_first_of(HTTP_LWS ";(", | 145 charset_end = |
147 charset_val), | 146 std::min(content_type_str.find_first_of(HTTP_LWS ";(", charset_val), |
148 charset_end); | 147 charset_end); |
149 } | 148 } |
150 } | 149 } |
151 | 150 |
152 // if the server sent "*/*", it is meaningless, so do not store it. | 151 // if the server sent "*/*", it is meaningless, so do not store it. |
153 // also, if type_val is the same as mime_type, then just update the | 152 // also, if type_val is the same as mime_type, then just update the |
154 // charset. however, if charset is empty and mime_type hasn't | 153 // charset. however, if charset is empty and mime_type hasn't |
155 // changed, then don't wipe-out an existing charset. We | 154 // changed, then don't wipe-out an existing charset. We |
156 // also want to reject a mime-type if it does not include a slash. | 155 // also want to reject a mime-type if it does not include a slash. |
157 // some servers give junk after the charset parameter, which may | 156 // some servers give junk after the charset parameter, which may |
158 // include a comma, so this check makes us a bit more tolerant. | 157 // include a comma, so this check makes us a bit more tolerant. |
159 if (content_type_str.length() != 0 && | 158 if (content_type_str.length() != 0 && content_type_str != "*/*" && |
160 content_type_str != "*/*" && | |
161 content_type_str.find_first_of('/') != std::string::npos) { | 159 content_type_str.find_first_of('/') != std::string::npos) { |
162 // Common case here is that mime_type is empty | 160 // Common case here is that mime_type is empty |
163 bool eq = !mime_type->empty() && LowerCaseEqualsASCII(begin + type_val, | 161 bool eq = !mime_type->empty() && |
164 begin + type_end, | 162 LowerCaseEqualsASCII( |
165 mime_type->data()); | 163 begin + type_val, begin + type_end, mime_type->data()); |
166 if (!eq) { | 164 if (!eq) { |
167 mime_type->assign(begin + type_val, begin + type_end); | 165 mime_type->assign(begin + type_val, begin + type_end); |
168 StringToLowerASCII(mime_type); | 166 StringToLowerASCII(mime_type); |
169 } | 167 } |
170 if ((!eq && *had_charset) || type_has_charset) { | 168 if ((!eq && *had_charset) || type_has_charset) { |
171 *had_charset = true; | 169 *had_charset = true; |
172 charset->assign(begin + charset_val, begin + charset_end); | 170 charset->assign(begin + charset_val, begin + charset_end); |
173 StringToLowerASCII(charset); | 171 StringToLowerASCII(charset); |
174 } | 172 } |
175 } | 173 } |
(...skipping 29 matching lines...) Expand all Loading... |
205 | 203 |
206 // static | 204 // static |
207 bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier, | 205 bool HttpUtil::ParseRangeHeader(const std::string& ranges_specifier, |
208 std::vector<HttpByteRange>* ranges) { | 206 std::vector<HttpByteRange>* ranges) { |
209 size_t equal_char_offset = ranges_specifier.find('='); | 207 size_t equal_char_offset = ranges_specifier.find('='); |
210 if (equal_char_offset == std::string::npos) | 208 if (equal_char_offset == std::string::npos) |
211 return false; | 209 return false; |
212 | 210 |
213 // Try to extract bytes-unit part. | 211 // Try to extract bytes-unit part. |
214 std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); | 212 std::string::const_iterator bytes_unit_begin = ranges_specifier.begin(); |
215 std::string::const_iterator bytes_unit_end = bytes_unit_begin + | 213 std::string::const_iterator bytes_unit_end = |
216 equal_char_offset; | 214 bytes_unit_begin + equal_char_offset; |
217 std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; | 215 std::string::const_iterator byte_range_set_begin = bytes_unit_end + 1; |
218 std::string::const_iterator byte_range_set_end = ranges_specifier.end(); | 216 std::string::const_iterator byte_range_set_end = ranges_specifier.end(); |
219 | 217 |
220 TrimLWS(&bytes_unit_begin, &bytes_unit_end); | 218 TrimLWS(&bytes_unit_begin, &bytes_unit_end); |
221 // "bytes" unit identifier is not found. | 219 // "bytes" unit identifier is not found. |
222 if (!LowerCaseEqualsASCII(bytes_unit_begin, bytes_unit_end, "bytes")) | 220 if (!LowerCaseEqualsASCII(bytes_unit_begin, bytes_unit_end, "bytes")) |
223 return false; | 221 return false; |
224 | 222 |
225 ValuesIterator byte_range_set_iterator(byte_range_set_begin, | 223 ValuesIterator byte_range_set_iterator( |
226 byte_range_set_end, ','); | 224 byte_range_set_begin, byte_range_set_end, ','); |
227 while (byte_range_set_iterator.GetNext()) { | 225 while (byte_range_set_iterator.GetNext()) { |
228 size_t minus_char_offset = byte_range_set_iterator.value().find('-'); | 226 size_t minus_char_offset = byte_range_set_iterator.value().find('-'); |
229 // If '-' character is not found, reports failure. | 227 // If '-' character is not found, reports failure. |
230 if (minus_char_offset == std::string::npos) | 228 if (minus_char_offset == std::string::npos) |
231 return false; | 229 return false; |
232 | 230 |
233 std::string::const_iterator first_byte_pos_begin = | 231 std::string::const_iterator first_byte_pos_begin = |
234 byte_range_set_iterator.value_begin(); | 232 byte_range_set_iterator.value_begin(); |
235 std::string::const_iterator first_byte_pos_end = | 233 std::string::const_iterator first_byte_pos_end = |
236 first_byte_pos_begin + minus_char_offset; | 234 first_byte_pos_begin + minus_char_offset; |
237 TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); | 235 TrimLWS(&first_byte_pos_begin, &first_byte_pos_end); |
238 std::string first_byte_pos(first_byte_pos_begin, first_byte_pos_end); | 236 std::string first_byte_pos(first_byte_pos_begin, first_byte_pos_end); |
239 | 237 |
240 HttpByteRange range; | 238 HttpByteRange range; |
241 // Try to obtain first-byte-pos. | 239 // Try to obtain first-byte-pos. |
242 if (!first_byte_pos.empty()) { | 240 if (!first_byte_pos.empty()) { |
243 int64 first_byte_position = -1; | 241 int64 first_byte_position = -1; |
244 if (!base::StringToInt64(first_byte_pos, &first_byte_position)) | 242 if (!base::StringToInt64(first_byte_pos, &first_byte_position)) |
245 return false; | 243 return false; |
246 range.set_first_byte_position(first_byte_position); | 244 range.set_first_byte_position(first_byte_position); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 return false; | 293 return false; |
296 | 294 |
297 return true; | 295 return true; |
298 } | 296 } |
299 | 297 |
300 namespace { | 298 namespace { |
301 // A header string containing any of the following fields will cause | 299 // A header string containing any of the following fields will cause |
302 // an error. The list comes from the XMLHttpRequest standard. | 300 // an error. The list comes from the XMLHttpRequest standard. |
303 // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method | 301 // http://www.w3.org/TR/XMLHttpRequest/#the-setrequestheader-method |
304 const char* const kForbiddenHeaderFields[] = { | 302 const char* const kForbiddenHeaderFields[] = { |
305 "accept-charset", | 303 "accept-charset", "accept-encoding", |
306 "accept-encoding", | 304 "access-control-request-headers", "access-control-request-method", |
307 "access-control-request-headers", | 305 "connection", "content-length", |
308 "access-control-request-method", | 306 "cookie", "cookie2", |
309 "connection", | 307 "content-transfer-encoding", "date", |
310 "content-length", | 308 "expect", "host", |
311 "cookie", | 309 "keep-alive", "origin", |
312 "cookie2", | 310 "referer", "te", |
313 "content-transfer-encoding", | 311 "trailer", "transfer-encoding", |
314 "date", | 312 "upgrade", "user-agent", |
315 "expect", | 313 "via", |
316 "host", | |
317 "keep-alive", | |
318 "origin", | |
319 "referer", | |
320 "te", | |
321 "trailer", | |
322 "transfer-encoding", | |
323 "upgrade", | |
324 "user-agent", | |
325 "via", | |
326 }; | 314 }; |
327 } // anonymous namespace | 315 } // anonymous namespace |
328 | 316 |
329 // static | 317 // static |
330 bool HttpUtil::IsSafeHeader(const std::string& name) { | 318 bool HttpUtil::IsSafeHeader(const std::string& name) { |
331 std::string lower_name(StringToLowerASCII(name)); | 319 std::string lower_name(StringToLowerASCII(name)); |
332 if (StartsWithASCII(lower_name, "proxy-", true) || | 320 if (StartsWithASCII(lower_name, "proxy-", true) || |
333 StartsWithASCII(lower_name, "sec-", true)) | 321 StartsWithASCII(lower_name, "sec-", true)) |
334 return false; | 322 return false; |
335 for (size_t i = 0; i < arraysize(kForbiddenHeaderFields); ++i) { | 323 for (size_t i = 0; i < arraysize(kForbiddenHeaderFields); ++i) { |
336 if (lower_name == kForbiddenHeaderFields[i]) | 324 if (lower_name == kForbiddenHeaderFields[i]) |
337 return false; | 325 return false; |
338 } | 326 } |
339 return true; | 327 return true; |
340 } | 328 } |
341 | 329 |
342 // static | 330 // static |
343 std::string HttpUtil::StripHeaders(const std::string& headers, | 331 std::string HttpUtil::StripHeaders(const std::string& headers, |
344 const char* const headers_to_remove[], | 332 const char* const headers_to_remove[], |
345 size_t headers_to_remove_len) { | 333 size_t headers_to_remove_len) { |
346 std::string stripped_headers; | 334 std::string stripped_headers; |
347 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); | 335 net::HttpUtil::HeadersIterator it(headers.begin(), headers.end(), "\r\n"); |
348 | 336 |
349 while (it.GetNext()) { | 337 while (it.GetNext()) { |
350 bool should_remove = false; | 338 bool should_remove = false; |
351 for (size_t i = 0; i < headers_to_remove_len; ++i) { | 339 for (size_t i = 0; i < headers_to_remove_len; ++i) { |
352 if (LowerCaseEqualsASCII(it.name_begin(), it.name_end(), | 340 if (LowerCaseEqualsASCII( |
353 headers_to_remove[i])) { | 341 it.name_begin(), it.name_end(), headers_to_remove[i])) { |
354 should_remove = true; | 342 should_remove = true; |
355 break; | 343 break; |
356 } | 344 } |
357 } | 345 } |
358 if (!should_remove) { | 346 if (!should_remove) { |
359 // Assume that name and values are on the same line. | 347 // Assume that name and values are on the same line. |
360 stripped_headers.append(it.name_begin(), it.values_end()); | 348 stripped_headers.append(it.name_begin(), it.values_end()); |
361 stripped_headers.append("\r\n"); | 349 stripped_headers.append("\r\n"); |
362 } | 350 } |
363 } | 351 } |
364 return stripped_headers; | 352 return stripped_headers; |
365 } | 353 } |
366 | 354 |
367 // static | 355 // static |
368 bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin, | 356 bool HttpUtil::IsNonCoalescingHeader(std::string::const_iterator name_begin, |
369 std::string::const_iterator name_end) { | 357 std::string::const_iterator name_end) { |
370 // NOTE: "set-cookie2" headers do not support expires attributes, so we don't | 358 // NOTE: "set-cookie2" headers do not support expires attributes, so we don't |
371 // have to list them here. | 359 // have to list them here. |
372 const char* kNonCoalescingHeaders[] = { | 360 const char* kNonCoalescingHeaders[] = { |
373 "date", | 361 "date", "expires", "last-modified", |
374 "expires", | 362 "location", // See bug 1050541 for details |
375 "last-modified", | 363 "retry-after", "set-cookie", |
376 "location", // See bug 1050541 for details | 364 // The format of auth-challenges mixes both space separated tokens and |
377 "retry-after", | 365 // comma separated properties, so coalescing on comma won't work. |
378 "set-cookie", | 366 "www-authenticate", "proxy-authenticate", |
379 // The format of auth-challenges mixes both space separated tokens and | 367 // STS specifies that UAs must not process any STS headers after the first |
380 // comma separated properties, so coalescing on comma won't work. | 368 // one. |
381 "www-authenticate", | 369 "strict-transport-security"}; |
382 "proxy-authenticate", | |
383 // STS specifies that UAs must not process any STS headers after the first | |
384 // one. | |
385 "strict-transport-security" | |
386 }; | |
387 for (size_t i = 0; i < arraysize(kNonCoalescingHeaders); ++i) { | 370 for (size_t i = 0; i < arraysize(kNonCoalescingHeaders); ++i) { |
388 if (LowerCaseEqualsASCII(name_begin, name_end, kNonCoalescingHeaders[i])) | 371 if (LowerCaseEqualsASCII(name_begin, name_end, kNonCoalescingHeaders[i])) |
389 return true; | 372 return true; |
390 } | 373 } |
391 return false; | 374 return false; |
392 } | 375 } |
393 | 376 |
394 bool HttpUtil::IsLWS(char c) { | 377 bool HttpUtil::IsLWS(char c) { |
395 return strchr(HTTP_LWS, c) != NULL; | 378 return strchr(HTTP_LWS, c) != NULL; |
396 } | 379 } |
(...skipping 15 matching lines...) Expand all Loading... |
412 return c == '"' || c == '\''; | 395 return c == '"' || c == '\''; |
413 } | 396 } |
414 | 397 |
415 // See RFC 2616 Sec 2.2 for the definition of |token|. | 398 // See RFC 2616 Sec 2.2 for the definition of |token|. |
416 bool HttpUtil::IsToken(std::string::const_iterator begin, | 399 bool HttpUtil::IsToken(std::string::const_iterator begin, |
417 std::string::const_iterator end) { | 400 std::string::const_iterator end) { |
418 if (begin == end) | 401 if (begin == end) |
419 return false; | 402 return false; |
420 for (std::string::const_iterator iter = begin; iter != end; ++iter) { | 403 for (std::string::const_iterator iter = begin; iter != end; ++iter) { |
421 unsigned char c = *iter; | 404 unsigned char c = *iter; |
422 if (c >= 0x80 || c <= 0x1F || c == 0x7F || | 405 if (c >= 0x80 || c <= 0x1F || c == 0x7F || c == '(' || c == ')' || |
423 c == '(' || c == ')' || c == '<' || c == '>' || c == '@' || | 406 c == '<' || c == '>' || c == '@' || c == ',' || c == ';' || c == ':' || |
424 c == ',' || c == ';' || c == ':' || c == '\\' || c == '"' || | 407 c == '\\' || c == '"' || c == '/' || c == '[' || c == ']' || c == '?' || |
425 c == '/' || c == '[' || c == ']' || c == '?' || c == '=' || | 408 c == '=' || c == '{' || c == '}' || c == ' ' || c == '\t') |
426 c == '{' || c == '}' || c == ' ' || c == '\t') | |
427 return false; | 409 return false; |
428 } | 410 } |
429 return true; | 411 return true; |
430 } | 412 } |
431 | 413 |
432 std::string HttpUtil::Unquote(std::string::const_iterator begin, | 414 std::string HttpUtil::Unquote(std::string::const_iterator begin, |
433 std::string::const_iterator end) { | 415 std::string::const_iterator end) { |
434 // Empty string | 416 // Empty string |
435 if (begin == end) | 417 if (begin == end) |
436 return std::string(); | 418 return std::string(); |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
653 unsigned int qvalue10 = 10; | 635 unsigned int qvalue10 = 10; |
654 base::StringTokenizer t(raw_language_list, ","); | 636 base::StringTokenizer t(raw_language_list, ","); |
655 std::string lang_list_with_q; | 637 std::string lang_list_with_q; |
656 while (t.GetNext()) { | 638 while (t.GetNext()) { |
657 std::string language = t.token(); | 639 std::string language = t.token(); |
658 if (qvalue10 == 10) { | 640 if (qvalue10 == 10) { |
659 // q=1.0 is implicit. | 641 // q=1.0 is implicit. |
660 lang_list_with_q = language; | 642 lang_list_with_q = language; |
661 } else { | 643 } else { |
662 DCHECK_LT(qvalue10, 10U); | 644 DCHECK_LT(qvalue10, 10U); |
663 base::StringAppendF(&lang_list_with_q, ",%s;q=0.%d", language.c_str(), | 645 base::StringAppendF( |
664 qvalue10); | 646 &lang_list_with_q, ",%s;q=0.%d", language.c_str(), qvalue10); |
665 } | 647 } |
666 // It does not make sense to have 'q=0'. | 648 // It does not make sense to have 'q=0'. |
667 if (qvalue10 > kQvalueDecrement10) | 649 if (qvalue10 > kQvalueDecrement10) |
668 qvalue10 -= kQvalueDecrement10; | 650 qvalue10 -= kQvalueDecrement10; |
669 } | 651 } |
670 return lang_list_with_q; | 652 return lang_list_with_q; |
671 } | 653 } |
672 | 654 |
673 void HttpUtil::AppendHeaderIfMissing(const char* header_name, | 655 void HttpUtil::AppendHeaderIfMissing(const char* header_name, |
674 const std::string& header_value, | 656 const std::string& header_value, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 // ones are not sent in practice, to reduce upload size & memory use. | 698 // ones are not sent in practice, to reduce upload size & memory use. |
717 | 699 |
718 enum { | 700 enum { |
719 HISTOGRAM_MIN_HTTP_STATUS_CODE = 100, | 701 HISTOGRAM_MIN_HTTP_STATUS_CODE = 100, |
720 HISTOGRAM_MAX_HTTP_STATUS_CODE = 599, | 702 HISTOGRAM_MAX_HTTP_STATUS_CODE = 599, |
721 }; | 703 }; |
722 | 704 |
723 // static | 705 // static |
724 std::vector<int> HttpUtil::GetStatusCodesForHistogram() { | 706 std::vector<int> HttpUtil::GetStatusCodesForHistogram() { |
725 std::vector<int> codes; | 707 std::vector<int> codes; |
726 codes.reserve( | 708 codes.reserve(HISTOGRAM_MAX_HTTP_STATUS_CODE - |
727 HISTOGRAM_MAX_HTTP_STATUS_CODE - HISTOGRAM_MIN_HTTP_STATUS_CODE + 2); | 709 HISTOGRAM_MIN_HTTP_STATUS_CODE + 2); |
728 codes.push_back(0); | 710 codes.push_back(0); |
729 for (int i = HISTOGRAM_MIN_HTTP_STATUS_CODE; | 711 for (int i = HISTOGRAM_MIN_HTTP_STATUS_CODE; |
730 i <= HISTOGRAM_MAX_HTTP_STATUS_CODE; ++i) | 712 i <= HISTOGRAM_MAX_HTTP_STATUS_CODE; |
| 713 ++i) |
731 codes.push_back(i); | 714 codes.push_back(i); |
732 return codes; | 715 return codes; |
733 } | 716 } |
734 | 717 |
735 // static | 718 // static |
736 int HttpUtil::MapStatusCodeForHistogram(int code) { | 719 int HttpUtil::MapStatusCodeForHistogram(int code) { |
737 if (HISTOGRAM_MIN_HTTP_STATUS_CODE <= code && | 720 if (HISTOGRAM_MIN_HTTP_STATUS_CODE <= code && |
738 code <= HISTOGRAM_MAX_HTTP_STATUS_CODE) | 721 code <= HISTOGRAM_MAX_HTTP_STATUS_CODE) |
739 return code; | 722 return code; |
740 return 0; | 723 return 0; |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
834 char delimiter) | 817 char delimiter) |
835 : props_(begin, end, delimiter), | 818 : props_(begin, end, delimiter), |
836 valid_(true), | 819 valid_(true), |
837 name_begin_(end), | 820 name_begin_(end), |
838 name_end_(end), | 821 name_end_(end), |
839 value_begin_(end), | 822 value_begin_(end), |
840 value_end_(end), | 823 value_end_(end), |
841 value_is_quoted_(false) { | 824 value_is_quoted_(false) { |
842 } | 825 } |
843 | 826 |
844 HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() {} | 827 HttpUtil::NameValuePairsIterator::~NameValuePairsIterator() { |
| 828 } |
845 | 829 |
846 // We expect properties to be formatted as one of: | 830 // We expect properties to be formatted as one of: |
847 // name="value" | 831 // name="value" |
848 // name='value' | 832 // name='value' |
849 // name='\'value\'' | 833 // name='\'value\'' |
850 // name=value | 834 // name=value |
851 // name = value | 835 // name = value |
852 // name= | 836 // name= |
853 // Due to buggy implementations found in some embedded devices, we also | 837 // Due to buggy implementations found in some embedded devices, we also |
854 // accept values with missing close quotemark (http://crbug.com/39836): | 838 // accept values with missing close quotemark (http://crbug.com/39836): |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 value_is_quoted_ = true; | 882 value_is_quoted_ = true; |
899 // Do not store iterators into this. See declaration of unquoted_value_. | 883 // Do not store iterators into this. See declaration of unquoted_value_. |
900 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_); | 884 unquoted_value_ = HttpUtil::Unquote(value_begin_, value_end_); |
901 } | 885 } |
902 } | 886 } |
903 | 887 |
904 return true; | 888 return true; |
905 } | 889 } |
906 | 890 |
907 } // namespace net | 891 } // namespace net |
OLD | NEW |