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 header parsing were borrowed from Firefox: | 5 // The rules for header parsing were borrowed from Firefox: |
6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo
nseHead.cpp | 6 // http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpRespo
nseHead.cpp |
7 // The rules for parsing content-types were also borrowed from Firefox: | 7 // The rules for parsing content-types were also borrowed from Firefox: |
8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 | 8 // http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834 |
9 | 9 |
10 #include "net/http/http_response_headers.h" | 10 #include "net/http/http_response_headers.h" |
(...skipping 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
199 blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); | 199 blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1); |
200 | 200 |
201 for (size_t i = 0; i < parsed_.size(); ++i) { | 201 for (size_t i = 0; i < parsed_.size(); ++i) { |
202 DCHECK(!parsed_[i].is_continuation()); | 202 DCHECK(!parsed_[i].is_continuation()); |
203 | 203 |
204 // Locate the start of the next header. | 204 // Locate the start of the next header. |
205 size_t k = i; | 205 size_t k = i; |
206 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} | 206 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} |
207 --k; | 207 --k; |
208 | 208 |
209 std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); | 209 std::string header_name = base::ToLowerASCII( |
210 base::StringToLowerASCII(&header_name); | 210 base::StringPiece(parsed_[i].name_begin, parsed_[i].name_end)); |
211 | |
212 if (filter_headers.find(header_name) == filter_headers.end()) { | 211 if (filter_headers.find(header_name) == filter_headers.end()) { |
213 // Make sure there is a null after the value. | 212 // Make sure there is a null after the value. |
214 blob.append(parsed_[i].name_begin, parsed_[k].value_end); | 213 blob.append(parsed_[i].name_begin, parsed_[k].value_end); |
215 blob.push_back('\0'); | 214 blob.push_back('\0'); |
216 } | 215 } |
217 | 216 |
218 i = k; | 217 i = k; |
219 } | 218 } |
220 blob.push_back('\0'); | 219 blob.push_back('\0'); |
221 | 220 |
(...skipping 19 matching lines...) Expand all Loading... |
241 | 240 |
242 DCHECK(!new_parsed[i].is_continuation()); | 241 DCHECK(!new_parsed[i].is_continuation()); |
243 | 242 |
244 // Locate the start of the next header. | 243 // Locate the start of the next header. |
245 size_t k = i; | 244 size_t k = i; |
246 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} | 245 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} |
247 --k; | 246 --k; |
248 | 247 |
249 base::StringPiece name(new_parsed[i].name_begin, new_parsed[i].name_end); | 248 base::StringPiece name(new_parsed[i].name_begin, new_parsed[i].name_end); |
250 if (ShouldUpdateHeader(name)) { | 249 if (ShouldUpdateHeader(name)) { |
251 std::string name_lower; | 250 std::string name_lower = base::ToLowerASCII(name); |
252 name.CopyToString(&name_lower); | |
253 base::StringToLowerASCII(&name_lower); | |
254 updated_headers.insert(name_lower); | 251 updated_headers.insert(name_lower); |
255 | 252 |
256 // Preserve this header line in the merged result, making sure there is | 253 // Preserve this header line in the merged result, making sure there is |
257 // a null after the value. | 254 // a null after the value. |
258 new_raw_headers.append(new_parsed[i].name_begin, new_parsed[k].value_end); | 255 new_raw_headers.append(new_parsed[i].name_begin, new_parsed[k].value_end); |
259 new_raw_headers.push_back('\0'); | 256 new_raw_headers.push_back('\0'); |
260 } | 257 } |
261 | 258 |
262 i = k; | 259 i = k; |
263 } | 260 } |
264 | 261 |
265 // Now, build the new raw headers. | 262 // Now, build the new raw headers. |
266 MergeWithHeaders(new_raw_headers, updated_headers); | 263 MergeWithHeaders(new_raw_headers, updated_headers); |
267 } | 264 } |
268 | 265 |
269 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, | 266 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, |
270 const HeaderSet& headers_to_remove) { | 267 const HeaderSet& headers_to_remove) { |
271 std::string new_raw_headers(raw_headers); | 268 std::string new_raw_headers(raw_headers); |
272 for (size_t i = 0; i < parsed_.size(); ++i) { | 269 for (size_t i = 0; i < parsed_.size(); ++i) { |
273 DCHECK(!parsed_[i].is_continuation()); | 270 DCHECK(!parsed_[i].is_continuation()); |
274 | 271 |
275 // Locate the start of the next header. | 272 // Locate the start of the next header. |
276 size_t k = i; | 273 size_t k = i; |
277 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} | 274 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} |
278 --k; | 275 --k; |
279 | 276 |
280 std::string name(parsed_[i].name_begin, parsed_[i].name_end); | 277 std::string name = base::ToLowerASCII( |
281 base::StringToLowerASCII(&name); | 278 base::StringPiece(parsed_[i].name_begin, parsed_[i].name_end)); |
282 if (headers_to_remove.find(name) == headers_to_remove.end()) { | 279 if (headers_to_remove.find(name) == headers_to_remove.end()) { |
283 // It's ok to preserve this header in the final result. | 280 // It's ok to preserve this header in the final result. |
284 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); | 281 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); |
285 new_raw_headers.push_back('\0'); | 282 new_raw_headers.push_back('\0'); |
286 } | 283 } |
287 | 284 |
288 i = k; | 285 i = k; |
289 } | 286 } |
290 new_raw_headers.push_back('\0'); | 287 new_raw_headers.push_back('\0'); |
291 | 288 |
292 // Make this object hold the new data. | 289 // Make this object hold the new data. |
293 raw_headers_.clear(); | 290 raw_headers_.clear(); |
294 parsed_.clear(); | 291 parsed_.clear(); |
295 Parse(new_raw_headers); | 292 Parse(new_raw_headers); |
296 } | 293 } |
297 | 294 |
298 void HttpResponseHeaders::RemoveHeader(const std::string& name) { | 295 void HttpResponseHeaders::RemoveHeader(const std::string& name) { |
299 // Copy up to the null byte. This just copies the status line. | 296 // Copy up to the null byte. This just copies the status line. |
300 std::string new_raw_headers(raw_headers_.c_str()); | 297 std::string new_raw_headers(raw_headers_.c_str()); |
301 new_raw_headers.push_back('\0'); | 298 new_raw_headers.push_back('\0'); |
302 | 299 |
303 std::string lowercase_name(name); | 300 std::string lowercase_name = base::ToLowerASCII(name); |
304 base::StringToLowerASCII(&lowercase_name); | |
305 HeaderSet to_remove; | 301 HeaderSet to_remove; |
306 to_remove.insert(lowercase_name); | 302 to_remove.insert(lowercase_name); |
307 MergeWithHeaders(new_raw_headers, to_remove); | 303 MergeWithHeaders(new_raw_headers, to_remove); |
308 } | 304 } |
309 | 305 |
310 void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, | 306 void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, |
311 const std::string& value) { | 307 const std::string& value) { |
312 std::string name_lowercase(name); | 308 std::string name_lowercase = base::ToLowerASCII(name); |
313 base::StringToLowerASCII(&name_lowercase); | |
314 | 309 |
315 std::string new_raw_headers(GetStatusLine()); | 310 std::string new_raw_headers(GetStatusLine()); |
316 new_raw_headers.push_back('\0'); | 311 new_raw_headers.push_back('\0'); |
317 | 312 |
318 new_raw_headers.reserve(raw_headers_.size()); | 313 new_raw_headers.reserve(raw_headers_.size()); |
319 | 314 |
320 void* iter = NULL; | 315 void* iter = NULL; |
321 std::string old_header_name; | 316 std::string old_header_name; |
322 std::string old_header_value; | 317 std::string old_header_value; |
323 while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) { | 318 while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) { |
324 std::string old_header_name_lowercase(name); | 319 std::string old_header_name_lowercase = base::ToLowerASCII(old_header_name); |
325 base::StringToLowerASCII(&old_header_name_lowercase); | |
326 | |
327 if (name_lowercase == old_header_name_lowercase && | 320 if (name_lowercase == old_header_name_lowercase && |
328 value == old_header_value) | 321 value == old_header_value) |
329 continue; | 322 continue; |
330 | 323 |
331 new_raw_headers.append(old_header_name); | 324 new_raw_headers.append(old_header_name); |
332 new_raw_headers.push_back(':'); | 325 new_raw_headers.push_back(':'); |
333 new_raw_headers.push_back(' '); | 326 new_raw_headers.push_back(' '); |
334 new_raw_headers.append(old_header_value); | 327 new_raw_headers.append(old_header_value); |
335 new_raw_headers.push_back('\0'); | 328 new_raw_headers.push_back('\0'); |
336 } | 329 } |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
466 typedef base::hash_map<std::string, size_t> HeadersMap; | 459 typedef base::hash_map<std::string, size_t> HeadersMap; |
467 HeadersMap headers_map; | 460 HeadersMap headers_map; |
468 HeadersMap::iterator iter = headers_map.end(); | 461 HeadersMap::iterator iter = headers_map.end(); |
469 | 462 |
470 std::vector<std::string> headers; | 463 std::vector<std::string> headers; |
471 | 464 |
472 for (size_t i = 0; i < parsed_.size(); ++i) { | 465 for (size_t i = 0; i < parsed_.size(); ++i) { |
473 DCHECK(!parsed_[i].is_continuation()); | 466 DCHECK(!parsed_[i].is_continuation()); |
474 | 467 |
475 std::string name(parsed_[i].name_begin, parsed_[i].name_end); | 468 std::string name(parsed_[i].name_begin, parsed_[i].name_end); |
476 std::string lower_name = base::StringToLowerASCII(name); | 469 std::string lower_name = base::ToLowerASCII(name); |
477 | 470 |
478 iter = headers_map.find(lower_name); | 471 iter = headers_map.find(lower_name); |
479 if (iter == headers_map.end()) { | 472 if (iter == headers_map.end()) { |
480 iter = headers_map.insert( | 473 iter = headers_map.insert( |
481 HeadersMap::value_type(lower_name, headers.size())).first; | 474 HeadersMap::value_type(lower_name, headers.size())).first; |
482 headers.push_back(name + ": "); | 475 headers.push_back(name + ": "); |
483 } else { | 476 } else { |
484 headers[iter->second].append(", "); | 477 headers[iter->second].append(", "); |
485 } | 478 } |
486 | 479 |
(...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
836 if (item_next != end) { | 829 if (item_next != end) { |
837 // Skip over comma for next position. | 830 // Skip over comma for next position. |
838 item_end = item_next; | 831 item_end = item_next; |
839 item_next++; | 832 item_next++; |
840 } | 833 } |
841 // trim off leading and trailing whitespace in this item. | 834 // trim off leading and trailing whitespace in this item. |
842 HttpUtil::TrimLWS(&item, &item_end); | 835 HttpUtil::TrimLWS(&item, &item_end); |
843 | 836 |
844 // assuming the header is not empty, lowercase and insert into set | 837 // assuming the header is not empty, lowercase and insert into set |
845 if (item_end > item) { | 838 if (item_end > item) { |
846 std::string name(&*item, item_end - item); | 839 result->insert( |
847 base::StringToLowerASCII(&name); | 840 base::ToLowerASCII(base::StringPiece(&*item, item_end - item))); |
848 result->insert(name); | |
849 } | 841 } |
850 | 842 |
851 // Continue to next item. | 843 // Continue to next item. |
852 item = item_next; | 844 item = item_next; |
853 } | 845 } |
854 } | 846 } |
855 } | 847 } |
856 | 848 |
857 void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { | 849 void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { |
858 for (size_t i = 0; i < arraysize(kHopByHopResponseHeaders); ++i) | 850 for (size_t i = 0; i < arraysize(kHopByHopResponseHeaders); ++i) |
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1441 return true; | 1433 return true; |
1442 } | 1434 } |
1443 | 1435 |
1444 bool HttpResponseHeaders::IsChunkEncoded() const { | 1436 bool HttpResponseHeaders::IsChunkEncoded() const { |
1445 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1437 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
1446 return GetHttpVersion() >= HttpVersion(1, 1) && | 1438 return GetHttpVersion() >= HttpVersion(1, 1) && |
1447 HasHeaderValue("Transfer-Encoding", "chunked"); | 1439 HasHeaderValue("Transfer-Encoding", "chunked"); |
1448 } | 1440 } |
1449 | 1441 |
1450 } // namespace net | 1442 } // namespace net |
OLD | NEW |