//
// Copyright (C) 2015 The Android Open Source Project
//
// 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 "shill/json_store.h"

#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

#include <cinttypes>
#include <map>
#include <memory>
#include <typeinfo>
#include <vector>

#include <base/files/important_file_writer.h>
#include <base/files/file_util.h>
#include <base/json/json_string_value_serializer.h>
#include <base/memory/ptr_util.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/values.h>

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

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

namespace shill {

namespace Logging {

static auto kModuleLogScope = ScopeLogger::kStorage;
static string ObjectID(const JsonStore* j) {
  return "(unknown)";
}

}  // namespace Logging

namespace {

static const char kCorruptSuffix[] = ".corrupted";
static const char kCoercedValuePropertyEncodedValue[] = "_encoded_value";
static const char kCoercedValuePropertyNativeType[] = "_native_type";
static const char kNativeTypeNonAsciiString[] = "non_ascii_string";
static const char kNativeTypeUint64[] = "uint64";
static const char kRootPropertyDescription[] = "description";
static const char kRootPropertySettings[] = "settings";

bool DoesGroupContainProperties(
    const brillo::VariantDictionary& group,
    const brillo::VariantDictionary& required_properties) {
  for (const auto& required_property_name_and_value : required_properties) {
    const auto& required_key = required_property_name_and_value.first;
    const auto& required_value = required_property_name_and_value.second;
    const auto& group_it = group.find(required_key);
    if (group_it == group.end() || group_it->second != required_value) {
      return false;
    }
  }
  return true;
}

// Deserialization helpers.

// A coerced value is used to represent values that base::Value does
// not directly support.  A coerced value has the form
//   {'_native_type': <type-as-string>, '_encoded_value': <value-as-string>}
bool IsCoercedValue(const base::DictionaryValue& value) {
  return value.HasKey(kCoercedValuePropertyNativeType) &&
      value.HasKey(kCoercedValuePropertyEncodedValue);
}

unique_ptr<brillo::Any> DecodeCoercedValue(
    const base::DictionaryValue& coerced_value) {
  string native_type;
  if (!coerced_value.GetStringWithoutPathExpansion(
          kCoercedValuePropertyNativeType, &native_type)) {
    LOG(ERROR) << "Property |" << kCoercedValuePropertyNativeType
               << "| is not a string.";
    return nullptr;
  }

  string encoded_value;
  if (!coerced_value.GetStringWithoutPathExpansion(
          kCoercedValuePropertyEncodedValue, &encoded_value)) {
    LOG(ERROR) << "Property |" << kCoercedValuePropertyEncodedValue
               << "| is not a string.";
    return nullptr;
  }

  if (native_type == kNativeTypeNonAsciiString) {
    vector<uint8_t> native_value;
    if (base::HexStringToBytes(encoded_value, &native_value)) {
      return unique_ptr<brillo::Any>(
          new brillo::Any(string(native_value.begin(), native_value.end())));
    } else {
      LOG(ERROR) << "Failed to decode hex data from |" << encoded_value << "|.";
      return nullptr;
    }
  } else if (native_type == kNativeTypeUint64) {
    uint64_t native_value;
    if (base::StringToUint64(encoded_value, &native_value)) {
      return unique_ptr<brillo::Any>(new brillo::Any(native_value));
    } else {
      LOG(ERROR) << "Failed to parse uint64 from |" << encoded_value << "|.";
      return nullptr;
    }
  } else {
    LOG(ERROR) << "Unsupported native type |" << native_type << "|.";
    return nullptr;
  }
}

unique_ptr<string> MakeStringFromValue(const base::Value& value) {
  const auto value_type = value.GetType();

  if (value_type == base::Value::TYPE_STRING) {
    unique_ptr<string> unwrapped_string(new string());
    value.GetAsString(unwrapped_string.get());
    return unwrapped_string;
  } else if (value_type == base::Value::TYPE_DICTIONARY) {
    const base::DictionaryValue* dictionary_value;
    value.GetAsDictionary(&dictionary_value);
    unique_ptr<brillo::Any> decoded_value(
        DecodeCoercedValue(*dictionary_value));
    if (!decoded_value) {
      LOG(ERROR) << "Failed to decode coerced value.";
      return nullptr;
    }

    if (!decoded_value->IsTypeCompatible<string>()) {
      LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<string>()
                 << "| from |" << decoded_value->GetUndecoratedTypeName()
                 << ".";
      return nullptr;
    }
    return unique_ptr<string>(new string(decoded_value->Get<string>()));
  } else {
    LOG(ERROR) << "Got unexpected type |" << value_type << "|.";
    return nullptr;
  }
}

unique_ptr<vector<string>> ConvertListValueToStringVector(
    const base::ListValue& list_value) {
  const size_t list_len = list_value.GetSize();
  for (size_t i = 0; i < list_len; ++i) {
    const base::Value* list_item;
    list_value.Get(i, &list_item);
    const auto item_type = list_item->GetType();
    if (item_type != base::Value::TYPE_STRING &&
        item_type != base::Value::TYPE_DICTIONARY) {
      LOG(ERROR) << "Element " << i << " has type " << item_type << ", "
                 << "instead of expected types "
                 << base::Value::TYPE_STRING << "  or "
                 << base::Value::TYPE_DICTIONARY << ".";
      return nullptr;
    }
  }

  unique_ptr<vector<string>> result(new vector<string>);
  for (size_t i = 0; i < list_len; ++i) {
    const base::Value* list_item;
    unique_ptr<string> native_string;
    list_value.Get(i, &list_item);
    native_string = MakeStringFromValue(*list_item);
    if (!native_string) {
      LOG(ERROR) << "Failed to parse string from element " << i << ".";
      return nullptr;
    }
    result->push_back(*native_string);
  }
  return result;
}

unique_ptr<brillo::VariantDictionary>
ConvertDictionaryValueToVariantDictionary(
    const base::DictionaryValue& dictionary_value) {
  base::DictionaryValue::Iterator it(dictionary_value);
  unique_ptr<brillo::VariantDictionary> variant_dictionary(
      new brillo::VariantDictionary());
  while (!it.IsAtEnd()) {
    const string& key = it.key();
    const base::Value& value = it.value();
    switch (value.GetType()) {
      case base::Value::TYPE_NULL:
        LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_NULL.";
        return nullptr;
      case base::Value::TYPE_BOOLEAN: {
        bool native_bool;
        value.GetAsBoolean(&native_bool);
        (*variant_dictionary)[key] = native_bool;
        break;
      }
      case base::Value::TYPE_INTEGER: {
        int native_int;
        value.GetAsInteger(&native_int);
        (*variant_dictionary)[key] = native_int;
        break;
      }
      case base::Value::TYPE_DOUBLE:
        LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_DOUBLE.";
        return nullptr;
      case base::Value::TYPE_STRING: {
        string native_string;
        value.GetAsString(&native_string);
        (*variant_dictionary)[key] = native_string;
        break;
      }
      case base::Value::TYPE_BINARY:
        /* The JSON parser should never create Values of this type. */
        LOG(ERROR) << "Key |" << key << "| has unexpected TYPE_BINARY.";
        return nullptr;
      case base::Value::TYPE_DICTIONARY: {
        const base::DictionaryValue* dictionary_value;
        value.GetAsDictionary(&dictionary_value);
        if (!IsCoercedValue(*dictionary_value)) {
          LOG(ERROR) << "Key |" << key << "| has unsupported TYPE_DICTIONARY.";
          return nullptr;
        }
        unique_ptr<brillo::Any> decoded_coerced_value(
            DecodeCoercedValue(*dictionary_value));
        if (!decoded_coerced_value) {
          LOG(ERROR) << "Key |" << key << "| could not be decoded.";
          return nullptr;
        }
        (*variant_dictionary)[key] = *decoded_coerced_value;
        break;
      }
      case base::Value::TYPE_LIST: {  // Only string lists, for now.
        const base::ListValue* list_value;
        value.GetAsList(&list_value);

        unique_ptr<vector<string>> string_list(
            ConvertListValueToStringVector(*list_value));
        if (!string_list) {
          LOG(ERROR) << "Key |" << key << "| could not be decoded.";
          return nullptr;
        }
        (*variant_dictionary)[key] = *string_list;
        break;
      }
    }
    it.Advance();
  }
  return variant_dictionary;
}

// Serialization helpers.

std::unique_ptr<base::DictionaryValue> MakeCoercedValue(
    const string& native_type, const string& encoded_value) {
  auto coerced_value = base::MakeUnique<base::DictionaryValue>();
  coerced_value->SetStringWithoutPathExpansion(
      kCoercedValuePropertyNativeType, native_type);
  coerced_value->SetStringWithoutPathExpansion(
      kCoercedValuePropertyEncodedValue, encoded_value);
  return coerced_value;
}

std::unique_ptr<base::Value> MakeValueForString(const string& native_string) {
  // Strictly speaking, we don't need to escape non-ASCII text, if
  // that text is UTF-8.  Practically speaking, however, it'll be
  // easier to inspect config files if all non-ASCII strings are
  // presented as byte sequences. (Unicode has many code points with
  // similar-looking glyphs.)
  if (base::IsStringASCII(native_string) &&
      native_string.find('\0') == string::npos) {
    return base::MakeUnique<base::StringValue>(native_string);
  } else {
    const string hex_encoded_string(
        base::HexEncode(native_string.data(), native_string.size()));
    return MakeCoercedValue(kNativeTypeNonAsciiString, hex_encoded_string);
  }
}

std::unique_ptr<base::DictionaryValue> ConvertVariantDictionaryToDictionaryValue(
    const brillo::VariantDictionary& variant_dictionary) {
  auto dictionary_value = base::MakeUnique<base::DictionaryValue>();
  for (const auto& key_and_value : variant_dictionary) {
    const auto& key = key_and_value.first;
    const auto& value = key_and_value.second;
    if (value.IsTypeCompatible<bool>()) {
      dictionary_value->SetBooleanWithoutPathExpansion(key, value.Get<bool>());
    } else if (value.IsTypeCompatible<int32_t>()) {
      dictionary_value->SetIntegerWithoutPathExpansion(key, value.Get<int>());
    } else if (value.IsTypeCompatible<string>()) {
      dictionary_value->SetWithoutPathExpansion(
          key, MakeValueForString(value.Get<string>()));
    } else if (value.IsTypeCompatible<uint64_t>()) {
      const string encoded_value(
          base::StringPrintf("%" PRIu64, value.Get<uint64_t>()));
      dictionary_value->SetWithoutPathExpansion(
          key, MakeCoercedValue(kNativeTypeUint64, encoded_value));
    } else if (value.IsTypeCompatible<vector<string>>()) {
      auto list_value = base::MakeUnique<base::ListValue>();
      for (const auto& string_list_item : value.Get<vector<string>>()) {
        list_value->Append(MakeValueForString(string_list_item));
      }
      dictionary_value->SetWithoutPathExpansion(key, std::move(list_value));
    } else {
      LOG(ERROR) << "Failed to convert element with key |" << key << "|.";
      return nullptr;
    }
  }
  return dictionary_value;
}

}  // namespace

JsonStore::JsonStore(const base::FilePath& path)
    : path_(path) {
  CHECK(!path_.empty());
}

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

bool JsonStore::Open() {
  if (!IsNonEmpty()) {
    LOG(INFO) << "Creating a new key file at |" << path_.value() << "|.";
    return true;
  }

  string json_string;
  if (!base::ReadFileToString(path_, &json_string)) {
    LOG(ERROR) << "Failed to read data from |" << path_.value() << "|.";
    return false;
  }

  JSONStringValueDeserializer json_deserializer(json_string);
  unique_ptr<base::Value> json_value;
  string json_error;
  json_deserializer.set_allow_trailing_comma(true);
  json_value.reset(
      json_deserializer.Deserialize(nullptr, &json_error).release());
  if (!json_value) {
    LOG(ERROR) << "Failed to parse JSON data from |" << path_.value() <<"|.";
    SLOG(this, 5) << json_error;
    return false;
  }

  const base::DictionaryValue* root_dictionary;
  if (!json_value->GetAsDictionary(&root_dictionary)) {
    LOG(ERROR) << "JSON value is not a dictionary.";
    return false;
  }

  CHECK(root_dictionary);
  if (root_dictionary->HasKey(kRootPropertyDescription) &&
      !root_dictionary->GetStringWithoutPathExpansion(
          kRootPropertyDescription, &file_description_)) {
    LOG(WARNING) << "Property |" << kRootPropertyDescription
                 << "| is not a string.";
    // Description is non-critical, so continue processing.
  }

  if (!root_dictionary->HasKey(kRootPropertySettings)) {
    LOG(ERROR) << "Property |" << kRootPropertySettings << "| is missing.";
    return false;
  }

  const base::DictionaryValue* settings_dictionary;
  if (!root_dictionary->GetDictionaryWithoutPathExpansion(
          kRootPropertySettings, &settings_dictionary)) {
    LOG(ERROR) << "Property |" << kRootPropertySettings
               << "| is not a dictionary.";
    return false;
  }

  if (!group_name_to_settings_.empty()) {
    LOG(INFO) << "Clearing existing settings on open.";
    group_name_to_settings_.clear();
  }

  base::DictionaryValue::Iterator it(*settings_dictionary);
  while (!it.IsAtEnd()) {
    const string& group_name = it.key();
    const base::DictionaryValue* group_settings_as_values;
    if (!it.value().GetAsDictionary(&group_settings_as_values)) {
      LOG(ERROR) << "Group |" << group_name << "| is not a dictionary.";
      return false;
    }

    unique_ptr<brillo::VariantDictionary> group_settings_as_variants =
        ConvertDictionaryValueToVariantDictionary(*group_settings_as_values);
    if (!group_settings_as_variants) {
      LOG(ERROR) << "Failed to convert group |" << group_name
                 << "| to variants.";
      return false;
    }

    group_name_to_settings_[group_name] = *group_settings_as_variants;
    it.Advance();
  }

  return true;
}

bool JsonStore::Close() {
  return Flush();
}

bool JsonStore::Flush() {
  auto groups = base::MakeUnique<base::DictionaryValue>();
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    std::unique_ptr<base::DictionaryValue> group_settings(
        ConvertVariantDictionaryToDictionaryValue(
            group_name_and_settings.second));
    if (!group_settings) {
      // This class maintains the invariant that anything placed in
      // |group_settings| is convertible. So abort if conversion fails.
      LOG(FATAL) << "Failed to convert group |" << group_name << "|.";
      return false;
    }
    groups->SetWithoutPathExpansion(group_name, std::move(group_settings));
  }

  base::DictionaryValue root;
  root.SetStringWithoutPathExpansion(
      kRootPropertyDescription, file_description_);
  root.SetWithoutPathExpansion(kRootPropertySettings, std::move(groups));

  string json_string;
  JSONStringValueSerializer json_serializer(&json_string);
  json_serializer.set_pretty_print(true);
  if (!json_serializer.Serialize(root)) {
    LOG(ERROR) << "Failed to serialize to JSON.";
    return false;
  }

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

  return true;
}

bool JsonStore::MarkAsCorrupted() {
  LOG(INFO) << "In " << __func__ << " for " << path_.value();
  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> JsonStore::GetGroups() const {
  set<string> matching_groups;
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    matching_groups.insert(group_name_and_settings.first);
  }
  return matching_groups;
}

// Returns a set so that caller can easily test whether a particular group
// is contained within this collection.
set<string> JsonStore::GetGroupsWithKey(const string& key) const {
  set<string> matching_groups;
  // iterate over groups, find ones with matching key
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    const auto& group_settings = group_name_and_settings.second;
    if (group_settings.find(key) != group_settings.end()) {
      matching_groups.insert(group_name);
    }
  }
  return matching_groups;
}

set<string> JsonStore::GetGroupsWithProperties(const KeyValueStore& properties)
    const {
  set<string> matching_groups;
  const brillo::VariantDictionary& properties_dict(properties.properties());
  for (const auto& group_name_and_settings : group_name_to_settings_) {
    const auto& group_name = group_name_and_settings.first;
    const auto& group_settings = group_name_and_settings.second;
    if (DoesGroupContainProperties(group_settings, properties_dict)) {
      matching_groups.insert(group_name);
    }
  }
  return matching_groups;
}

bool JsonStore::ContainsGroup(const string& group) const {
  const auto& it = group_name_to_settings_.find(group);
  return it != group_name_to_settings_.end();
}

bool JsonStore::DeleteKey(const string& group, const string& key) {
  const auto& group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    LOG(ERROR) << "Could not find group |" << group << "|.";
    return false;
  }

  auto& group_settings = group_name_and_settings->second;
  auto property_it = group_settings.find(key);
  if (property_it != group_settings.end()) {
    group_settings.erase(property_it);
  }

  return true;
}

bool JsonStore::DeleteGroup(const string& group) {
  auto group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings != group_name_to_settings_.end()) {
    group_name_to_settings_.erase(group_name_and_settings);
  }
  return true;
}

bool JsonStore::SetHeader(const string& header) {
  file_description_ = header;
  return true;
}

bool JsonStore::GetString(const string& group,
                          const string& key,
                          string* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetString(
    const string& group, const string& key, const string& value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetBool(const string& group, const string& key, bool* value)
    const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetBool(const string& group, const string& key, bool value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetInt(
    const string& group, const string& key, int* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetInt(const string& group, const string& key, int value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetUint64(
    const string& group, const string& key, uint64_t* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetUint64(
    const string& group, const string& key, uint64_t value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetStringList(
    const string& group, const string& key, vector<string>* value) const {
  return ReadSetting(group, key, value);
}

bool JsonStore::SetStringList(
    const string& group, const string& key, const vector<string>& value) {
  return WriteSetting(group, key, value);
}

bool JsonStore::GetCryptedString(
    const string& group, const string& key, string* value) {
  string encrypted_value;
  if (!GetString(group, key, &encrypted_value)) {
    return false;
  }

  // TODO(quiche): Once we've removed the glib dependency in
  // CryptoProvider, move to using CryptoProvider, instead of
  // CryptoROT47 directly. This change should be done before using
  // JsonStore in production, as the on-disk format of crypted strings
  // will change.
  CryptoROT47 rot47;
  string decrypted_value;
  if (!rot47.Decrypt(encrypted_value, &decrypted_value)) {
    LOG(ERROR) << "Failed to decrypt value for |" << group << "|"
               << ":|" << key << "|.";
    return false;
  }

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

bool JsonStore::SetCryptedString(
    const string& group, const string& key, const string& value) {
  CryptoROT47 rot47;
  string encrypted_value;
  if (!rot47.Encrypt(value, &encrypted_value)) {
    LOG(ERROR) << "Failed to encrypt value for |" << group << "|"
               << ":|" << key << "|.";
    return false;
  }

  return SetString(group, key, encrypted_value);
}

// Private methods.
template<typename T>
bool JsonStore::ReadSetting(
    const string& group, const string& key, T* out) const {
  const auto& group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    SLOG(this, 10) << "Could not find group |" << group << "|.";
    return false;
  }

  const auto& group_settings = group_name_and_settings->second;
  const auto& property_name_and_value = group_settings.find(key);
  if (property_name_and_value == group_settings.end()) {
    SLOG(this, 10) << "Could not find property |" << key << "|.";
    return false;
  }

  if (!property_name_and_value->second.IsTypeCompatible<T>()) {
    // We assume that the reader and the writer agree on the exact
    // type. So we do not allow implicit conversion.
    LOG(ERROR) << "Can not read |" << brillo::GetUndecoratedTypeName<T>()
               << "| from |"
               << property_name_and_value->second.GetUndecoratedTypeName()
               << "|.";
    return false;
  }

  if (out) {
    return property_name_and_value->second.GetValue(out);
  } else {
    return true;
  }
}

template<typename T>
bool JsonStore::WriteSetting(
    const string& group, const string& key, const T& new_value) {
  auto group_name_and_settings = group_name_to_settings_.find(group);
  if (group_name_and_settings == group_name_to_settings_.end()) {
    group_name_to_settings_[group][key] = new_value;
    return true;
  }

  auto& group_settings = group_name_and_settings->second;
  auto property_name_and_value = group_settings.find(key);
  if (property_name_and_value == group_settings.end()) {
    group_settings[key] = new_value;
    return true;
  }

  if (!property_name_and_value->second.IsTypeCompatible<T>()) {
    SLOG(this, 10) << "New type |" << brillo::GetUndecoratedTypeName<T>()
                   << "| differs from current type |"
                   << property_name_and_value->second.GetUndecoratedTypeName()
                   << "|.";
    return false;
  } else {
    property_name_and_value->second = new_value;
    return true;
  }
}

}  // namespace shill
