| 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 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 | 201 |
| 202 for (size_t i = 0; i < parsed_.size(); ++i) { | 202 for (size_t i = 0; i < parsed_.size(); ++i) { |
| 203 DCHECK(!parsed_[i].is_continuation()); | 203 DCHECK(!parsed_[i].is_continuation()); |
| 204 | 204 |
| 205 // Locate the start of the next header. | 205 // Locate the start of the next header. |
| 206 size_t k = i; | 206 size_t k = i; |
| 207 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} | 207 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} |
| 208 --k; | 208 --k; |
| 209 | 209 |
| 210 std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); | 210 std::string header_name(parsed_[i].name_begin, parsed_[i].name_end); |
| 211 StringToLowerASCII(&header_name); | 211 base::StringToLowerASCII(&header_name); |
| 212 | 212 |
| 213 if (filter_headers.find(header_name) == filter_headers.end()) { | 213 if (filter_headers.find(header_name) == filter_headers.end()) { |
| 214 // Make sure there is a null after the value. | 214 // Make sure there is a null after the value. |
| 215 blob.append(parsed_[i].name_begin, parsed_[k].value_end); | 215 blob.append(parsed_[i].name_begin, parsed_[k].value_end); |
| 216 blob.push_back('\0'); | 216 blob.push_back('\0'); |
| 217 } | 217 } |
| 218 | 218 |
| 219 i = k; | 219 i = k; |
| 220 } | 220 } |
| 221 blob.push_back('\0'); | 221 blob.push_back('\0'); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 244 | 244 |
| 245 // Locate the start of the next header. | 245 // Locate the start of the next header. |
| 246 size_t k = i; | 246 size_t k = i; |
| 247 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} | 247 while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {} |
| 248 --k; | 248 --k; |
| 249 | 249 |
| 250 const std::string::const_iterator& name_begin = new_parsed[i].name_begin; | 250 const std::string::const_iterator& name_begin = new_parsed[i].name_begin; |
| 251 const std::string::const_iterator& name_end = new_parsed[i].name_end; | 251 const std::string::const_iterator& name_end = new_parsed[i].name_end; |
| 252 if (ShouldUpdateHeader(name_begin, name_end)) { | 252 if (ShouldUpdateHeader(name_begin, name_end)) { |
| 253 std::string name(name_begin, name_end); | 253 std::string name(name_begin, name_end); |
| 254 StringToLowerASCII(&name); | 254 base::StringToLowerASCII(&name); |
| 255 updated_headers.insert(name); | 255 updated_headers.insert(name); |
| 256 | 256 |
| 257 // Preserve this header line in the merged result, making sure there is | 257 // Preserve this header line in the merged result, making sure there is |
| 258 // a null after the value. | 258 // a null after the value. |
| 259 new_raw_headers.append(name_begin, new_parsed[k].value_end); | 259 new_raw_headers.append(name_begin, new_parsed[k].value_end); |
| 260 new_raw_headers.push_back('\0'); | 260 new_raw_headers.push_back('\0'); |
| 261 } | 261 } |
| 262 | 262 |
| 263 i = k; | 263 i = k; |
| 264 } | 264 } |
| 265 | 265 |
| 266 // Now, build the new raw headers. | 266 // Now, build the new raw headers. |
| 267 MergeWithHeaders(new_raw_headers, updated_headers); | 267 MergeWithHeaders(new_raw_headers, updated_headers); |
| 268 } | 268 } |
| 269 | 269 |
| 270 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, | 270 void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers, |
| 271 const HeaderSet& headers_to_remove) { | 271 const HeaderSet& headers_to_remove) { |
| 272 std::string new_raw_headers(raw_headers); | 272 std::string new_raw_headers(raw_headers); |
| 273 for (size_t i = 0; i < parsed_.size(); ++i) { | 273 for (size_t i = 0; i < parsed_.size(); ++i) { |
| 274 DCHECK(!parsed_[i].is_continuation()); | 274 DCHECK(!parsed_[i].is_continuation()); |
| 275 | 275 |
| 276 // Locate the start of the next header. | 276 // Locate the start of the next header. |
| 277 size_t k = i; | 277 size_t k = i; |
| 278 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} | 278 while (++k < parsed_.size() && parsed_[k].is_continuation()) {} |
| 279 --k; | 279 --k; |
| 280 | 280 |
| 281 std::string name(parsed_[i].name_begin, parsed_[i].name_end); | 281 std::string name(parsed_[i].name_begin, parsed_[i].name_end); |
| 282 StringToLowerASCII(&name); | 282 base::StringToLowerASCII(&name); |
| 283 if (headers_to_remove.find(name) == headers_to_remove.end()) { | 283 if (headers_to_remove.find(name) == headers_to_remove.end()) { |
| 284 // It's ok to preserve this header in the final result. | 284 // It's ok to preserve this header in the final result. |
| 285 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); | 285 new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end); |
| 286 new_raw_headers.push_back('\0'); | 286 new_raw_headers.push_back('\0'); |
| 287 } | 287 } |
| 288 | 288 |
| 289 i = k; | 289 i = k; |
| 290 } | 290 } |
| 291 new_raw_headers.push_back('\0'); | 291 new_raw_headers.push_back('\0'); |
| 292 | 292 |
| 293 // Make this object hold the new data. | 293 // Make this object hold the new data. |
| 294 raw_headers_.clear(); | 294 raw_headers_.clear(); |
| 295 parsed_.clear(); | 295 parsed_.clear(); |
| 296 Parse(new_raw_headers); | 296 Parse(new_raw_headers); |
| 297 } | 297 } |
| 298 | 298 |
| 299 void HttpResponseHeaders::RemoveHeader(const std::string& name) { | 299 void HttpResponseHeaders::RemoveHeader(const std::string& name) { |
| 300 // Copy up to the null byte. This just copies the status line. | 300 // Copy up to the null byte. This just copies the status line. |
| 301 std::string new_raw_headers(raw_headers_.c_str()); | 301 std::string new_raw_headers(raw_headers_.c_str()); |
| 302 new_raw_headers.push_back('\0'); | 302 new_raw_headers.push_back('\0'); |
| 303 | 303 |
| 304 std::string lowercase_name(name); | 304 std::string lowercase_name(name); |
| 305 StringToLowerASCII(&lowercase_name); | 305 base::StringToLowerASCII(&lowercase_name); |
| 306 HeaderSet to_remove; | 306 HeaderSet to_remove; |
| 307 to_remove.insert(lowercase_name); | 307 to_remove.insert(lowercase_name); |
| 308 MergeWithHeaders(new_raw_headers, to_remove); | 308 MergeWithHeaders(new_raw_headers, to_remove); |
| 309 } | 309 } |
| 310 | 310 |
| 311 void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, | 311 void HttpResponseHeaders::RemoveHeaderLine(const std::string& name, |
| 312 const std::string& value) { | 312 const std::string& value) { |
| 313 std::string name_lowercase(name); | 313 std::string name_lowercase(name); |
| 314 StringToLowerASCII(&name_lowercase); | 314 base::StringToLowerASCII(&name_lowercase); |
| 315 | 315 |
| 316 std::string new_raw_headers(GetStatusLine()); | 316 std::string new_raw_headers(GetStatusLine()); |
| 317 new_raw_headers.push_back('\0'); | 317 new_raw_headers.push_back('\0'); |
| 318 | 318 |
| 319 new_raw_headers.reserve(raw_headers_.size()); | 319 new_raw_headers.reserve(raw_headers_.size()); |
| 320 | 320 |
| 321 void* iter = NULL; | 321 void* iter = NULL; |
| 322 std::string old_header_name; | 322 std::string old_header_name; |
| 323 std::string old_header_value; | 323 std::string old_header_value; |
| 324 while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) { | 324 while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) { |
| 325 std::string old_header_name_lowercase(name); | 325 std::string old_header_name_lowercase(name); |
| 326 StringToLowerASCII(&old_header_name_lowercase); | 326 base::StringToLowerASCII(&old_header_name_lowercase); |
| 327 | 327 |
| 328 if (name_lowercase == old_header_name_lowercase && | 328 if (name_lowercase == old_header_name_lowercase && |
| 329 value == old_header_value) | 329 value == old_header_value) |
| 330 continue; | 330 continue; |
| 331 | 331 |
| 332 new_raw_headers.append(old_header_name); | 332 new_raw_headers.append(old_header_name); |
| 333 new_raw_headers.push_back(':'); | 333 new_raw_headers.push_back(':'); |
| 334 new_raw_headers.push_back(' '); | 334 new_raw_headers.push_back(' '); |
| 335 new_raw_headers.append(old_header_value); | 335 new_raw_headers.append(old_header_value); |
| 336 new_raw_headers.push_back('\0'); | 336 new_raw_headers.push_back('\0'); |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 467 typedef base::hash_map<std::string, size_t> HeadersMap; | 467 typedef base::hash_map<std::string, size_t> HeadersMap; |
| 468 HeadersMap headers_map; | 468 HeadersMap headers_map; |
| 469 HeadersMap::iterator iter = headers_map.end(); | 469 HeadersMap::iterator iter = headers_map.end(); |
| 470 | 470 |
| 471 std::vector<std::string> headers; | 471 std::vector<std::string> headers; |
| 472 | 472 |
| 473 for (size_t i = 0; i < parsed_.size(); ++i) { | 473 for (size_t i = 0; i < parsed_.size(); ++i) { |
| 474 DCHECK(!parsed_[i].is_continuation()); | 474 DCHECK(!parsed_[i].is_continuation()); |
| 475 | 475 |
| 476 std::string name(parsed_[i].name_begin, parsed_[i].name_end); | 476 std::string name(parsed_[i].name_begin, parsed_[i].name_end); |
| 477 std::string lower_name = StringToLowerASCII(name); | 477 std::string lower_name = base::StringToLowerASCII(name); |
| 478 | 478 |
| 479 iter = headers_map.find(lower_name); | 479 iter = headers_map.find(lower_name); |
| 480 if (iter == headers_map.end()) { | 480 if (iter == headers_map.end()) { |
| 481 iter = headers_map.insert( | 481 iter = headers_map.insert( |
| 482 HeadersMap::value_type(lower_name, headers.size())).first; | 482 HeadersMap::value_type(lower_name, headers.size())).first; |
| 483 headers.push_back(name + ": "); | 483 headers.push_back(name + ": "); |
| 484 } else { | 484 } else { |
| 485 headers[iter->second].append(", "); | 485 headers[iter->second].append(", "); |
| 486 } | 486 } |
| 487 | 487 |
| (...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 843 // Skip over comma for next position. | 843 // Skip over comma for next position. |
| 844 item_end = item_next; | 844 item_end = item_next; |
| 845 item_next++; | 845 item_next++; |
| 846 } | 846 } |
| 847 // trim off leading and trailing whitespace in this item. | 847 // trim off leading and trailing whitespace in this item. |
| 848 HttpUtil::TrimLWS(&item, &item_end); | 848 HttpUtil::TrimLWS(&item, &item_end); |
| 849 | 849 |
| 850 // assuming the header is not empty, lowercase and insert into set | 850 // assuming the header is not empty, lowercase and insert into set |
| 851 if (item_end > item) { | 851 if (item_end > item) { |
| 852 std::string name(&*item, item_end - item); | 852 std::string name(&*item, item_end - item); |
| 853 StringToLowerASCII(&name); | 853 base::StringToLowerASCII(&name); |
| 854 result->insert(name); | 854 result->insert(name); |
| 855 } | 855 } |
| 856 | 856 |
| 857 // Continue to next item. | 857 // Continue to next item. |
| 858 item = item_next; | 858 item = item_next; |
| 859 } | 859 } |
| 860 } | 860 } |
| 861 } | 861 } |
| 862 | 862 |
| 863 void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { | 863 void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) { |
| (...skipping 530 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1394 return true; | 1394 return true; |
| 1395 } | 1395 } |
| 1396 | 1396 |
| 1397 bool HttpResponseHeaders::IsChunkEncoded() const { | 1397 bool HttpResponseHeaders::IsChunkEncoded() const { |
| 1398 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. | 1398 // Ignore spurious chunked responses from HTTP/1.0 servers and proxies. |
| 1399 return GetHttpVersion() >= HttpVersion(1, 1) && | 1399 return GetHttpVersion() >= HttpVersion(1, 1) && |
| 1400 HasHeaderValue("Transfer-Encoding", "chunked"); | 1400 HasHeaderValue("Transfer-Encoding", "chunked"); |
| 1401 } | 1401 } |
| 1402 | 1402 |
| 1403 } // namespace net | 1403 } // namespace net |
| OLD | NEW |