// 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
