// Copyright (c) 2012 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/spdy/spdy_http_utils.h"

#include <string>

#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
#include "net/base/escape.h"
#include "net/base/load_flags.h"
#include "net/base/net_util.h"
#include "net/http/http_request_headers.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
#include "net/http/http_util.h"

namespace net {

bool SpdyHeadersToHttpResponse(const SpdyHeaderBlock& headers,
                               SpdyMajorVersion protocol_version,
                               HttpResponseInfo* response) {
  std::string status_key = (protocol_version >= SPDY3) ? ":status" : "status";
  std::string version_key =
      (protocol_version >= SPDY3) ? ":version" : "version";
  std::string version;
  std::string status;

  // The "status" and "version" headers are required.
  SpdyHeaderBlock::const_iterator it;
  it = headers.find(status_key);
  if (it == headers.end())
    return false;
  status = it->second;

  it = headers.find(version_key);
  if (it == headers.end())
    return false;
  version = it->second;

  std::string raw_headers(version);
  raw_headers.push_back(' ');
  raw_headers.append(status);
  raw_headers.push_back('\0');
  for (it = headers.begin(); it != headers.end(); ++it) {
    // For each value, if the server sends a NUL-separated
    // list of values, we separate that back out into
    // individual headers for each value in the list.
    // e.g.
    //    Set-Cookie "foo\0bar"
    // becomes
    //    Set-Cookie: foo\0
    //    Set-Cookie: bar\0
    std::string value = it->second;
    size_t start = 0;
    size_t end = 0;
    do {
      end = value.find('\0', start);
      std::string tval;
      if (end != value.npos)
        tval = value.substr(start, (end - start));
      else
        tval = value.substr(start);
      if (protocol_version >= 3 && it->first[0] == ':')
        raw_headers.append(it->first.substr(1));
      else
        raw_headers.append(it->first);
      raw_headers.push_back(':');
      raw_headers.append(tval);
      raw_headers.push_back('\0');
      start = end + 1;
    } while (end != value.npos);
  }

  response->headers = new HttpResponseHeaders(raw_headers);
  response->was_fetched_via_spdy = true;
  return true;
}

void CreateSpdyHeadersFromHttpRequest(const HttpRequestInfo& info,
                                      const HttpRequestHeaders& request_headers,
                                      SpdyHeaderBlock* headers,
                                      SpdyMajorVersion protocol_version,
                                      bool direct) {

  HttpRequestHeaders::Iterator it(request_headers);
  while (it.GetNext()) {
    std::string name = StringToLowerASCII(it.name());
    if (name == "connection" || name == "proxy-connection" ||
        name == "transfer-encoding") {
      continue;
    }
    if (headers->find(name) == headers->end()) {
      (*headers)[name] = it.value();
    } else {
      std::string new_value = (*headers)[name];
      new_value.append(1, '\0');  // +=() doesn't append 0's
      new_value += it.value();
      (*headers)[name] = new_value;
    }
  }
  static const char kHttpProtocolVersion[] = "HTTP/1.1";

  if (protocol_version < SPDY3) {
    (*headers)["version"] = kHttpProtocolVersion;
    (*headers)["method"] = info.method;
    (*headers)["host"] = GetHostAndOptionalPort(info.url);
    (*headers)["scheme"] = info.url.scheme();
    if (direct)
      (*headers)["url"] = HttpUtil::PathForRequest(info.url);
    else
      (*headers)["url"] = HttpUtil::SpecForRequest(info.url);
  } else {
    (*headers)[":version"] = kHttpProtocolVersion;
    (*headers)[":method"] = info.method;
    (*headers)[":host"] = GetHostAndOptionalPort(info.url);
    (*headers)[":scheme"] = info.url.scheme();
    (*headers)[":path"] = HttpUtil::PathForRequest(info.url);
    headers->erase("host"); // this is kinda insane, spdy 3 spec.
  }

}

COMPILE_ASSERT(HIGHEST - LOWEST < 4 &&
               HIGHEST - MINIMUM_PRIORITY < 5,
               request_priority_incompatible_with_spdy);

SpdyPriority ConvertRequestPriorityToSpdyPriority(
    const RequestPriority priority,
    SpdyMajorVersion protocol_version) {
  DCHECK_GE(priority, MINIMUM_PRIORITY);
  DCHECK_LE(priority, MAXIMUM_PRIORITY);
  if (protocol_version == SPDY2) {
    // SPDY 2 only has 2 bits of priority, but we have 5 RequestPriorities.
    // Map IDLE => 3, LOWEST => 2, LOW => 2, MEDIUM => 1, HIGHEST => 0.
    if (priority > LOWEST) {
      return static_cast<SpdyPriority>(HIGHEST - priority);
    } else {
      return static_cast<SpdyPriority>(HIGHEST - priority - 1);
    }
  } else {
    return static_cast<SpdyPriority>(HIGHEST - priority);
  }
}

NET_EXPORT_PRIVATE RequestPriority ConvertSpdyPriorityToRequestPriority(
    SpdyPriority priority,
    SpdyMajorVersion protocol_version) {
  // Handle invalid values gracefully, and pick LOW to map 2 back
  // to for SPDY/2.
  SpdyPriority idle_cutoff = (protocol_version == SPDY2) ? 3 : 5;
  return (priority >= idle_cutoff) ?
      IDLE : static_cast<RequestPriority>(HIGHEST - priority);
}

GURL GetUrlFromHeaderBlock(const SpdyHeaderBlock& headers,
                           SpdyMajorVersion protocol_version,
                           bool pushed) {
  // SPDY 2 server push urls are specified in a single "url" header.
  if (pushed && protocol_version == SPDY2) {
      std::string url;
      SpdyHeaderBlock::const_iterator it;
      it = headers.find("url");
      if (it != headers.end())
        url = it->second;
      return GURL(url);
  }

  const char* scheme_header = protocol_version >= SPDY3 ? ":scheme" : "scheme";
  const char* host_header = protocol_version >= SPDY3 ? ":host" : "host";
  const char* path_header = protocol_version >= SPDY3 ? ":path" : "url";

  std::string scheme;
  std::string host_port;
  std::string path;
  SpdyHeaderBlock::const_iterator it;
  it = headers.find(scheme_header);
  if (it != headers.end())
    scheme = it->second;
  it = headers.find(host_header);
  if (it != headers.end())
    host_port = it->second;
  it = headers.find(path_header);
  if (it != headers.end())
    path = it->second;

  std::string url = (scheme.empty() || host_port.empty() || path.empty())
                        ? std::string()
                        : scheme + "://" + host_port + path;
  return GURL(url);
}

bool ShouldShowHttpHeaderValue(const std::string& header_name) {
#if defined(SPDY_PROXY_AUTH_ORIGIN)
  if (header_name == "proxy-authorization")
    return false;
#endif
  return true;
}

}  // namespace net
