// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"

#include <memory>
#include <vector>

#include "url/gurl.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_map_util.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_string_piece.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_text_utils.h"
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"

using spdy::SpdyHeaderBlock;

namespace quic {

// static
bool SpdyUtils::ExtractContentLengthFromHeaders(int64_t* content_length,
                                                SpdyHeaderBlock* headers) {
  auto it = headers->find("content-length");
  if (it == headers->end()) {
    return false;
  } else {
    // Check whether multiple values are consistent.
    QuicStringPiece content_length_header = it->second;
    std::vector<QuicStringPiece> values =
        QuicTextUtils::Split(content_length_header, '\0');
    for (const QuicStringPiece& value : values) {
      uint64_t new_value;
      if (!QuicTextUtils::StringToUint64(value, &new_value)) {
        QUIC_DLOG(ERROR)
            << "Content length was either unparseable or negative.";
        return false;
      }
      if (*content_length < 0) {
        *content_length = new_value;
        continue;
      }
      if (new_value != static_cast<uint64_t>(*content_length)) {
        QUIC_DLOG(ERROR)
            << "Parsed content length " << new_value << " is "
            << "inconsistent with previously detected content length "
            << *content_length;
        return false;
      }
    }
    return true;
  }
}

bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
                                       int64_t* content_length,
                                       SpdyHeaderBlock* headers) {
  for (const auto& p : header_list) {
    const std::string& name = p.first;
    if (name.empty()) {
      QUIC_DLOG(ERROR) << "Header name must not be empty.";
      return false;
    }

    if (QuicTextUtils::ContainsUpperCase(name)) {
      QUIC_DLOG(ERROR) << "Malformed header: Header name " << name
                       << " contains upper-case characters.";
      return false;
    }

    headers->AppendValueOrAddHeader(name, p.second);
  }

  if (QuicContainsKey(*headers, "content-length") &&
      !ExtractContentLengthFromHeaders(content_length, headers)) {
    return false;
  }

  QUIC_DVLOG(1) << "Successfully parsed headers: " << headers->DebugString();
  return true;
}

bool SpdyUtils::CopyAndValidateTrailers(const QuicHeaderList& header_list,
                                        size_t* final_byte_offset,
                                        SpdyHeaderBlock* trailers) {
  bool found_final_byte_offset = false;
  for (const auto& p : header_list) {
    const std::string& name = p.first;

    // Pull out the final offset pseudo header which indicates the number of
    // response body bytes expected.
    if (!found_final_byte_offset && name == kFinalOffsetHeaderKey &&
        QuicTextUtils::StringToSizeT(p.second, final_byte_offset)) {
      found_final_byte_offset = true;
      continue;
    }

    if (name.empty() || name[0] == ':') {
      QUIC_DLOG(ERROR)
          << "Trailers must not be empty, and must not contain pseudo-"
          << "headers. Found: '" << name << "'";
      return false;
    }

    if (QuicTextUtils::ContainsUpperCase(name)) {
      QUIC_DLOG(ERROR) << "Malformed header: Header name " << name
                       << " contains upper-case characters.";
      return false;
    }

    trailers->AppendValueOrAddHeader(name, p.second);
  }

  if (!found_final_byte_offset) {
    QUIC_DLOG(ERROR) << "Required key '" << kFinalOffsetHeaderKey
                     << "' not present";
    return false;
  }

  // TODO(rjshade): Check for other forbidden keys, following the HTTP/2 spec.

  QUIC_DVLOG(1) << "Successfully parsed Trailers: " << trailers->DebugString();
  return true;
}

// static
std::string SpdyUtils::GetPromisedUrlFromHeaders(
    const SpdyHeaderBlock& headers) {
  // RFC 7540, Section 8.1.2.3: All HTTP/2 requests MUST include exactly
  // one valid value for the ":method", ":scheme", and ":path" pseudo-header
  // fields, unless it is a CONNECT request.

  // RFC 7540, Section  8.2.1:  The header fields in PUSH_PROMISE and any
  // subsequent CONTINUATION frames MUST be a valid and complete set of request
  // header fields (Section 8.1.2.3).  The server MUST include a method in the
  // ":method" pseudo-header field that is safe and cacheable.
  //
  // RFC 7231, Section  4.2.1: Of the request methods defined by this
  // specification, the GET, HEAD, OPTIONS, and TRACE methods are defined to be
  // safe.
  //
  // RFC 7231, Section  4.2.1: ... this specification defines GET, HEAD, and
  // POST as cacheable, ...
  //
  // So the only methods allowed in a PUSH_PROMISE are GET and HEAD.
  SpdyHeaderBlock::const_iterator it = headers.find(":method");
  if (it == headers.end() || (it->second != "GET" && it->second != "HEAD")) {
    return std::string();
  }

  it = headers.find(":scheme");
  if (it == headers.end() || it->second.empty()) {
    return std::string();
  }
  QuicStringPiece scheme = it->second;

  // RFC 7540, Section 8.2: The server MUST include a value in the
  // ":authority" pseudo-header field for which the server is authoritative
  // (see Section 10.1).
  it = headers.find(":authority");
  if (it == headers.end() || it->second.empty()) {
    return std::string();
  }
  QuicStringPiece authority = it->second;

  // RFC 7540, Section 8.1.2.3 requires that the ":path" pseudo-header MUST
  // NOT be empty for "http" or "https" URIs;
  //
  // However, to ensure the scheme is consistently canonicalized, that check
  // is deferred to implementations in QuicUrlUtils::GetPushPromiseUrl().
  it = headers.find(":path");
  if (it == headers.end()) {
    return std::string();
  }
  QuicStringPiece path = it->second;

  return GetPushPromiseUrl(scheme, authority, path);
}

// static
std::string SpdyUtils::GetPromisedHostNameFromHeaders(
    const SpdyHeaderBlock& headers) {
  // TODO(fayang): Consider just checking out the value of the ":authority" key
  // in headers.
  return GURL(GetPromisedUrlFromHeaders(headers)).host();
}

// static
bool SpdyUtils::PromisedUrlIsValid(const SpdyHeaderBlock& headers) {
  std::string url(GetPromisedUrlFromHeaders(headers));
  return !url.empty() && GURL(url).is_valid();
}

// static
bool SpdyUtils::PopulateHeaderBlockFromUrl(const std::string url,
                                           SpdyHeaderBlock* headers) {
  (*headers)[":method"] = "GET";
  size_t pos = url.find("://");
  if (pos == std::string::npos) {
    return false;
  }
  (*headers)[":scheme"] = url.substr(0, pos);
  size_t start = pos + 3;
  pos = url.find("/", start);
  if (pos == std::string::npos) {
    (*headers)[":authority"] = url.substr(start);
    (*headers)[":path"] = "/";
    return true;
  }
  (*headers)[":authority"] = url.substr(start, pos - start);
  (*headers)[":path"] = url.substr(pos);
  return true;
}

// static
std::string SpdyUtils::GetPushPromiseUrl(QuicStringPiece scheme,
                                         QuicStringPiece authority,
                                         QuicStringPiece path) {
  // RFC 7540, Section 8.1.2.3: The ":path" pseudo-header field includes the
  // path and query parts of the target URI (the "path-absolute" production
  // and optionally a '?' character followed by the "query" production (see
  // Sections 3.3 and 3.4 of RFC3986). A request in asterisk form includes the
  // value '*' for the ":path" pseudo-header field.
  //
  // This pseudo-header field MUST NOT be empty for "http" or "https" URIs;
  // "http" or "https" URIs that do not contain a path MUST include a value of
  // '/'. The exception to this rule is an OPTIONS request for an "http" or
  // "https" URI that does not include a path component; these MUST include a
  // ":path" pseudo-header with a value of '*' (see RFC7230, Section 5.3.4).
  //
  // In addition to the above restriction from RFC 7540, note that RFC3986
  // defines the "path-absolute" construction as starting with "/" but not "//".
  //
  // RFC 7540, Section  8.2.1:  The header fields in PUSH_PROMISE and any
  // subsequent CONTINUATION frames MUST be a valid and complete set of request
  // header fields (Section 8.1.2.3).  The server MUST include a method in the
  // ":method" pseudo-header field that is safe and cacheable.
  //
  // RFC 7231, Section  4.2.1:
  // ... this specification defines GET, HEAD, and POST as cacheable, ...
  //
  // Since the OPTIONS method is not cacheable, it cannot be the method of a
  // PUSH_PROMISE. Therefore, the exception mentioned in RFC 7540, Section
  // 8.1.2.3 about OPTIONS requests does not apply here (i.e. ":path" cannot be
  // "*").
  if (path.empty() || path[0] != '/' || (path.size() >= 2 && path[1] == '/')) {
    return std::string();
  }

  // Validate the scheme; this is to ensure a scheme of "foo://bar" is not
  // parsed as a URL of "foo://bar://baz" when combined with a host of "baz".
  std::string canonical_scheme;
  url::StdStringCanonOutput canon_scheme_output(&canonical_scheme);
  url::Component canon_component;
  url::Component scheme_component(0, scheme.size());

  if (!url::CanonicalizeScheme(scheme.data(), scheme_component,
                               &canon_scheme_output, &canon_component) ||
      !canon_component.is_nonempty() || canon_component.begin != 0) {
    return std::string();
  }
  canonical_scheme.resize(canon_component.len + 1);

  // Validate the authority; this is to ensure an authority such as
  // "host/path" is not accepted, as when combined with a scheme like
  // "http://", could result in a URL of "http://host/path".
  url::Component auth_component(0, authority.size());
  url::Component username_component;
  url::Component password_component;
  url::Component host_component;
  url::Component port_component;

  url::ParseAuthority(authority.data(), auth_component, &username_component,
                      &password_component, &host_component, &port_component);

  // RFC 7540, Section 8.1.2.3: The authority MUST NOT include the deprecated
  // "userinfo" subcomponent for "http" or "https" schemed URIs.
  //
  // Note: Although |canonical_scheme| has not yet been checked for that, as
  // it is performed later in processing, only "http" and "https" schemed
  // URIs are supported for PUSH.
  if (username_component.is_valid() || password_component.is_valid()) {
    return std::string();
  }

  // Failed parsing or no host present. ParseAuthority() will ensure that
  // host_component + port_component cover the entire string, if
  // username_component and password_component are not present.
  if (!host_component.is_nonempty()) {
    return std::string();
  }

  // Validate the port (if present; it's optional).
  int parsed_port_number = url::PORT_INVALID;
  if (port_component.is_nonempty()) {
    parsed_port_number = url::ParsePort(authority.data(), port_component);
    if (parsed_port_number < 0 && parsed_port_number != url::PORT_UNSPECIFIED) {
      return std::string();
    }
  }

  // Validate the host by attempting to canonicalize it. Invalid characters
  // will result in a canonicalization failure (e.g. '/')
  std::string canon_host;
  url::StdStringCanonOutput canon_host_output(&canon_host);
  canon_component.reset();
  if (!url::CanonicalizeHost(authority.data(), host_component,
                             &canon_host_output, &canon_component) ||
      !canon_component.is_nonempty() || canon_component.begin != 0) {
    return std::string();
  }

  // At this point, "authority" has been validated to either be of the form
  // 'host:port' or 'host', with 'host' being a valid domain or IP address,
  // and 'port' (if present), being a valid port. Attempt to construct a
  // URL of just the (scheme, host, port), which should be safe and will not
  // result in ambiguous parsing.
  //
  // This also enforces that all PUSHed URLs are either HTTP or HTTPS-schemed
  // URIs, consistent with the other restrictions enforced above.
  //
  // Note: url::CanonicalizeScheme() will have added the ':' to
  // |canonical_scheme|.
  GURL origin_url(canonical_scheme + "//" + std::string(authority));
  if (!origin_url.is_valid() || !origin_url.SchemeIsHTTPOrHTTPS() ||
      // The following checks are merely defense in depth.
      origin_url.has_username() || origin_url.has_password() ||
      (origin_url.has_path() && origin_url.path_piece() != "/") ||
      origin_url.has_query() || origin_url.has_ref()) {
    return std::string();
  }

  // Attempt to parse the path.
  std::string spec = origin_url.GetWithEmptyPath().spec();
  spec.pop_back();  // Remove the '/', as ":path" must contain it.
  spec.append(std::string(path));

  // Attempt to parse the full URL, with the path as well. Ensure there is no
  // fragment to the query.
  GURL full_url(spec);
  if (!full_url.is_valid() || full_url.has_ref()) {
    return std::string();
  }

  return full_url.spec();
}

}  // namespace quic
