// Copyright (c) 2012 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 <map>

#include <base/files/important_file_writer.h>
#include <base/file_util.h>
#include <base/strings/string_number_conversions.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

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

using std::map;
using std::set;
using std::string;
using std::vector;

namespace shill {

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

KeyFileStore::KeyFileStore(GLib *glib)
    : glib_(glib),
      crypto_(glib),
      key_file_(NULL) {}

KeyFileStore::~KeyFileStore() {
  ReleaseKeyFile();
}

void KeyFileStore::ReleaseKeyFile() {
  if (key_file_) {
    glib_->KeyFileFree(key_file_);
    key_file_ = NULL;
  }
}

bool KeyFileStore::IsNonEmpty() const {
  int64 file_size = 0;
  return base::GetFileSize(path_, &file_size) && file_size != 0;
}

bool KeyFileStore::Open() {
  CHECK(!path_.empty());
  CHECK(!key_file_);
  crypto_.Init();
  key_file_ = glib_->KeyFileNew();
  if (!IsNonEmpty()) {
    LOG(INFO) << "Creating a new key file at " << path_.value();
    return true;
  }
  GError *error = NULL;
  if (glib_->KeyFileLoadFromFile(
          key_file_,
          path_.value().c_str(),
          static_cast<GKeyFileFlags>(G_KEY_FILE_KEEP_COMMENTS |
                                     G_KEY_FILE_KEEP_TRANSLATIONS),
          &error)) {
    return true;
  }
  LOG(ERROR) << "Failed to load key file from " << path_.value() << ": "
             << glib_->ConvertErrorToMessage(error);
  ReleaseKeyFile();
  return false;
}

bool KeyFileStore::Close() {
  bool success = Flush();
  ReleaseKeyFile();
  return success;
}

bool KeyFileStore::Flush() {
  CHECK(key_file_);
  GError *error = NULL;
  gsize length = 0;
  gchar *data = glib_->KeyFileToData(key_file_, &length, &error);

  bool success = true;
  if (path_.empty()) {
    LOG(ERROR) << "Empty key file path.";
    success = false;
  }
  if (success && (!data || error)) {
    LOG(ERROR) << "Failed to convert key file to string: "
               << glib_->ConvertErrorToMessage(error);
    success = false;
  }
  if (success) {
    ScopedUmask owner_only_umask(~(S_IRUSR | S_IWUSR));
    success = base::ImportantFileWriter::WriteFileAtomically(path_, data);
    if (!success) {
      LOG(ERROR) << "Failed to store key file: " << path_.value();
    }
  }
  glib_->Free(data);
  return success;
}

bool KeyFileStore::MarkAsCorrupted() {
  LOG(INFO) << "In " << __func__ << " for " << path_.value();
  if (path_.empty()) {
    LOG(ERROR) << "Empty key file path.";
    return false;
  }
  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;
}

set<string> KeyFileStore::GetGroups() const {
  CHECK(key_file_);
  gsize length = 0;
  gchar **groups = glib_->KeyFileGetGroups(key_file_, &length);
  if (!groups) {
    LOG(ERROR) << "Unable to obtain groups.";
    return set<string>();
  }
  set<string> group_set(groups, groups + length);
  glib_->Strfreev(groups);
  return group_set;
}

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

set<string> KeyFileStore::GetGroupsWithProperties(
     const KeyValueStore &properties) const {
  set<string> groups = GetGroups();
  set<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 string &group) const {
  CHECK(key_file_);
  return glib_->KeyFileHasGroup(key_file_, group.c_str());
}

bool KeyFileStore::DeleteKey(const string &group, const string &key) {
  CHECK(key_file_);
  GError *error = NULL;
  glib_->KeyFileRemoveKey(key_file_, group.c_str(), key.c_str(), &error);
  if (error && error->code != G_KEY_FILE_ERROR_KEY_NOT_FOUND) {
    LOG(ERROR) << "Failed to delete (" << group << ":" << key << "): "
               << glib_->ConvertErrorToMessage(error);
    return false;
  }
  return true;
}

bool KeyFileStore::DeleteGroup(const string &group) {
  CHECK(key_file_);
  GError *error = NULL;
  glib_->KeyFileRemoveGroup(key_file_, group.c_str(), &error);
  if (error && error->code != G_KEY_FILE_ERROR_GROUP_NOT_FOUND) {
    LOG(ERROR) << "Failed to delete group " << group << ": "
               << glib_->ConvertErrorToMessage(error);
    return false;
  }
  return true;
}

bool KeyFileStore::SetHeader(const string &header) {
  GError *error = NULL;
  glib_->KeyFileSetComment(key_file_, NULL, NULL, header.c_str(), &error);
  if (error) {
    LOG(ERROR) << "Failed to to set header: "
               << glib_->ConvertErrorToMessage(error);
    return false;
  }
  return true;
}

bool KeyFileStore::GetString(const string &group,
                             const string &key,
                             string *value) const {
  CHECK(key_file_);
  GError *error = NULL;
  gchar *data =
      glib_->KeyFileGetString(key_file_, group.c_str(), key.c_str(), &error);
  if (!data) {
    string s = glib_->ConvertErrorToMessage(error);
    SLOG(Storage, 10) << "Failed to lookup (" << group << ":" << key << "): "
                      << s;
    return false;
  }
  if (value) {
    *value = data;
  }
  glib_->Free(data);
  return true;
}

bool KeyFileStore::SetString(const string &group,
                             const string &key,
                             const string &value) {
  CHECK(key_file_);
  glib_->KeyFileSetString(key_file_, group.c_str(), key.c_str(), value.c_str());
  return true;
}

bool KeyFileStore::GetBool(const string &group,
                           const string &key,
                           bool *value) const {
  CHECK(key_file_);
  GError *error = NULL;
  gboolean data =
      glib_->KeyFileGetBoolean(key_file_, group.c_str(), key.c_str(), &error);
  if (error) {
    string s = glib_->ConvertErrorToMessage(error);
    SLOG(Storage, 10) << "Failed to lookup (" << group << ":" << key << "): "
                      << s;
    return false;
  }
  if (value) {
    *value = data;
  }
  return true;
}

bool KeyFileStore::SetBool(const string &group, const string &key, bool value) {
  CHECK(key_file_);
  glib_->KeyFileSetBoolean(key_file_,
                           group.c_str(),
                           key.c_str(),
                           value ? TRUE : FALSE);
  return true;
}

bool KeyFileStore::GetInt(
    const string &group, const string &key, int *value) const {
  CHECK(key_file_);
  GError *error = NULL;
  gint data =
      glib_->KeyFileGetInteger(key_file_, group.c_str(), key.c_str(), &error);
  if (error) {
    string s = glib_->ConvertErrorToMessage(error);
    SLOG(Storage, 10) << "Failed to lookup (" << group << ":" << key << "): "
                      << s;
    return false;
  }
  if (value) {
    *value = data;
  }
  return true;
}

bool KeyFileStore::SetInt(const string &group, const string &key, int value) {
  CHECK(key_file_);
  glib_->KeyFileSetInteger(key_file_, group.c_str(), key.c_str(), value);
  return true;
}

bool KeyFileStore::GetUint64(
    const string &group, const string &key, uint64 *value) const {
  // Read the value in as a string and then convert to uint64 because glib's
  // g_key_file_set_uint64 appears not to work correctly on 32-bit platforms
  // in unit tests.
  string data_string;
  if (!GetString(group, key, &data_string)) {
    return false;
  }

  uint64 data;
  if (!base::StringToUint64(data_string, &data)) {
    SLOG(Storage, 10) << "Failed to convert (" << group << ":" << key << "): "
                      << "string to uint64 conversion failed";
    return false;
  }

  if (value) {
    *value = data;
  }

  return true;
}

bool KeyFileStore::SetUint64(
    const string &group, const string &key, uint64 value) {
  // Convert the value to a string first, then save the value because glib's
  // g_key_file_get_uint64 appears not to work on 32-bit platforms in our
  // unit tests.
  return SetString(group, key, base::Uint64ToString(value));
}

bool KeyFileStore::GetStringList(const string &group,
                                 const string &key,
                                 vector<string> *value) const {
  CHECK(key_file_);
  gsize length = 0;
  GError *error = NULL;
  gchar **data = glib_->KeyFileGetStringList(key_file_,
                                             group.c_str(),
                                             key.c_str(),
                                             &length,
                                             &error);
  if (!data) {
    string s = glib_->ConvertErrorToMessage(error);
    SLOG(Storage, 10) << "Failed to lookup (" << group << ":" << key << "): "
                      << s;
    return false;
  }
  if (value) {
    value->assign(data, data + length);
  }
  glib_->Strfreev(data);
  return true;
}

bool KeyFileStore::SetStringList(const string &group,
                                 const string &key,
                                 const vector<string> &value) {
  CHECK(key_file_);
  vector<const char *> list;
  for (const auto &string_entry : value) {
    list.push_back(string_entry.c_str());
  }
  glib_->KeyFileSetStringList(key_file_,
                              group.c_str(),
                              key.c_str(),
                              list.data(),
                              list.size());
  return true;
}

bool KeyFileStore::GetCryptedString(const string &group,
                                    const string &key,
                                    string *value) {
  if (!GetString(group, key, value)) {
    return false;
  }
  if (value) {
    *value = crypto_.Decrypt(*value);
  }
  return true;
}

bool KeyFileStore::SetCryptedString(const string &group,
                                    const string &key,
                                    const string &value) {
  return SetString(group, key, crypto_.Encrypt(value));
}

bool KeyFileStore::DoesGroupMatchProperties(
    const string &group, const KeyValueStore &properties) const {
  map<string, bool>::const_iterator bool_it;
  for (const auto &property : properties.bool_properties()) {
    bool value;
    if (!GetBool(group, property.first, &value) || value != property.second) {
      return false;
    }
  }
  for (const auto &property : properties.int_properties()) {
    int value;
    if (!GetInt(group, property.first, &value) || value != property.second) {
      return false;
    }
  }
  for (const auto &property : properties.string_properties()) {
    string value;
    if (!GetString(group, property.first, &value) || value != property.second) {
      return false;
    }
  }
  return true;
}

}  // namespace shill
