| 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 |