// Copyright 2018 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 "shill/key_file_store.h"

#include <list>
#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include <base/check.h>
#include <base/check_op.h>
#include <base/files/file_util.h>
#include <base/files/important_file_writer.h>
#include <base/optional.h>
#include <base/stl_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_split.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <brillo/scoped_umask.h>
#include <fcntl.h>
#include <re2/re2.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include "shill/key_value_store.h"
#include "shill/logging.h"

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kStorage;
static std::string ObjectID(const KeyFileStore* k) {
  return "(key_file_store)";
}
}  // namespace Logging

namespace {

// GLib uses the semicolon for separating lists, but it is configurable,
// so we don't want to hardcode it around this file.
constexpr char kListSeparator = ';';

std::string Escape(const std::string& str, base::Optional<char> separator) {
  std::string out;
  bool leading_space = true;
  for (const char c : str) {
    switch (c) {
      case ' ':
        if (leading_space) {
          out += "\\s";
        } else {
          out += ' ';
        }
        break;
      case '\t':
        if (leading_space) {
          out += "\\t";
        } else {
          out += '\t';
        }
        break;
      case '\n':
        out += "\\n";
        break;
      case '\r':
        out += "\\r";
        break;
      case '\\':
        out += "\\\\";
        leading_space = false;
        break;
      default:
        if (separator.has_value() && c == separator.value()) {
          out += "\\";
          out += c;
          leading_space = true;
        } else {
          out += c;
          leading_space = false;
        }
        break;
    }
  }
  return out;
}

bool Unescape(const std::string& str,
              base::Optional<char> separator,
              std::vector<std::string>* out) {
  DCHECK(out);
  out->clear();
  std::string current;
  bool escaping = false;
  for (const char c : str) {
    if (escaping) {
      switch (c) {
        case 's':
          current += ' ';
          break;
        case 't':
          current += '\t';
          break;
        case 'n':
          current += '\n';
          break;
        case 'r':
          current += '\r';
          break;
        default:
          current += c;
          break;
      }
      escaping = false;
      continue;
    }

    if (c == '\\') {
      escaping = true;
      continue;
    }

    if (separator.has_value() && c == separator.value()) {
      out->push_back(current);
      current.clear();
      continue;
    }

    current += c;
  }

  if (escaping) {
    LOG(ERROR) << "Unterminated escape sequence in \"" << str << "\"";
    return false;
  }
  // If we are parsing a list and the current string is empty, then the last
  // character was either a separator (closing off a list item) or the entire
  // list is empty. In this case, we don't add an element.
  // Otherwise, we are parsing not as as list, in which case |current| holds
  // the whole value, or we've started to parse a value but it is technically
  // unterminated, which glib still accepts. In those cases, we add to the
  // output.
  if (!separator.has_value() || !current.empty()) {
    out->push_back(current);
  }
  return true;
}

using KeyValuePair = std::pair<std::string, std::string>;
bool IsBlankComment(const KeyValuePair& kv) {
  return kv.first.empty() && kv.second.empty();
}

class Group {
 public:
  explicit Group(const std::string& name) : name_(name) {}
  Group(const Group&) = delete;
  Group& operator=(const Group&) = delete;

  void Set(const std::string& key, const std::string& value) {
    if (index_.count(key) > 0) {
      index_[key]->second = value;
      return;
    }

    entries_.push_back({key, value});
    index_[key] = &entries_.back();
  }

  base::Optional<std::string> Get(const std::string& key) const {
    const auto it = index_.find(key);
    if (it == index_.end()) {
      return base::nullopt;
    }

    return it->second->second;
  }

  bool Delete(const std::string& key) {
    const auto it = index_.find(key);
    if (it == index_.end()) {
      return false;
    }

    KeyValuePair* pair = it->second;
    index_.erase(it);
    base::Erase(entries_, *pair);
    return true;
  }

  // Comment lines are ignored, but they have to be preserved when the file is
  // written back out. Hence, we add them to the entries list but not to the
  // index.
  void AddComment(const std::string& comment) {
    entries_.push_back({"", comment});
  }

  // Serializes this group to a string, preserving comments.
  std::string Serialize(bool is_last_group) const {
    std::string data = base::StringPrintf("[%s]\n", name_.c_str());
    for (const auto& entry : entries_) {
      if (!entry.first.empty()) {
        data += entry.first + "=";
      }
      data += entry.second + "\n";
    }
    // If this is not the last group and there isn't already a blank
    // comment line, glib adds a blank line for readability. Replicate
    // that behavior here.
    if (!is_last_group &&
        (entries_.empty() || !IsBlankComment(entries_.back()))) {
      data += "\n";
    }
    return data;
  }

 private:
  std::string name_;
  std::list<KeyValuePair> entries_;
  std::map<std::string, KeyValuePair*> index_;
};

}  // namespace

constexpr LazyRE2 group_header_matcher = {
    "\\[([^[:cntrl:]\\]]*)\\][[:space:]]*"};
constexpr LazyRE2 key_value_matcher = {"([^ ]+?) *= *(.*)"};

class KeyFileStore::KeyFile {
 public:
  static std::unique_ptr<KeyFile> Create(const base::FilePath& path) {
    std::string contents;
    if (!base::ReadFileToString(path, &contents)) {
      return nullptr;
    }

    auto lines = base::SplitString(contents, "\n", base::KEEP_WHITESPACE,
                                   base::SPLIT_WANT_ALL);
    // Trim final empty line if present, since ending a file on a newline
    // will cause us to have an extra with base::SPLIT_WANT_ALL.
    if (!lines.empty() && lines.back().empty()) {
      lines.pop_back();
    }

    std::list<std::string> pre_group_comments;
    std::list<Group> groups;
    std::map<std::string, Group*> index;
    for (const auto& line : lines) {
      // Trim leading spaces.
      auto pos = line.find_first_not_of(' ');
      std::string trimmed_line;
      if (pos != std::string::npos) {
        trimmed_line = line.substr(pos);
      }

      if (trimmed_line.empty() || trimmed_line[0] == '#') {
        // Comment line.
        if (groups.empty()) {
          pre_group_comments.push_back(line);
        } else {
          groups.back().AddComment(line);
        }
        continue;
      }

      std::string group_name;
      if (RE2::FullMatch(trimmed_line, *group_header_matcher, &group_name)) {
        // Group header.
        groups.emplace_back(group_name);
        index[group_name] = &groups.back();
        continue;
      }

      std::string key;
      std::string value;
      if (RE2::FullMatch(trimmed_line, *key_value_matcher, &key, &value)) {
        // Key-value pair.
        if (groups.empty()) {
          LOG(ERROR) << "Key-value pair found without a group";
          return nullptr;
        }

        groups.back().Set(key, value);
        continue;
      }

      LOG(ERROR) << "Could not parse line: \"" << line << "\"";
      return nullptr;
    }

    return std::unique_ptr<KeyFile>(
        new KeyFile(path, std::move(pre_group_comments), std::move(groups),
                    std::move(index)));
  }

  void Set(const std::string& group,
           const std::string& key,
           const std::string& value) {
    if (index_.count(group) == 0) {
      groups_.emplace_back(group);
      index_[group] = &groups_.back();
    }

    index_[group]->Set(key, value);
  }

  base::Optional<std::string> Get(const std::string& group,
                                  const std::string& key) const {
    const auto it = index_.find(group);
    if (it == index_.end()) {
      return base::nullopt;
    }

    return it->second->Get(key);
  }

  bool Delete(const std::string& group, const std::string& key) {
    const auto it = index_.find(group);
    if (it == index_.end()) {
      return false;
    }

    return it->second->Delete(key);
  }

  bool HasGroup(const std::string& group) const {
    return index_.count(group) > 0;
  }

  bool DeleteGroup(const std::string& group) {
    const auto it = index_.find(group);
    if (it == index_.end()) {
      return false;
    }

    Group* grp = it->second;
    index_.erase(it);
    base::EraseIf(groups_, [grp](const Group& g) { return &g == grp; });
    return true;
  }

  std::set<std::string> GetGroups() const {
    std::set<std::string> group_names;
    for (const auto& group : index_) {
      group_names.insert(group.first);
    }
    return group_names;
  }

  void SetHeader(const std::string& header) {
    const auto lines = base::SplitString(header, "\n", base::KEEP_WHITESPACE,
                                         base::SPLIT_WANT_ALL);

    pre_group_comments_.clear();
    for (const std::string& line : lines) {
      pre_group_comments_.push_back("#" + line);
    }
  }

  bool Flush() const {
    std::string to_write;
    for (const std::string& line : pre_group_comments_) {
      to_write += line + '\n';
    }
    for (const Group& group : groups_) {
      to_write += group.Serialize(&group == &groups_.back());
    }

    brillo::ScopedUmask owner_only_umask(~(S_IRUSR | S_IWUSR) & 0777);
    if (!base::ImportantFileWriter::WriteFileAtomically(path_, to_write)) {
      LOG(ERROR) << "Failed to store key file: " << path_.value();
      return false;
    }
    return true;
  }

 private:
  KeyFile(const base::FilePath& path,
          std::list<std::string> pre_group_comments,
          std::list<Group> groups,
          std::map<std::string, Group*> index)
      : path_(path),
        pre_group_comments_(pre_group_comments),
        groups_(std::move(groups)),
        index_(std::move(index)) {}
  KeyFile(const KeyFile&) = delete;
  KeyFile& operator=(const KeyFile&) = delete;

  base::FilePath path_;
  std::list<std::string> pre_group_comments_;
  std::list<Group> groups_;
  std::map<std::string, Group*> index_;
};

const char KeyFileStore::kCorruptSuffix[] = ".corrupted";

KeyFileStore::KeyFileStore(const base::FilePath& path)
    : key_file_(nullptr), path_(path) {
  CHECK(!path_.empty());
}

KeyFileStore::~KeyFileStore() = default;

bool KeyFileStore::IsEmpty() const {
  int64_t file_size = 0;
  return !base::GetFileSize(path_, &file_size) || file_size <= 0;
}

bool KeyFileStore::Open() {
  CHECK(!key_file_);
  if (IsEmpty()) {
    LOG(INFO) << "Creating a new key file at " << path_.value();
    base::File f(path_, base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_READ |
                            base::File::FLAG_WRITE);
  }

  key_file_ = KeyFile::Create(path_);
  if (!key_file_) {
    LOG(ERROR) << "Failed to load key file from " << path_.value();
    return false;
  }

  return true;
}

bool KeyFileStore::Close() {
  bool success = Flush();
  key_file_.reset();
  return success;
}

bool KeyFileStore::Flush() {
  return key_file_->Flush();
}

bool KeyFileStore::MarkAsCorrupted() {
  LOG(INFO) << "In " << __func__ << " for " << path_.value();
  std::string corrupted_path = path_.value() + kCorruptSuffix;
  int ret = rename(path_.value().c_str(), corrupted_path.c_str());
  if (ret != 0) {
    PLOG(ERROR) << "File rename failed";
    return false;
  }
  return true;
}

std::set<std::string> KeyFileStore::GetGroups() const {
  CHECK(key_file_);
  return key_file_->GetGroups();
}

// Returns a set so that caller can easily test whether a particular group
// is contained within this collection.
std::set<std::string> KeyFileStore::GetGroupsWithKey(
    const std::string& key) const {
  std::set<std::string> groups = GetGroups();
  std::set<std::string> groups_with_key;
  for (const auto& group : groups) {
    if (key_file_->Get(group, key).has_value()) {
      groups_with_key.insert(group);
    }
  }
  return groups_with_key;
}

std::set<std::string> KeyFileStore::GetGroupsWithProperties(
    const KeyValueStore& properties) const {
  std::set<std::string> groups = GetGroups();
  std::set<std::string> groups_with_properties;
  for (const auto& group : groups) {
    if (DoesGroupMatchProperties(group, properties)) {
      groups_with_properties.insert(group);
    }
  }
  return groups_with_properties;
}

bool KeyFileStore::ContainsGroup(const std::string& group) const {
  CHECK(key_file_);
  return key_file_->HasGroup(group);
}

bool KeyFileStore::DeleteKey(const std::string& group, const std::string& key) {
  CHECK(key_file_);
  return key_file_->Delete(group, key);
}

bool KeyFileStore::DeleteGroup(const std::string& group) {
  CHECK(key_file_);
  return key_file_->DeleteGroup(group);
}

bool KeyFileStore::SetHeader(const std::string& header) {
  CHECK(key_file_);
  key_file_->SetHeader(header);
  return true;
}

bool KeyFileStore::GetString(const std::string& group,
                             const std::string& key,
                             std::string* value) const {
  CHECK(key_file_);
  base::Optional<std::string> data = key_file_->Get(group, key);
  if (!data.has_value()) {
    SLOG(this, 10) << "Failed to lookup (" << group << ":" << key << ")";
    return false;
  }

  std::vector<std::string> temp;
  if (!Unescape(data.value(), base::nullopt, &temp)) {
    SLOG(this, 10) << "Failed to parse (" << group << ":" << key << ") as"
                   << " string";
    return false;
  }

  CHECK_EQ(1U, temp.size());
  if (value) {
    *value = temp[0];
  }
  return true;
}

bool KeyFileStore::SetString(const std::string& group,
                             const std::string& key,
                             const std::string& value) {
  CHECK(key_file_);
  key_file_->Set(group, key, Escape(value, base::nullopt));
  return true;
}

bool KeyFileStore::GetBool(const std::string& group,
                           const std::string& key,
                           bool* value) const {
  CHECK(key_file_);
  base::Optional<std::string> data = key_file_->Get(group, key);
  if (!data.has_value()) {
    SLOG(this, 10) << "Failed to lookup (" << group << ":" << key << ")";
    return false;
  }

  bool b;
  if (data.value() == "true") {
    b = true;
  } else if (data.value() == "false") {
    b = false;
  } else {
    SLOG(this, 10) << "Failed to parse (" << group << ":" << key << ") as"
                   << " bool";
    return false;
  }

  if (value) {
    *value = b;
  }
  return true;
}

bool KeyFileStore::SetBool(const std::string& group,
                           const std::string& key,
                           bool value) {
  CHECK(key_file_);
  key_file_->Set(group, key, value ? "true" : "false");
  return true;
}

bool KeyFileStore::GetInt(const std::string& group,
                          const std::string& key,
                          int* value) const {
  CHECK(key_file_);
  base::Optional<std::string> data = key_file_->Get(group, key);
  if (!data.has_value()) {
    SLOG(this, 10) << "Failed to lookup (" << group << ":" << key << ")";
    return false;
  }

  int i;
  if (!base::StringToInt(data.value(), &i)) {
    SLOG(this, 10) << "Failed to parse (" << group << ":" << key << ") as"
                   << " int";
    return false;
  }

  if (value) {
    *value = i;
  }
  return true;
}

bool KeyFileStore::SetInt(const std::string& group,
                          const std::string& key,
                          int value) {
  CHECK(key_file_);
  key_file_->Set(group, key, base::NumberToString(value));
  return true;
}

bool KeyFileStore::GetUint64(const std::string& group,
                             const std::string& key,
                             uint64_t* value) const {
  CHECK(key_file_);
  base::Optional<std::string> data = key_file_->Get(group, key);
  if (!data.has_value()) {
    SLOG(this, 10) << "Failed to lookup (" << group << ":" << key << ")";
    return false;
  }

  uint64_t i;
  if (!base::StringToUint64(data.value(), &i)) {
    SLOG(this, 10) << "Failed to parse (" << group << ":" << key << "): "
                   << " as uint64";
    return false;
  }

  if (value) {
    *value = i;
  }
  return true;
}

bool KeyFileStore::SetUint64(const std::string& group,
                             const std::string& key,
                             uint64_t value) {
  CHECK(key_file_);
  key_file_->Set(group, key, base::NumberToString(value));
  return true;
}

bool KeyFileStore::GetStringList(const std::string& group,
                                 const std::string& key,
                                 std::vector<std::string>* value) const {
  CHECK(key_file_);
  base::Optional<std::string> data = key_file_->Get(group, key);
  if (!data.has_value()) {
    SLOG(this, 10) << "Failed to lookup (" << group << ":" << key << ")";
    return false;
  }

  std::vector<std::string> list;
  if (!Unescape(data.value(), kListSeparator, &list)) {
    SLOG(this, 10) << "Failed to parse (" << group << ":" << key << "): "
                   << " as string list";
    return false;
  }

  if (value) {
    *value = list;
  }
  return true;
}

bool KeyFileStore::SetStringList(const std::string& group,
                                 const std::string& key,
                                 const std::vector<std::string>& value) {
  CHECK(key_file_);
  std::vector<std::string> escaped_strings;
  // glib appends a separator to every element of the list.
  for (const auto& string_entry : value) {
    escaped_strings.push_back(Escape(string_entry, kListSeparator) +
                              kListSeparator);
  }
  key_file_->Set(group, key, base::JoinString(escaped_strings, std::string()));
  return true;
}

bool KeyFileStore::GetCryptedString(const std::string& group,
                                    const std::string& deprecated_key,
                                    const std::string& plaintext_key,
                                    std::string* value) const {
  if (GetString(group, plaintext_key, value)) {
    return true;
  }

  if (!GetString(group, deprecated_key, value)) {
    return false;
  }
  if (value) {
    auto plaintext = Crypto::Decrypt(*value);
    if (!plaintext.has_value()) {
      return false;
    }
    *value = std::move(plaintext).value();
  }
  return true;
}

bool KeyFileStore::SetCryptedString(const std::string& group,
                                    const std::string& deprecated_key,
                                    const std::string& plaintext_key,
                                    const std::string& value) {
  SetString(group, deprecated_key, Crypto::Encrypt(value));
  return SetString(group, plaintext_key, value);
}

bool KeyFileStore::DoesGroupMatchProperties(
    const std::string& group, const KeyValueStore& properties) const {
  for (const auto& property : properties.properties()) {
    if (property.second.IsTypeCompatible<bool>()) {
      bool value;
      if (!GetBool(group, property.first, &value) ||
          value != property.second.Get<bool>()) {
        return false;
      }
    } else if (property.second.IsTypeCompatible<int32_t>()) {
      int value;
      if (!GetInt(group, property.first, &value) ||
          value != property.second.Get<int32_t>()) {
        return false;
      }
    } else if (property.second.IsTypeCompatible<std::string>()) {
      std::string value;
      if (!GetString(group, property.first, &value) ||
          value != property.second.Get<std::string>()) {
        return false;
      }
    }
  }
  return true;
}

std::unique_ptr<StoreInterface> CreateStore(const base::FilePath& path) {
  return std::make_unique<KeyFileStore>(path);
}

}  // namespace shill
