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

#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) {
    return base::nullopt;
  }
  base::Base64Encode(*maybe_string_to_encode_in_latin1, &output);
  if (!output.length() && maybe_string_to_encode_in_latin1->length()) {
    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
