// Copyright 2018 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/dom/base64.h"

#include "base/base64.h"

namespace cobalt {
namespace dom {

namespace {
// https://infra.spec.whatwg.org/#ascii-whitespace
const char kAsciiWhitespace[] = {0x09, 0x0a, 0x0c, 0x0d, 0x20};

bool IsAtobAllowedChar(char c) {
  // atob() allows '+', '/', and ASCII alphanumeric characters.
  // https://infra.spec.whatwg.org/#forgiving-base64-decode
  if (c == '+') {
    return true;
  }
  if (c < '/') {
    return false;
  }
  if (c <= '9') {
    return true;
  }
  if (c < 'A') {
    return false;
  }
  if (c <= 'Z') {
    return true;
  }
  if (c < 'a') {
    return false;
  }
  if (c <= 'z') {
    return true;
  }
  return false;
}

bool IsNotAsciiWhitespace(char c) {
  for (char sp_char : kAsciiWhitespace) {
    if (c == sp_char) {
      return false;
    }
  }
  return true;
}

base::optional<std::string> GetAtobAllowedStr(const std::string& input_str) {
  // Our base64 decoding method does not check for forbidden characters. We use
  // the following method to reject string containing disallowed character or
  // format in atob().
  // Step 1-4 of https://infra.spec.whatwg.org/#forgiving-base64-decode
  std::string output_str;
  // Step 1: Remove all ASCII whitespace from data.
  std::copy_if(input_str.begin(), input_str.end(),
               std::back_inserter(output_str), IsNotAsciiWhitespace);
  // Step 2: If data's length divides by 4 leaving no remainder, then:
  //        1. if data ends with one or two U+003D (=) code points, then
  //           remove them from data.
  if (!output_str.empty() && output_str.length() % 4 == 0 &&
      output_str.back() == '=') {
    output_str.pop_back();
    if (output_str.back() == '=') {
      output_str.pop_back();
    }
  }
  // Step 3: If data's length divides by 4 leaving a remainder of 1, return
  // failure.
  if (output_str.length() % 4 == 1) {
    return base::nullopt;
  }
  // Step 4: If data contains a code point that is not allowed, return failure.
  for (char current_char : output_str) {
    if (!IsAtobAllowedChar(current_char)) {
      return base::nullopt;
    }
  }
  // Customized step: add padding to string less than 4 character.
  for (size_t i = output_str.length() % 4; i > 1 && i < 4; i++) {
    output_str.push_back('=');
  }
  return output_str;
}

base::optional<std::string> Utf8ToLatin1(const std::string& input) {
  std::string output;
  unsigned char current_char_remainder = 0x00;
  for (unsigned char c : input) {
    if (c <= 0x7f && !current_char_remainder) {
      output.push_back(c);
    } else if (c <= 0xbf && current_char_remainder) {
      // This is the only byte or second byte of one character.
      output.push_back(current_char_remainder | (c & 0x3f));
      current_char_remainder = 0x00;
    } else if (c == 0xc2 && !current_char_remainder) {
      current_char_remainder = c & 0x80;
    } else if (c == 0xc3 && !current_char_remainder) {
      current_char_remainder = 0xc0;
    } else {
      return base::nullopt;
    }
  }
  return output;
}
}  // namespace

base::optional<std::string> ForgivingBase64Encode(
    const std::string& string_to_encode) {
  // https://infra.spec.whatwg.org/#forgiving-base64-encode
  auto maybe_string_to_encode_in_latin1 = Utf8ToLatin1(string_to_encode);
  std::string output;
  if (!maybe_string_to_encode_in_latin1 ||
      !base::Base64Encode(*maybe_string_to_encode_in_latin1, &output)) {
    return base::nullopt;
  }
  return output;
}

base::optional<std::vector<uint8_t>> ForgivingBase64Decode(
    const std::string& encoded_string) {
  // https://infra.spec.whatwg.org/#forgiving-base64-decode
  // Step 1-4:
  auto maybe_encoded_string_no_whitespace = GetAtobAllowedStr(encoded_string);
  // Step 5-10:
  std::vector<uint8_t> output;
  // If input string format is not allowed or base64 encoding failed, return
  // nullopt to signal failure.
  if (!maybe_encoded_string_no_whitespace ||
      !base::Base64Decode(*maybe_encoded_string_no_whitespace, &output)) {
    return base::nullopt;
  }
  return output;
}

}  // namespace dom
}  // namespace cobalt
