// Copyright 2014 The Chromium OS 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 <brillo/http/http_form_data.h>

#include <limits>
#include <utility>

#include <base/format_macros.h>
#include <base/rand_util.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>

#include <brillo/errors/error_codes.h>
#include <brillo/http/http_transport.h>
#include <brillo/mime_utils.h>
#include <brillo/streams/file_stream.h>
#include <brillo/streams/input_stream_set.h>
#include <brillo/streams/memory_stream.h>

namespace brillo {
namespace http {

namespace form_header {
const char kContentDisposition[] = "Content-Disposition";
const char kContentTransferEncoding[] = "Content-Transfer-Encoding";
const char kContentType[] = "Content-Type";
}  // namespace form_header

const char content_disposition::kFile[] = "file";
const char content_disposition::kFormData[] = "form-data";

FormField::FormField(const std::string& name,
                     const std::string& content_disposition,
                     const std::string& content_type,
                     const std::string& transfer_encoding)
    : name_{name},
      content_disposition_{content_disposition},
      content_type_{content_type},
      transfer_encoding_{transfer_encoding} {}

std::string FormField::GetContentDisposition() const {
  std::string disposition = content_disposition_;
  if (!name_.empty())
    base::StringAppendF(&disposition, "; name=\"%s\"", name_.c_str());
  return disposition;
}

std::string FormField::GetContentType() const {
  return content_type_;
}

std::string FormField::GetContentHeader() const {
  HeaderList headers{
      {form_header::kContentDisposition, GetContentDisposition()}};

  if (!content_type_.empty())
    headers.emplace_back(form_header::kContentType, GetContentType());

  if (!transfer_encoding_.empty()) {
    headers.emplace_back(form_header::kContentTransferEncoding,
                         transfer_encoding_);
  }

  std::string result;
  for (const auto& pair : headers) {
    base::StringAppendF(&result, "%s: %s\r\n", pair.first.c_str(),
                        pair.second.c_str());
  }
  result += "\r\n";
  return result;
}

TextFormField::TextFormField(const std::string& name,
                             const std::string& data,
                             const std::string& content_type,
                             const std::string& transfer_encoding)
    : FormField{name, content_disposition::kFormData, content_type,
                transfer_encoding},
      data_{data} {}

bool TextFormField::ExtractDataStreams(std::vector<StreamPtr>* streams) {
  streams->push_back(MemoryStream::OpenCopyOf(data_, nullptr));
  return true;
}

FileFormField::FileFormField(const std::string& name,
                             StreamPtr stream,
                             const std::string& file_name,
                             const std::string& content_disposition,
                             const std::string& content_type,
                             const std::string& transfer_encoding)
    : FormField{name, content_disposition, content_type, transfer_encoding},
      stream_{std::move(stream)},
      file_name_{file_name} {}

std::string FileFormField::GetContentDisposition() const {
  std::string disposition = FormField::GetContentDisposition();
  base::StringAppendF(&disposition, "; filename=\"%s\"", file_name_.c_str());
  return disposition;
}

bool FileFormField::ExtractDataStreams(std::vector<StreamPtr>* streams) {
  if (!stream_)
    return false;
  streams->push_back(std::move(stream_));
  return true;
}

MultiPartFormField::MultiPartFormField(const std::string& name,
                                       const std::string& content_type,
                                       const std::string& boundary)
    : FormField{name,
                content_disposition::kFormData,
                content_type.empty() ? mime::multipart::kMixed : content_type,
                {}},
      boundary_{boundary} {
  if (boundary_.empty())
    boundary_ = base::StringPrintf("%016" PRIx64, base::RandUint64());
}

bool MultiPartFormField::ExtractDataStreams(std::vector<StreamPtr>* streams) {
  for (auto& part : parts_) {
    std::string data = GetBoundaryStart() + part->GetContentHeader();
    streams->push_back(MemoryStream::OpenCopyOf(data, nullptr));
    if (!part->ExtractDataStreams(streams))
      return false;

    streams->push_back(MemoryStream::OpenRef("\r\n", nullptr));
  }
  if (!parts_.empty()) {
    std::string data = GetBoundaryEnd();
    streams->push_back(MemoryStream::OpenCopyOf(data, nullptr));
  }
  return true;
}

std::string MultiPartFormField::GetContentType() const {
  // Quote the boundary only if it has non-alphanumeric chars in it.
  // https://www.w3.org/Protocols/rfc1341/7_2_Multipart.html
  bool use_quotes = false;
  for (auto ch : boundary_) {
    if (!base::IsAsciiAlpha(ch) && !base::IsAsciiDigit(ch)) {
      use_quotes = true;
      break;
    }
  }
  return base::StringPrintf(
      use_quotes ? "%s; boundary=\"%s\"" : "%s; boundary=%s",
      content_type_.c_str(), boundary_.c_str());
}

void MultiPartFormField::AddCustomField(std::unique_ptr<FormField> field) {
  parts_.push_back(std::move(field));
}

void MultiPartFormField::AddTextField(const std::string& name,
                                      const std::string& data) {
  AddCustomField(std::unique_ptr<FormField>{new TextFormField{name, data}});
}

bool MultiPartFormField::AddFileField(const std::string& name,
                                      const base::FilePath& file_path,
                                      const std::string& content_disposition,
                                      const std::string& content_type,
                                      brillo::ErrorPtr* error) {
  StreamPtr stream =
      FileStream::Open(file_path, Stream::AccessMode::READ,
                       FileStream::Disposition::OPEN_EXISTING, error);
  if (!stream)
    return false;
  std::string file_name = file_path.BaseName().value();
  std::unique_ptr<FormField> file_field{
      new FileFormField{name, std::move(stream), file_name, content_disposition,
                        content_type, "binary"}};
  AddCustomField(std::move(file_field));
  return true;
}

std::string MultiPartFormField::GetBoundaryStart() const {
  return base::StringPrintf("--%s\r\n", boundary_.c_str());
}

std::string MultiPartFormField::GetBoundaryEnd() const {
  return base::StringPrintf("--%s--\r\n", boundary_.c_str());
}

FormData::FormData() : FormData{std::string{}} {}

FormData::FormData(const std::string& boundary)
    : form_data_{"", mime::multipart::kFormData, boundary} {}

void FormData::AddCustomField(std::unique_ptr<FormField> field) {
  form_data_.AddCustomField(std::move(field));
}

void FormData::AddTextField(const std::string& name, const std::string& data) {
  form_data_.AddTextField(name, data);
}

bool FormData::AddFileField(const std::string& name,
                            const base::FilePath& file_path,
                            const std::string& content_type,
                            brillo::ErrorPtr* error) {
  return form_data_.AddFileField(
      name, file_path, content_disposition::kFormData, content_type, error);
}

std::string FormData::GetContentType() const {
  return form_data_.GetContentType();
}

StreamPtr FormData::ExtractDataStream() {
  std::vector<StreamPtr> source_streams;
  if (form_data_.ExtractDataStreams(&source_streams))
    return InputStreamSet::Create(std::move(source_streams), nullptr);
  return {};
}

}  // namespace http
}  // namespace brillo
