// Copyright 2006 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#ifdef HAVE_CONFIG_H
#include <config.h>  // Must come first
#endif

#include <assert.h>

// Disable exception handler warnings.
#pragma warning(disable:4530)

#include <fstream>
#include <vector>

#include "common/windows/string_utils-inl.h"

#include "common/windows/http_upload.h"

namespace {
  using std::string;
  using std::wstring;
  using std::map;
  using std::vector;
  using std::ifstream;
  using std::ios;

  const wchar_t kUserAgent[] = L"Breakpad/1.0 (Windows)";

  // Helper class which closes an internet handle when it goes away
  class AutoInternetHandle {
  public:
    explicit AutoInternetHandle(HINTERNET handle) : handle_(handle) {}
    ~AutoInternetHandle() {
      if (handle_) {
        InternetCloseHandle(handle_);
      }
    }

    HINTERNET get() { return handle_; }

  private:
    HINTERNET handle_;
  };

  wstring UTF8ToWide(const string& utf8) {
    if (utf8.length() == 0) {
      return wstring();
    }

    // compute the length of the buffer we'll need
    int charcount = MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, NULL, 0);

    if (charcount == 0) {
      return wstring();
    }

    // convert
    wchar_t* buf = new wchar_t[charcount];
    MultiByteToWideChar(CP_UTF8, 0, utf8.c_str(), -1, buf, charcount);
    wstring result(buf);
    delete[] buf;
    return result;
  }

  string WideToMBCP(const wstring& wide, unsigned int cp) {
    if (wide.length() == 0) {
      return string();
    }

    // compute the length of the buffer we'll need
    int charcount = WideCharToMultiByte(cp, 0, wide.c_str(), -1,
        NULL, 0, NULL, NULL);
    if (charcount == 0) {
      return string();
    }

    // convert
    char *buf = new char[charcount];
    WideCharToMultiByte(cp, 0, wide.c_str(), -1, buf, charcount,
        NULL, NULL);

    string result(buf);
    delete[] buf;
    return result;
  }

  bool GetFileContents(const wstring& filename, vector<char>* contents) {
    bool rv = false;
    // The "open" method on pre-MSVC8 ifstream implementations doesn't accept a
    // wchar_t* filename, so use _wfopen directly in that case.  For VC8 and
    // later, _wfopen has been deprecated in favor of _wfopen_s, which does
    // not exist in earlier versions, so let the ifstream open the file itself.
    // GCC doesn't support wide file name and opening on FILE* requires ugly
    // hacks, so fallback to multi byte file.
#ifdef _MSC_VER
    ifstream file;
    file.open(filename.c_str(), ios::binary);
#else // GCC
    ifstream file(WideToMBCP(filename, CP_ACP).c_str(), ios::binary);
#endif  // _MSC_VER >= 1400
    if (file.is_open()) {
      file.seekg(0, ios::end);
      std::streamoff length = file.tellg();
      // Check for loss of data when converting lenght from std::streamoff into
      // std::vector<char>::size_type
      std::vector<char>::size_type vector_size =
        static_cast<std::vector<char>::size_type>(length);
      if (static_cast<std::streamoff>(vector_size) == length) {
        contents->resize(vector_size);
        if (length != 0) {
          file.seekg(0, ios::beg);
          file.read(&((*contents)[0]), length);
        }
        rv = true;
      }
      file.close();
    }
    return rv;
  }

  bool CheckParameters(const map<wstring, wstring>& parameters) {
    for (map<wstring, wstring>::const_iterator pos = parameters.begin();
          pos != parameters.end(); ++pos) {
      const wstring& str = pos->first;
      if (str.size() == 0) {
        return false;  // disallow empty parameter names
      }
      for (unsigned int i = 0; i < str.size(); ++i) {
        wchar_t c = str[i];
        if (c < 32 || c == '"' || c > 127) {
          return false;
        }
      }
    }
    return true;
  }

  // Converts a UTF16 string to UTF8.
  string WideToUTF8(const wstring& wide) {
    return WideToMBCP(wide, CP_UTF8);
  }

  bool ReadResponse(HINTERNET request, wstring *response) {
    bool has_content_length_header = false;
    wchar_t content_length[32];
    DWORD content_length_size = sizeof(content_length);
    DWORD claimed_size = 0;
    string response_body;

    if (HttpQueryInfo(request, HTTP_QUERY_CONTENT_LENGTH,
        static_cast<LPVOID>(&content_length),
        &content_length_size, 0)) {
      has_content_length_header = true;
      claimed_size = wcstol(content_length, NULL, 10);
      response_body.reserve(claimed_size);
    }

    DWORD bytes_available;
    DWORD total_read = 0;
    BOOL return_code;

    while (((return_code = InternetQueryDataAvailable(request, &bytes_available,
        0, 0)) != 0) && bytes_available > 0) {
      vector<char> response_buffer(bytes_available);
      DWORD size_read;

      return_code = InternetReadFile(request,
          &response_buffer[0],
          bytes_available, &size_read);

      if (return_code && size_read > 0) {
        total_read += size_read;
        response_body.append(&response_buffer[0], size_read);
      }
      else {
        break;
      }
    }

    bool succeeded = return_code && (!has_content_length_header ||
        (total_read == claimed_size));
    if (succeeded && response) {
      *response = UTF8ToWide(response_body);
    }

    return succeeded;
  }

  bool SendRequestInner(
      const wstring& url,
      const wstring& http_method,
      const wstring& content_type_header,
      const string& request_body,
      int* timeout_ms,
      wstring* response_body,
      int* response_code) {
    if (response_code) {
      *response_code = 0;
    }

    // Break up the URL and make sure we can handle it
    wchar_t scheme[16], host[256], path[1024];
    URL_COMPONENTS components;
    memset(&components, 0, sizeof(components));
    components.dwStructSize = sizeof(components);
    components.lpszScheme = scheme;
    components.dwSchemeLength = sizeof(scheme) / sizeof(scheme[0]);
    components.lpszHostName = host;
    components.dwHostNameLength = sizeof(host) / sizeof(host[0]);
    components.lpszUrlPath = path;
    components.dwUrlPathLength = sizeof(path) / sizeof(path[0]);
    if (!InternetCrackUrl(url.c_str(), static_cast<DWORD>(url.size()),
        0, &components)) {
      DWORD err = GetLastError();
      wprintf(L"%d\n", err);
      return false;
    }
    bool secure = false;
    if (wcscmp(scheme, L"https") == 0) {
      secure = true;
    }
    else if (wcscmp(scheme, L"http") != 0) {
      return false;
    }

    AutoInternetHandle internet(InternetOpen(kUserAgent,
        INTERNET_OPEN_TYPE_PRECONFIG,
        NULL,  // proxy name
        NULL,  // proxy bypass
        0));   // flags
    if (!internet.get()) {
      return false;
    }

    AutoInternetHandle connection(InternetConnect(internet.get(),
        host,
        components.nPort,
        NULL,    // user name
        NULL,    // password
        INTERNET_SERVICE_HTTP,
        0,       // flags
        0));  // context
    if (!connection.get()) {
      return false;
    }

    DWORD http_open_flags = secure ? INTERNET_FLAG_SECURE : 0;
    http_open_flags |= INTERNET_FLAG_NO_COOKIES;
    AutoInternetHandle request(HttpOpenRequest(connection.get(),
        http_method.c_str(),
        path,
        NULL,    // version
        NULL,    // referer
        NULL,    // agent type
        http_open_flags,
        0));  // context
    if (!request.get()) {
      return false;
    }

    if (!content_type_header.empty()) {
      HttpAddRequestHeaders(request.get(),
          content_type_header.c_str(),
          static_cast<DWORD>(-1),
          HTTP_ADDREQ_FLAG_ADD);
    }

    if (timeout_ms) {
      if (!InternetSetOption(request.get(),
          INTERNET_OPTION_SEND_TIMEOUT,
          timeout_ms,
          sizeof(*timeout_ms))) {
        fwprintf(stderr, L"Could not unset send timeout, continuing...\n");
      }

      if (!InternetSetOption(request.get(),
          INTERNET_OPTION_RECEIVE_TIMEOUT,
          timeout_ms,
          sizeof(*timeout_ms))) {
        fwprintf(stderr, L"Could not unset receive timeout, continuing...\n");
      }
    }

    if (!HttpSendRequest(request.get(), NULL, 0,
        const_cast<char*>(request_body.data()),
        static_cast<DWORD>(request_body.size()))) {
      return false;
    }

    // The server indicates a successful upload with HTTP status 200.
    wchar_t http_status[4];
    DWORD http_status_size = sizeof(http_status);
    if (!HttpQueryInfo(request.get(), HTTP_QUERY_STATUS_CODE,
        static_cast<LPVOID>(&http_status), &http_status_size,
        0)) {
      return false;
    }

    int http_response = wcstol(http_status, NULL, 10);
    if (response_code) {
      *response_code = http_response;
    }

    bool result = (http_response == 200);

    if (result) {
      result = ReadResponse(request.get(), response_body);
    }

    return result;
  }

  wstring GenerateMultipartBoundary() {
    // The boundary has 27 '-' characters followed by 16 hex digits
    static const wchar_t kBoundaryPrefix[] = L"---------------------------";
    static const int kBoundaryLength = 27 + 16 + 1;

    // Generate some random numbers to fill out the boundary
    int r0 = rand();
    int r1 = rand();

    wchar_t temp[kBoundaryLength];
    swprintf(temp, kBoundaryLength, L"%s%08X%08X", kBoundaryPrefix, r0, r1);

    // remove when VC++7.1 is no longer supported
    temp[kBoundaryLength - 1] = L'\0';

    return wstring(temp);
  }

  wstring GenerateMultipartPostRequestHeader(const wstring& boundary) {
    wstring header = L"Content-Type: multipart/form-data; boundary=";
    header += boundary;
    return header;
  }

  bool AppendFileToRequestBody(const wstring& file_part_name,
                               const wstring& filename,
                               string* request_body,
                               bool set_content_type = true) {
    string file_part_name_utf8 = WideToUTF8(file_part_name);
    if (file_part_name_utf8.empty()) {
      return false;
    }

    string filename_utf8 = WideToUTF8(filename);
    if (filename_utf8.empty()) {
      return false;
    }

    if (set_content_type) {
      request_body->append(
          "Content-Disposition: form-data; "
          "name=\"" +
          file_part_name_utf8 +
          "\"; "
          "filename=\"" +
          filename_utf8 + "\"\r\n");
      request_body->append("Content-Type: application/octet-stream\r\n");
      request_body->append("\r\n");
    }

    vector<char> contents;
    if (!GetFileContents(filename, &contents)) {
      return false;
    }

    if (!contents.empty()) {
      request_body->append(&(contents[0]), contents.size());
    }

    return true;
  }

  bool GenerateRequestBody(const map<wstring, wstring>& parameters,
      const map<wstring, wstring>& files,
      const wstring& boundary,
      string *request_body) {
    string boundary_str = WideToUTF8(boundary);
    if (boundary_str.empty()) {
      return false;
    }

    request_body->clear();

    // Append each of the parameter pairs as a form-data part
    for (map<wstring, wstring>::const_iterator pos = parameters.begin();
        pos != parameters.end(); ++pos) {
      request_body->append("--" + boundary_str + "\r\n");
      request_body->append("Content-Disposition: form-data; name=\"" +
          WideToUTF8(pos->first) + "\"\r\n\r\n" +
          WideToUTF8(pos->second) + "\r\n");
    }

    // Now append each upload file as a binary (octet-stream) part
    for (map<wstring, wstring>::const_iterator pos = files.begin();
        pos != files.end(); ++pos) {
      request_body->append("--" + boundary_str + "\r\n");

      if (!AppendFileToRequestBody(pos->first, pos->second, request_body)) {
        return false;
      }
    }
    request_body->append("--" + boundary_str + "--\r\n");
    return true;
  }
}

namespace google_breakpad {
  bool HTTPUpload::SendPutRequest(
      const wstring& url,
      const wstring& path,
      int* timeout_ms,
      wstring* response_body,
      int* response_code) {
    string request_body;
    // Turn off content-type in the body. If content-type is set then binary
    // files uploaded to GCS end up with the it prepended to the file
    // contents.
    if (!AppendFileToRequestBody(L"symbol_file", path, &request_body,
                                 /*set_content_type=*/false)) {
      return false;
    }

    return SendRequestInner(
        url,
        L"PUT",
        L"",
        request_body,
        timeout_ms,
        response_body,
        response_code);
  }

  bool HTTPUpload::SendGetRequest(
      const wstring& url,
      int* timeout_ms,
      wstring* response_body,
      int* response_code) {
    return SendRequestInner(
        url,
        L"GET",
        L"",
        "",
        timeout_ms,
        response_body,
        response_code);
  }

  bool HTTPUpload::SendMultipartPostRequest(
      const wstring& url,
      const map<wstring, wstring>& parameters,
      const map<wstring, wstring>& files,
      int* timeout_ms,
      wstring* response_body,
      int* response_code) {
    // TODO(bryner): support non-ASCII parameter names
    if (!CheckParameters(parameters)) {
      return false;
    }

    wstring boundary = GenerateMultipartBoundary();
    wstring content_type_header = GenerateMultipartPostRequestHeader(boundary);

    string request_body;
    if (!GenerateRequestBody(parameters, files, boundary, &request_body)) {
      return false;
    }

    return SendRequestInner(
        url,
        L"POST",
        content_type_header,
        request_body,
        timeout_ms,
        response_body,
        response_code);
  }

  bool HTTPUpload::SendSimplePostRequest(
      const wstring& url,
      const wstring& body,
      const wstring& content_type,
      int *timeout_ms,
      wstring *response_body,
      int *response_code) {
    return SendRequestInner(
        url,
        L"POST",
        content_type,
        WideToUTF8(body),
        timeout_ms,
        response_body,
        response_code);
  }
}  // namespace google_breakpad
