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 |