15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The rules for header parsing were borrowed from Firefox:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://lxr.mozilla.org/seamonkey/source/netwerk/protocol/http/src/nsHttpResponseHead.cpp
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The rules for parsing content-types were also borrowed from Firefox:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// http://lxr.mozilla.org/mozilla/source/netwerk/base/src/nsURLHelper.cpp#834
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_response_headers.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/metrics/histogram.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/pickle.h"
177d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_number_conversions.h"
18c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
197d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/string_util.h"
207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/strings/stringprintf.h"
21eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/escape.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/http/http_util.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::Time;
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::TimeDelta;
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These headers are RFC 2616 hop-by-hop headers;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not to be stored by caches.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kHopByHopResponseHeaders[] = {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "connection",
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "proxy-connection",
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "keep-alive",
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "trailer",
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "transfer-encoding",
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "upgrade"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These headers are challenge response headers;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not to be stored by caches.
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kChallengeResponseHeaders[] = {
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "www-authenticate",
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "proxy-authenticate"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These headers are cookie setting headers;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// not to be stored by caches or disclosed otherwise.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kCookieResponseHeaders[] = {
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "set-cookie",
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "set-cookie2"
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// By default, do not cache Strict-Transport-Security or Public-Key-Pins.
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This avoids erroneously re-processing them on page loads from cache ---
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// they are defined to be valid only on live and error-free HTTPS
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// connections.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kSecurityStateHeaders[] = {
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "strict-transport-security",
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "public-key-pins"
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// These response headers are not copied from a 304/206 response to the cached
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// response headers.  This list is based on Mozilla's nsHttpResponseHead.cpp.
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* const kNonUpdatedHeaders[] = {
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "connection",
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "proxy-connection",
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "keep-alive",
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "www-authenticate",
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "proxy-authenticate",
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "trailer",
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "transfer-encoding",
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "upgrade",
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  "etag",
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "x-frame-options",
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "x-xss-protection",
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Some header prefixes mean "Don't copy this header from a 304 response.".
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Rather than listing all the relevant headers, we can consolidate them into
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// this list:
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const char* const kNonUpdatedHeaderPrefixes[] = {
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "content-",
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "x-content-",
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  "x-webkit-"
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ShouldUpdateHeader(const std::string::const_iterator& name_begin,
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        const std::string::const_iterator& name_end) {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kNonUpdatedHeaders); ++i) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (LowerCaseEqualsASCII(name_begin, name_end, kNonUpdatedHeaders[i]))
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < arraysize(kNonUpdatedHeaderPrefixes); ++i) {
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (StartsWithASCII(std::string(name_begin, name_end),
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                        kNonUpdatedHeaderPrefixes[i], false))
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      return false;
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void CheckDoesNotHaveEmbededNulls(const std::string& str) {
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Care needs to be taken when adding values to the raw headers string to
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // make sure it does not contain embeded NULLs. Any embeded '\0' may be
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // understood as line terminators and change how header lines get tokenized.
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CHECK(str.find('\0') == std::string::npos);
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct HttpResponseHeaders::ParsedHeader {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A header "continuation" contains only a subsequent value for the
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preceding header.  (Header values are comma separated.)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool is_continuation() const { return name_begin == name_end; }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator name_begin;
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator name_end;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator value_begin;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator value_end;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//-----------------------------------------------------------------------------
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpResponseHeaders::HttpResponseHeaders(const std::string& raw_input)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : response_code_(-1) {
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parse(raw_input);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The most important thing to do with this histogram is find out
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the existence of unusual HTTP status codes.  As it happens
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // right now, there aren't double-constructions of response headers
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // using this constructor, so our counts should also be accurate,
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // without instantiating the histogram in two places.  It is also
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // important that this histogram not collect data in the other
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // constructor, which rebuilds an histogram from a pickle, since
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that would actually create a double call between the original
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // HttpResponseHeader that was serialized, and initialization of the
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // new object from that pickle.
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.HttpResponseCode",
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   HttpUtil::MapStatusCodeForHistogram(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       response_code_),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   // Note the third argument is only
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   // evaluated once, see macro
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   // definition for details.
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   HttpUtil::GetStatusCodesForHistogram());
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpResponseHeaders::HttpResponseHeaders(const Pickle& pickle,
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                         PickleIterator* iter)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : response_code_(-1) {
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string raw_input;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (pickle.ReadString(iter, &raw_input))
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Parse(raw_input);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::Persist(Pickle* pickle, PersistOptions options) {
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (options == PERSIST_RAW) {
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pickle->WriteString(raw_headers_);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;  // Done.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderSet filter_headers;
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Construct set of headers to filter out based on options.
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_NON_CACHEABLE) == PERSIST_SANS_NON_CACHEABLE)
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddNonCacheableHeaders(&filter_headers);
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_COOKIES) == PERSIST_SANS_COOKIES)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddCookieHeaders(&filter_headers);
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_CHALLENGES) == PERSIST_SANS_CHALLENGES)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddChallengeHeaders(&filter_headers);
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_HOP_BY_HOP) == PERSIST_SANS_HOP_BY_HOP)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddHopByHopHeaders(&filter_headers);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_RANGES) == PERSIST_SANS_RANGES)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddHopContentRangeHeaders(&filter_headers);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((options & PERSIST_SANS_SECURITY_STATE) == PERSIST_SANS_SECURITY_STATE)
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddSecurityStateHeaders(&filter_headers);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string blob;
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blob.reserve(raw_headers_.size());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This copies the status line w/ terminator null.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note raw_headers_ has embedded nulls instead of \n,
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so this just copies the first header line.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blob.assign(raw_headers_.c_str(), strlen(raw_headers_.c_str()) + 1);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < parsed_.size(); ++i) {
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!parsed_[i].is_continuation());
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locate the start of the next header.
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t k = i;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (++k < parsed_.size() && parsed_[k].is_continuation()) {}
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --k;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string header_name(parsed_[i].name_begin, parsed_[i].name_end);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringToLowerASCII(&header_name);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (filter_headers.find(header_name) == filter_headers.end()) {
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Make sure there is a null after the value.
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blob.append(parsed_[i].name_begin, parsed_[k].value_end);
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      blob.push_back('\0');
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = k;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  blob.push_back('\0');
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pickle->WriteString(blob);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::Update(const HttpResponseHeaders& new_headers) {
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(new_headers.response_code() == 304 ||
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         new_headers.response_code() == 206);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy up to the null byte.  This just copies the status line.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(raw_headers_.c_str());
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderSet updated_headers;
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: we write the new headers then the old headers for convenience.  The
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // order should not matter.
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Figure out which headers we want to take from new_headers:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < new_headers.parsed_.size(); ++i) {
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const HeaderList& new_parsed = new_headers.parsed_;
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!new_parsed[i].is_continuation());
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locate the start of the next header.
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t k = i;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (++k < new_parsed.size() && new_parsed[k].is_continuation()) {}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --k;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string::const_iterator& name_begin = new_parsed[i].name_begin;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string::const_iterator& name_end = new_parsed[i].name_end;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ShouldUpdateHeader(name_begin, name_end)) {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string name(name_begin, name_end);
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      StringToLowerASCII(&name);
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      updated_headers.insert(name);
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Preserve this header line in the merged result, making sure there is
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // a null after the value.
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_raw_headers.append(name_begin, new_parsed[k].value_end);
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_raw_headers.push_back('\0');
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = k;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, build the new raw headers.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MergeWithHeaders(new_raw_headers, updated_headers);
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::MergeWithHeaders(const std::string& raw_headers,
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const HeaderSet& headers_to_remove) {
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(raw_headers);
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < parsed_.size(); ++i) {
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!parsed_[i].is_continuation());
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Locate the start of the next header.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t k = i;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (++k < parsed_.size() && parsed_[k].is_continuation()) {}
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --k;
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name(parsed_[i].name_begin, parsed_[i].name_end);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringToLowerASCII(&name);
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (headers_to_remove.find(name) == headers_to_remove.end()) {
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // It's ok to preserve this header in the final result.
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_raw_headers.append(parsed_[i].name_begin, parsed_[k].value_end);
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new_raw_headers.push_back('\0');
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = k;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make this object hold the new data.
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.clear();
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_.clear();
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parse(new_raw_headers);
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::RemoveHeader(const std::string& name) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy up to the null byte.  This just copies the status line.
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(raw_headers_.c_str());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string lowercase_name(name);
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringToLowerASCII(&lowercase_name);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderSet to_remove;
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  to_remove.insert(lowercase_name);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MergeWithHeaders(new_raw_headers, to_remove);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::RemoveHeaderLine(const std::string& name,
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                           const std::string& value) {
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name_lowercase(name);
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StringToLowerASCII(&name_lowercase);
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(GetStatusLine());
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.reserve(raw_headers_.size());
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string old_header_name;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string old_header_value;
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeaderLines(&iter, &old_header_name, &old_header_value)) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string old_header_name_lowercase(name);
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    StringToLowerASCII(&old_header_name_lowercase);
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (name_lowercase == old_header_name_lowercase &&
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        value == old_header_value)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_raw_headers.append(old_header_name);
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_raw_headers.push_back(':');
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_raw_headers.push_back(' ');
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_raw_headers.append(old_header_value);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    new_raw_headers.push_back('\0');
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make this object hold the new data.
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.clear();
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_.clear();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parse(new_raw_headers);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddHeader(const std::string& header) {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckDoesNotHaveEmbededNulls(header);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Don't copy the last null.
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(raw_headers_, 0, raw_headers_.size() - 1);
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.append(header);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make this object hold the new data.
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.clear();
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_.clear();
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Parse(new_raw_headers);
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::ReplaceStatusLine(const std::string& new_status) {
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  CheckDoesNotHaveEmbededNulls(new_status);
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Copy up to the null byte.  This just copies the status line.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string new_raw_headers(new_status);
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  new_raw_headers.push_back('\0');
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeaderSet empty_to_remove;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MergeWithHeaders(new_raw_headers, empty_to_remove);
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::Parse(const std::string& raw_input) {
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.reserve(raw_input.size());
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // ParseStatusLine adds a normalized status line to raw_headers_
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator line_begin = raw_input.begin();
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator line_end =
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::find(line_begin, raw_input.end(), '\0');
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // has_headers = true, if there is any data following the status line.
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used by ParseStatusLine() to decide if a HTTP/0.9 is really a HTTP/1.0.
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool has_headers = (line_end != raw_input.end() &&
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      (line_end + 1) != raw_input.end() &&
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      *(line_end + 1) != '\0');
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParseStatusLine(line_begin, line_end, has_headers);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.push_back('\0');  // Terminate status line with a null.
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (line_end == raw_input.end()) {
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.push_back('\0');  // Ensure the headers end with a double null.
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]);
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Including a terminating null byte.
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t status_line_len = raw_headers_.size();
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now, we add the rest of the raw headers to raw_headers_, and begin parsing
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it (to populate our parsed_ vector).
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.append(line_end + 1, raw_input.end());
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ensure the headers end with a double null.
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (raw_headers_.size() < 2 ||
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         raw_headers_[raw_headers_.size() - 2] != '\0' ||
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         raw_headers_[raw_headers_.size() - 1] != '\0') {
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.push_back('\0');
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Adjust to point at the null byte following the status line
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  line_end = raw_headers_.begin() + status_line_len - 1;
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::HeadersIterator headers(line_end + 1, raw_headers_.end(),
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::string(1, '\0'));
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (headers.GetNext()) {
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddHeader(headers.name_begin(),
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              headers.name_end(),
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              headers.values_begin(),
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)              headers.values_end());
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 2]);
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_EQ('\0', raw_headers_[raw_headers_.size() - 1]);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Append all of our headers to the final output string.
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::GetNormalizedHeaders(std::string* output) const {
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copy up to the null byte.  this just copies the status line.
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->assign(raw_headers_.c_str());
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headers may appear multiple times (not necessarily in succession) in the
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // header data, so we build a map from header name to generated header lines.
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to preserve the order of the original headers, the actual values are kept
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // in a separate list.  finally, the list of headers is flattened to form
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the normalized block of headers.
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: We take special care to preserve the whitespace around any commas
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that may occur in the original response headers.  Because our consumer may
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // be a web app, we cannot be certain of the semantics of commas despite the
4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // fact that RFC 2616 says that they should be regarded as value separators.
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  typedef base::hash_map<std::string, size_t> HeadersMap;
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeadersMap headers_map;
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HeadersMap::iterator iter = headers_map.end();
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> headers;
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < parsed_.size(); ++i) {
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!parsed_[i].is_continuation());
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string name(parsed_[i].name_begin, parsed_[i].name_end);
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string lower_name = StringToLowerASCII(name);
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    iter = headers_map.find(lower_name);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (iter == headers_map.end()) {
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      iter = headers_map.insert(
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          HeadersMap::value_type(lower_name, headers.size())).first;
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers.push_back(name + ": ");
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      headers[iter->second].append(", ");
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator value_begin = parsed_[i].value_begin;
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator value_end = parsed_[i].value_end;
4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (++i < parsed_.size() && parsed_[i].is_continuation())
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_end = parsed_[i].value_end;
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --i;
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers[iter->second].append(value_begin, value_end);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < headers.size(); ++i) {
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->push_back('\n');
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    output->append(headers[i]);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output->push_back('\n');
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetNormalizedHeader(const std::string& name,
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              std::string* value) const {
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If you hit this assertion, please use EnumerateHeader instead!
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!HttpUtil::IsNonCoalescingHeader(name));
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->clear();
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool found = false;
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i = 0;
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (i < parsed_.size()) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = FindHeader(i, name);
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == std::string::npos)
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    found = true;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value->empty())
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value->append(", ");
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator value_begin = parsed_[i].value_begin;
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator value_end = parsed_[i].value_end;
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (++i < parsed_.size() && parsed_[i].is_continuation())
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      value_end = parsed_[i].value_end;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value->append(value_begin, value_end);
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return found;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HttpResponseHeaders::GetStatusLine() const {
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copy up to the null byte.
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(raw_headers_.c_str());
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string HttpResponseHeaders::GetStatusText() const {
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // GetStatusLine() is already normalized, so it has the format:
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // <http_version> SP <response_code> SP <status_text>
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string status_text = GetStatusLine();
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator begin = status_text.begin();
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator end = status_text.end();
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < 2; ++i)
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    begin = std::find(begin, end, ' ') + 1;
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(begin, end);
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::EnumerateHeaderLines(void** iter,
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               std::string* name,
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                               std::string* value) const {
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i = reinterpret_cast<size_t>(*iter);
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == parsed_.size())
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!parsed_[i].is_continuation());
5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  name->assign(parsed_[i].name_begin, parsed_[i].name_end);
5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator value_begin = parsed_[i].value_begin;
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator value_end = parsed_[i].value_end;
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (++i < parsed_.size() && parsed_[i].is_continuation())
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value_end = parsed_[i].value_end;
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->assign(value_begin, value_end);
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *iter = reinterpret_cast<void*>(i);
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
541c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HttpResponseHeaders::EnumerateHeader(void** iter,
542c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::StringPiece& name,
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          std::string* value) const {
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i;
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!iter || !*iter) {
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = FindHeader(0, name);
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = reinterpret_cast<size_t>(*iter);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i >= parsed_.size()) {
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = std::string::npos;
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else if (!parsed_[i].is_continuation()) {
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      i = FindHeader(i, name);
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (i == std::string::npos) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    value->clear();
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (iter)
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *iter = reinterpret_cast<void*>(i + 1);
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  value->assign(parsed_[i].value_begin, parsed_[i].value_end);
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HttpResponseHeaders::HasHeaderValue(const base::StringPiece& name,
568c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                         const base::StringPiece& value) const {
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The value has to be an exact match.  This is important since
5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 'cache-control: no-cache' != 'cache-control: no-cache="foo"'
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string temp;
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeader(&iter, name, &temp)) {
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value.size() == temp.size() &&
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::equal(temp.begin(), temp.end(), value.begin(),
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::CaseInsensitiveCompare<char>()))
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return true;
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
582c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool HttpResponseHeaders::HasHeader(const base::StringPiece& name) const {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return FindHeader(0, name) != std::string::npos;
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpResponseHeaders::HttpResponseHeaders() : response_code_(-1) {
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpResponseHeaders::~HttpResponseHeaders() {
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this implementation implicitly assumes that line_end points at a valid
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sentinel character (such as '\0').
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HttpVersion HttpResponseHeaders::ParseVersion(
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator line_begin,
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator line_end) {
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator p = line_begin;
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // RFC2616 sec 3.1: HTTP-Version   = "HTTP" "/" 1*DIGIT "." 1*DIGIT
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: (1*DIGIT apparently means one or more digits, but we only handle 1).
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO: handle leading zeros, which is allowed by the rfc1616 sec 3.1.
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((line_end - p < 4) || !LowerCaseEqualsASCII(p, p + 4, "http")) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "missing status line";
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HttpVersion();
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  p += 4;
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p >= line_end || *p != '/') {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "missing version";
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HttpVersion();
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator dot = std::find(p, line_end, '.');
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (dot == line_end) {
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "malformed version";
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HttpVersion();
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++p;  // from / to first digit.
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ++dot;  // from . to second digit.
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!(*p >= '0' && *p <= '9' && *dot >= '0' && *dot <= '9')) {
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "malformed version number";
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return HttpVersion();
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 major = *p - '0';
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 minor = *dot - '0';
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HttpVersion(major, minor);
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: this implementation implicitly assumes that line_end points at a valid
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sentinel character (such as '\0').
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::ParseStatusLine(
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator line_begin,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string::const_iterator line_end,
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool has_headers) {
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Extract the version number
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_http_version_ = ParseVersion(line_begin, line_end);
6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Clamp the version number to one of: {0.9, 1.0, 1.1}
6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_http_version_ == HttpVersion(0, 9) && !has_headers) {
6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_version_ = HttpVersion(0, 9);
6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_ = "HTTP/0.9";
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (parsed_http_version_ >= HttpVersion(1, 1)) {
6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_version_ = HttpVersion(1, 1);
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_ = "HTTP/1.1";
6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Treat everything else like HTTP 1.0
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    http_version_ = HttpVersion(1, 0);
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_ = "HTTP/1.0";
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parsed_http_version_ != http_version_) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "assuming HTTP/" << http_version_.major_value() << "."
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             << http_version_.minor_value();
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(eroman): this doesn't make sense if ParseVersion failed.
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator p = std::find(line_begin, line_end, ' ');
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p == line_end) {
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "missing response status; assuming 200 OK";
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.append(" 200 OK");
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code_ = 200;
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip whitespace.
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*p == ' ')
6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++p;
6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator code = p;
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*p >= '0' && *p <= '9')
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++p;
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p == code) {
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "missing response status number; assuming 200";
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.append(" 200 OK");
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    response_code_ = 200;
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.push_back(' ');
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.append(code, p);
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers_.push_back(' ');
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringToInt(StringPiece(code, p), &response_code_);
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip whitespace.
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (*p == ' ')
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ++p;
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Trim trailing whitespace.
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (line_end > p && line_end[-1] == ' ')
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --line_end;
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (p == line_end) {
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "missing response status text; assuming OK";
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Not super critical what we put here. Just use "OK"
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // even if it isn't descriptive of response_code_.
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.append("OK");
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers_.append(p, line_end);
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t HttpResponseHeaders::FindHeader(size_t from,
710c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                       const base::StringPiece& search) const {
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = from; i < parsed_.size(); ++i) {
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parsed_[i].is_continuation())
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string::const_iterator& name_begin = parsed_[i].name_begin;
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string::const_iterator& name_end = parsed_[i].name_end;
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (static_cast<size_t>(name_end - name_begin) == search.size() &&
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::equal(name_begin, name_end, search.begin(),
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   base::CaseInsensitiveCompare<char>()))
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return i;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string::npos;
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddHeader(std::string::const_iterator name_begin,
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::string::const_iterator name_end,
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::string::const_iterator values_begin,
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    std::string::const_iterator values_end) {
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the header can be coalesced, then we should split it up.
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (values_begin == values_end ||
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpUtil::IsNonCoalescingHeader(name_begin, name_end)) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    AddToParsed(name_begin, name_end, values_begin, values_end);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpUtil::ValuesIterator it(values_begin, values_end, ',');
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    while (it.GetNext()) {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      AddToParsed(name_begin, name_end, it.value_begin(), it.value_end());
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // clobber these so that subsequent values are treated as continuations
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      name_begin = name_end = raw_headers_.end();
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddToParsed(std::string::const_iterator name_begin,
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string::const_iterator name_end,
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string::const_iterator value_begin,
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      std::string::const_iterator value_end) {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ParsedHeader header;
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.name_begin = name_begin;
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.name_end = name_end;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.value_begin = value_begin;
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  header.value_end = value_end;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  parsed_.push_back(header);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddNonCacheableHeaders(HeaderSet* result) const {
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Add server specified transients.  Any 'cache-control: no-cache="foo,bar"'
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // headers present in the response specify additional headers that we should
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not store in the cache.
759c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kCacheControl[] = "cache-control";
760c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const char kPrefix[] = "no-cache=\"";
761c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const size_t kPrefixLen = sizeof(kPrefix) - 1;
762c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeader(&iter, kCacheControl, &value)) {
766c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // If the value is smaller than the prefix and a terminal quote, skip
767c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // it.
768c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (value.size() <= kPrefixLen ||
769c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        value.compare(0, kPrefixLen, kPrefix) != 0) {
770c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
771c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    }
772c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // if it doesn't end with a quote, then treat as malformed
773c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (value[value.size()-1] != '\"')
774c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      continue;
775c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
776c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // process the value as a comma-separated list of items. Each
777c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    // item can be wrapped by linear white space.
778c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string::const_iterator item = value.begin() + kPrefixLen;
779c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string::const_iterator end = value.end() - 1;
780c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    while (item != end) {
781c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Find the comma to compute the length of the current item,
782c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // and the position of the next one.
783c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string::const_iterator item_next = std::find(item, end, ',');
784c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      std::string::const_iterator item_end = end;
785c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (item_next != end) {
786c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        // Skip over comma for next position.
787c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        item_end = item_next;
788c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        item_next++;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
790c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // trim off leading and trailing whitespace in this item.
791c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      HttpUtil::TrimLWS(&item, &item_end);
792c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
793c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // assuming the header is not empty, lowercase and insert into set
794c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      if (item_end > item) {
795c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        std::string name(&*item, item_end - item);
796c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        StringToLowerASCII(&name);
797c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        result->insert(name);
798c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      }
799c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
800c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      // Continue to next item.
801c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      item = item_next;
8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddHopByHopHeaders(HeaderSet* result) {
8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kHopByHopResponseHeaders); ++i)
8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->insert(std::string(kHopByHopResponseHeaders[i]));
8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddCookieHeaders(HeaderSet* result) {
8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kCookieResponseHeaders); ++i)
8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->insert(std::string(kCookieResponseHeaders[i]));
8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddChallengeHeaders(HeaderSet* result) {
8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kChallengeResponseHeaders); ++i)
8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->insert(std::string(kChallengeResponseHeaders[i]));
8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddHopContentRangeHeaders(HeaderSet* result) {
8225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result->insert("content-range");
8235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::AddSecurityStateHeaders(HeaderSet* result) {
8265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < arraysize(kSecurityStateHeaders); ++i)
8275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result->insert(std::string(kSecurityStateHeaders[i]));
8285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void HttpResponseHeaders::GetMimeTypeAndCharset(std::string* mime_type,
8315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                std::string* charset) const {
8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mime_type->clear();
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  charset->clear();
8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = "content-type";
8365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
8375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool had_charset = false;
8395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeader(&iter, name, &value))
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    HttpUtil::ParseContentType(value, mime_type, charset, &had_charset, NULL);
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetMimeType(std::string* mime_type) const {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string unused;
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetMimeTypeAndCharset(mime_type, &unused);
8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !mime_type->empty();
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetCharset(std::string* charset) const {
8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string unused;
8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetMimeTypeAndCharset(&unused, charset);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return !charset->empty();
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::IsRedirect(std::string* location) const {
8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!IsRedirectResponseCode(response_code_))
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If we lack a Location header, then we can't treat this as a redirect.
8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We assume that the first non-empty location value is the target URL that
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // we want to follow.  TODO(darin): Is this consistent with other browsers?
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t i = std::string::npos;
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  do {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    i = FindHeader(++i, "location");
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == std::string::npos)
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If the location value is empty, then it doesn't count.
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } while (parsed_[i].value_begin == parsed_[i].value_end);
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (location) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Escape any non-ASCII characters to preserve them.  The server should
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // only be returning ASCII here, but for compat we need to do this.
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *location = EscapeNonASCII(
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        std::string(parsed_[i].value_begin, parsed_[i].value_end));
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::IsRedirectResponseCode(int response_code) {
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Users probably want to see 300 (multiple choice) pages, so we don't count
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them as redirects that need to be followed.
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return (response_code == 301 ||
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response_code == 302 ||
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response_code == 303 ||
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          response_code == 307);
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From RFC 2616 section 13.2.4:
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The calculation to determine if a response has expired is quite simple:
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   response_is_fresh = (freshness_lifetime > current_age)
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Of course, there are other factors that can force a response to always be
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// validated or re-fetched.
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::RequiresValidation(const Time& request_time,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const Time& response_time,
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const Time& current_time) const {
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta lifetime =
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetFreshnessLifetime(response_time);
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (lifetime == TimeDelta())
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return lifetime <= GetCurrentAge(request_time, response_time, current_time);
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From RFC 2616 section 13.2.4:
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The max-age directive takes priority over Expires, so if max-age is present
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// in a response, the calculation is simply:
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   freshness_lifetime = max_age_value
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Otherwise, if Expires is present in the response, the calculation is:
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   freshness_lifetime = expires_value - date_value
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that neither of these calculations is vulnerable to clock skew, since
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// all of the information comes from the origin server.
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Also, if the response does have a Last-Modified time, the heuristic
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// expiration value SHOULD be no more than some fraction of the interval since
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that time. A typical setting of this fraction might be 10%:
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   freshness_lifetime = (date_value - last_modified_value) * 0.10
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta HttpResponseHeaders::GetFreshnessLifetime(
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const Time& response_time) const {
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Check for headers that force a response to never be fresh.  For backwards
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // compat, we treat "Pragma: no-cache" as a synonym for "Cache-Control:
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // no-cache" even though RFC 2616 does not specify it.
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (HasHeaderValue("cache-control", "no-cache") ||
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasHeaderValue("cache-control", "no-store") ||
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasHeaderValue("pragma", "no-cache") ||
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasHeaderValue("vary", "*"))  // see RFC 2616 section 13.6
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta();  // not fresh
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: "Cache-Control: max-age" overrides Expires, so we only check the
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Expires header after checking for max-age in GetFreshnessLifetime.  This
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // is important since "Expires: <date in the past>" means not fresh, but
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // it should not trump a max-age value.
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta max_age_value;
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetMaxAgeValue(&max_age_value))
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return max_age_value;
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is no Date header, then assume that the server response was
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generated at the time when we received the response.
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time date_value;
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetDateValue(&date_value))
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    date_value = response_time;
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time expires_value;
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (GetExpiresValue(&expires_value)) {
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The expires value can be a date in the past!
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (expires_value > date_value)
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return expires_value - date_value;
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta();  // not fresh
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From RFC 2616 section 13.4:
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A response received with a status code of 200, 203, 206, 300, 301 or 410
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   MAY be stored by a cache and used in reply to a subsequent request,
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   subject to the expiration mechanism, unless a cache-control directive
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   prohibits caching.
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   ...
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   A response received with any other status code (e.g. status codes 302
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   and 307) MUST NOT be returned in a reply to a subsequent request unless
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   there are cache-control directives or another header(s) that explicitly
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   allow it.
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // From RFC 2616 section 14.9.4:
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   When the must-revalidate directive is present in a response received by
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   a cache, that cache MUST NOT use the entry after it becomes stale to
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   respond to a subsequent request without first revalidating it with the
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   origin server. (I.e., the cache MUST do an end-to-end revalidation every
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   time, if, based solely on the origin server's Expires or max-age value,
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   the cached response is stale.)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if ((response_code_ == 200 || response_code_ == 203 ||
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       response_code_ == 206) &&
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !HasHeaderValue("cache-control", "must-revalidate")) {
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // TODO(darin): Implement a smarter heuristic.
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Time last_modified_value;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (GetLastModifiedValue(&last_modified_value)) {
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // The last-modified value can be a date in the past!
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (last_modified_value <= date_value)
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return (date_value - last_modified_value) / 10;
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // These responses are implicitly fresh (unless otherwise overruled):
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (response_code_ == 300 || response_code_ == 301 || response_code_ == 410)
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return TimeDelta::FromMicroseconds(kint64max);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return TimeDelta();  // not fresh
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From RFC 2616 section 13.2.3:
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Summary of age calculation algorithm, when a cache receives a response:
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   /*
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    * age_value
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *      is the value of Age: header received by the cache with
10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *              this response.
10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    * date_value
10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *      is the value of the origin server's Date: header
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    * request_time
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *      is the (local) time when the cache made the request
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *              that resulted in this cached response
10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    * response_time
10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *      is the (local) time when the cache received the
10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *              response
10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    * now
10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    *      is the current (local) time
10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    */
10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   apparent_age = max(0, response_time - date_value);
10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   corrected_received_age = max(apparent_age, age_value);
10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   response_delay = response_time - request_time;
10295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   corrected_initial_age = corrected_received_age + response_delay;
10305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   resident_time = now - response_time;
10315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   current_age   = corrected_initial_age + resident_time;
10325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TimeDelta HttpResponseHeaders::GetCurrentAge(const Time& request_time,
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const Time& response_time,
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                             const Time& current_time) const {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is no Date header, then assume that the server response was
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // generated at the time when we received the response.
10385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Time date_value;
10395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetDateValue(&date_value))
10405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    date_value = response_time;
10415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If there is no Age header, then assume age is zero.  GetAgeValue does not
10435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // modify its out param if the value does not exist.
10445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta age_value;
10455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GetAgeValue(&age_value);
10465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta apparent_age = std::max(TimeDelta(), response_time - date_value);
10485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta corrected_received_age = std::max(apparent_age, age_value);
10495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta response_delay = response_time - request_time;
10505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta corrected_initial_age = corrected_received_age + response_delay;
10515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta resident_time = current_time - response_time;
10525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TimeDelta current_age = corrected_initial_age + resident_time;
10535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return current_age;
10555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetMaxAgeValue(TimeDelta* result) const {
10585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name = "cache-control";
10595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
10605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char kMaxAgePrefix[] = "max-age=";
10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t kMaxAgePrefixLen = arraysize(kMaxAgePrefix) - 1;
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
10655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeader(&iter, name, &value)) {
10665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (value.size() > kMaxAgePrefixLen) {
10675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (LowerCaseEqualsASCII(value.begin(),
10685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               value.begin() + kMaxAgePrefixLen,
10695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               kMaxAgePrefix)) {
10705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int64 seconds;
10715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringToInt64(StringPiece(value.begin() + kMaxAgePrefixLen,
10725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        value.end()),
10735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            &seconds);
10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *result = TimeDelta::FromSeconds(seconds);
10755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
10765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
10815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetAgeValue(TimeDelta* result) const {
10845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnumerateHeader(NULL, "Age", &value))
10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
10875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 seconds;
10895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::StringToInt64(value, &seconds);
10905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *result = TimeDelta::FromSeconds(seconds);
10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetDateValue(Time* result) const {
10955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetTimeValuedHeader("Date", result);
10965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetLastModifiedValue(Time* result) const {
10995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetTimeValuedHeader("Last-Modified", result);
11005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetExpiresValue(Time* result) const {
11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetTimeValuedHeader("Expires", result);
11045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetTimeValuedHeader(const std::string& name,
11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              Time* result) const {
11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnumerateHeader(NULL, name, &value))
11105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // When parsing HTTP dates it's beneficial to default to GMT because:
11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 1. RFC2616 3.3.1 says times should always be specified in GMT
11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 2. Only counter-example incorrectly appended "UTC" (crbug.com/153759)
11155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 3. When adjusting cookie expiration times for clock skew
11165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    (crbug.com/135131) this better matches our cookie expiration
11175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    time parser which ignores timezone specifiers and assumes GMT.
11185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // 4. This is exactly what Firefox does.
11195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(pauljensen): The ideal solution would be to return false if the
11205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // timezone could not be understood so as to avoid makeing other calculations
11215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // based on an incorrect time.  This would require modifying the time
11225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // library or duplicating the code. (http://crbug.com/158327)
11235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return Time::FromUTCString(value.c_str(), result);
11245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::IsKeepAlive() const {
11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_version_ < HttpVersion(1, 0))
11285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // NOTE: It is perhaps risky to assume that a Proxy-Connection header is
11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // meaningful when we don't know that this response was from a proxy, but
11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Mozilla also does this, so we'll do the same.
11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string connection_val;
11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnumerateHeader(NULL, "connection", &connection_val))
11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EnumerateHeader(NULL, "proxy-connection", &connection_val);
11365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool keep_alive;
11385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (http_version_ == HttpVersion(1, 0)) {
11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // HTTP/1.0 responses default to NOT keep-alive
11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keep_alive = LowerCaseEqualsASCII(connection_val, "keep-alive");
11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // HTTP/1.1 responses default to keep-alive
11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    keep_alive = !LowerCaseEqualsASCII(connection_val, "close");
11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
11465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return keep_alive;
11485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::HasStrongValidators() const {
11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string etag_header;
11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateHeader(NULL, "etag", &etag_header);
11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string last_modified_header;
11545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateHeader(NULL, "Last-Modified", &last_modified_header);
11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string date_header;
11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnumerateHeader(NULL, "Date", &date_header);
11575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return HttpUtil::HasStrongValidators(GetHttpVersion(),
11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       etag_header,
11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       last_modified_header,
11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       date_header);
11615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From RFC 2616:
11645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Content-Length = "Content-Length" ":" 1*DIGIT
11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 HttpResponseHeaders::GetContentLength() const {
11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetInt64HeaderValue("content-length");
11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int64 HttpResponseHeaders::GetInt64HeaderValue(
11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& header) const {
11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content_length_val;
11735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnumerateHeader(&iter, header, &content_length_val))
11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_length_val.empty())
11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
11785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_length_val[0] == '+')
11805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
11815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int64 result;
11835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool ok = base::StringToInt64(content_length_val, &result);
11845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ok || result < 0)
11855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
11865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
11885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
11895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// From RFC 2616 14.16:
11915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// content-range-spec =
11925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//     bytes-unit SP byte-range-resp-spec "/" ( instance-length | "*" )
11935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// byte-range-resp-spec = (first-byte-pos "-" last-byte-pos) | "*"
11945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instance-length = 1*DIGIT
11955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes-unit = "bytes"
11965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::GetContentRange(int64* first_byte_position,
11975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int64* last_byte_position,
11985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          int64* instance_length) const {
11995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iter = NULL;
12005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string content_range_spec;
12015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *first_byte_position = *last_byte_position = *instance_length = -1;
12025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!EnumerateHeader(&iter, "content-range", &content_range_spec))
12035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the header value is empty, we have an invalid header.
12065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (content_range_spec.empty())
12075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t space_position = content_range_spec.find(' ');
12105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (space_position == std::string::npos)
12115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Invalid header if it doesn't contain "bytes-unit".
12145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator content_range_spec_begin =
12155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.begin();
12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator content_range_spec_end =
12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.begin() + space_position;
12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::TrimLWS(&content_range_spec_begin, &content_range_spec_end);
12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LowerCaseEqualsASCII(content_range_spec_begin,
12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            content_range_spec_end,
12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            "bytes")) {
12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t slash_position = content_range_spec.find('/', space_position + 1);
12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (slash_position == std::string::npos)
12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Obtain the part behind the space and before slash.
12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator byte_range_resp_spec_begin =
12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.begin() + space_position + 1;
12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator byte_range_resp_spec_end =
12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.begin() + slash_position;
12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::TrimLWS(&byte_range_resp_spec_begin, &byte_range_resp_spec_end);
12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the byte-range-resp-spec part.
12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string byte_range_resp_spec(byte_range_resp_spec_begin,
12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   byte_range_resp_spec_end);
12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If byte-range-resp-spec != "*".
12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!LowerCaseEqualsASCII(byte_range_resp_spec, "*")) {
12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t minus_position = byte_range_resp_spec.find('-');
12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (minus_position != std::string::npos) {
12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Obtain first-byte-pos.
12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator first_byte_pos_begin =
12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          byte_range_resp_spec.begin();
12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator first_byte_pos_end =
12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          byte_range_resp_spec.begin() + minus_position;
12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpUtil::TrimLWS(&first_byte_pos_begin, &first_byte_pos_end);
12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      bool ok = base::StringToInt64(StringPiece(first_byte_pos_begin,
12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                first_byte_pos_end),
12525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    first_byte_position);
12535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Obtain last-byte-pos.
12555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator last_byte_pos_begin =
12565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          byte_range_resp_spec.begin() + minus_position + 1;
12575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string::const_iterator last_byte_pos_end =
12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          byte_range_resp_spec.end();
12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HttpUtil::TrimLWS(&last_byte_pos_begin, &last_byte_pos_end);
12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ok &= base::StringToInt64(StringPiece(last_byte_pos_begin,
12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            last_byte_pos_end),
12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                last_byte_position);
12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!ok) {
12655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        *first_byte_position = *last_byte_position = -1;
12665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
12675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
12685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (*first_byte_position < 0 || *last_byte_position < 0 ||
12695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *first_byte_position > *last_byte_position)
12705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
12715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
12725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
12735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
12745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the instance-length part.
12775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If instance-length == "*".
12785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator instance_length_begin =
12795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.begin() + slash_position + 1;
12805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator instance_length_end =
12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      content_range_spec.end();
12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  HttpUtil::TrimLWS(&instance_length_begin, &instance_length_end);
12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (LowerCaseEqualsASCII(instance_length_begin, instance_length_end, "*")) {
12855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (!base::StringToInt64(StringPiece(instance_length_begin,
12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              instance_length_end),
12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  instance_length)) {
12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *instance_length = -1;
12905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
12925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We have all the values; let's verify that they make sense for a 206
12945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // response.
12955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (*first_byte_position < 0 || *last_byte_position < 0 ||
12965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *instance_length < 0 || *instance_length - 1 < *last_byte_position)
12975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
12985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
12995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)base::Value* HttpResponseHeaders::NetLogCallback(
13035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NetLog::LogLevel /* log_level */) const {
13047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
13057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  base::ListValue* headers = new base::ListValue();
13067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  headers->Append(new base::StringValue(GetStatusLine()));
13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void* iterator = NULL;
13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string name;
13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string value;
13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (EnumerateHeaderLines(&iterator, &name, &value)) {
13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    headers->Append(
13127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      new base::StringValue(base::StringPrintf("%s: %s",
13137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                               name.c_str(),
13147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                               value.c_str())));
13155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dict->Set("headers", headers);
13175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return dict;
13185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static
13215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::FromNetLogParam(
13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const base::Value* event_param,
13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    scoped_refptr<HttpResponseHeaders>* http_response_headers) {
13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *http_response_headers = NULL;
13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::DictionaryValue* dict = NULL;
13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const base::ListValue* header_list = NULL;
13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!event_param ||
13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !event_param->GetAsDictionary(&dict) ||
13315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !dict->GetList("headers", &header_list)) {
13325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
13335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string raw_headers;
13365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (base::ListValue::const_iterator it = header_list->begin();
13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       it != header_list->end();
13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       ++it) {
13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string header_line;
13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(*it)->GetAsString(&header_line))
13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
13425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers.append(header_line);
13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    raw_headers.push_back('\0');
13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  raw_headers.push_back('\0');
13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *http_response_headers = new HttpResponseHeaders(raw_headers);
13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HttpResponseHeaders::IsChunkEncoded() const {
13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Ignore spurious chunked responses from HTTP/1.0 servers and proxies.
13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return GetHttpVersion() >= HttpVersion(1, 1) &&
13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HasHeaderValue("Transfer-Encoding", "chunked");
13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1358