// Copyright 2013 The Chromium 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 "components/policy/core/common/registry_dict.h"

#include <utility>

#include "base/json/json_reader.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/sys_byteorder.h"
#include "base/values.h"

#if defined(OS_WIN)
#include "base/win/registry.h"
#include "components/policy/core/common/schema.h"

using base::win::RegistryKeyIterator;
using base::win::RegistryValueIterator;
#endif  // #if defined(OS_WIN)

namespace policy {

namespace {

#if defined(OS_WIN)
// Validates that a key is numerical. Used for lists below.
bool IsKeyNumerical(const std::string& key) {
  int temp = 0;
  return base::StringToInt(key, &temp);
}

// Converts a value (as read from the registry) to meet |schema|, converting
// types as necessary. Unconvertible types will show up as null values in the
// result.
std::unique_ptr<base::Value> ConvertValue(const base::Value& value,
                                          const Schema& schema) {
  if (!schema.valid())
    return value.CreateDeepCopy();

  // If the type is good already, go with it.
  if (value.IsType(schema.type())) {
    // Recurse for complex types.
    const base::DictionaryValue* dict = nullptr;
    const base::ListValue* list = nullptr;
    if (value.GetAsDictionary(&dict)) {
      std::unique_ptr<base::DictionaryValue> result(
          new base::DictionaryValue());
      for (base::DictionaryValue::Iterator entry(*dict); !entry.IsAtEnd();
           entry.Advance()) {
        std::unique_ptr<base::Value> converted =
            ConvertValue(entry.value(), schema.GetProperty(entry.key()));
        if (converted)
          result->SetWithoutPathExpansion(entry.key(), converted.release());
      }
      return std::move(result);
    } else if (value.GetAsList(&list)) {
      std::unique_ptr<base::ListValue> result(new base::ListValue());
      for (base::ListValue::const_iterator entry(list->begin());
           entry != list->end(); ++entry) {
        std::unique_ptr<base::Value> converted =
            ConvertValue(*entry, schema.GetItems());
        if (converted)
          result->Append(std::move(converted));
      }
      return std::move(result);
    }
    return value.CreateDeepCopy();
  }

  // Else, do some conversions to map windows registry data types to JSON types.
  std::string string_value;
  int int_value = 0;
  switch (schema.type()) {
    case base::Value::Type::NONE: {
      return base::MakeUnique<base::Value>();
    }
    case base::Value::Type::BOOLEAN: {
      // Accept booleans encoded as either string or integer.
      if (value.GetAsInteger(&int_value) ||
          (value.GetAsString(&string_value) &&
           base::StringToInt(string_value, &int_value))) {
        return std::unique_ptr<base::Value>(new base::Value(int_value != 0));
      }
      break;
    }
    case base::Value::Type::INTEGER: {
      // Integers may be string-encoded.
      if (value.GetAsString(&string_value) &&
          base::StringToInt(string_value, &int_value)) {
        return std::unique_ptr<base::Value>(new base::Value(int_value));
      }
      break;
    }
    case base::Value::Type::DOUBLE: {
      // Doubles may be string-encoded or integer-encoded.
      double double_value = 0;
      if (value.GetAsDouble(&double_value) ||
          (value.GetAsString(&string_value) &&
           base::StringToDouble(string_value, &double_value))) {
        return std::unique_ptr<base::Value>(new base::Value(double_value));
      }
      break;
    }
    case base::Value::Type::LIST: {
      // Lists are encoded as subkeys with numbered value in the registry
      // (non-numerical keys are ignored).
      const base::DictionaryValue* dict = nullptr;
      if (value.GetAsDictionary(&dict)) {
        std::unique_ptr<base::ListValue> result(new base::ListValue());
        for (base::DictionaryValue::Iterator it(*dict); !it.IsAtEnd();
             it.Advance()) {
          if (!IsKeyNumerical(it.key()))
            continue;
          std::unique_ptr<base::Value> converted =
              ConvertValue(it.value(), schema.GetItems());
          if (converted)
            result->Append(std::move(converted));
        }
        return std::move(result);
      }
      // Fall through in order to accept lists encoded as JSON strings.
    }
    case base::Value::Type::DICTIONARY: {
      // Dictionaries may be encoded as JSON strings.
      if (value.GetAsString(&string_value)) {
        std::unique_ptr<base::Value> result =
            base::JSONReader::Read(string_value);
        if (result && result->IsType(schema.type()))
          return result;
      }
      break;
    }
    case base::Value::Type::STRING:
    case base::Value::Type::BINARY:
      // No conversion possible.
      break;
  }

  LOG(WARNING) << "Failed to convert " << value.GetType()
               << " to " << schema.type();
  return nullptr;
}
#endif  // #if defined(OS_WIN)

}  // namespace

bool CaseInsensitiveStringCompare::operator()(const std::string& a,
                                              const std::string& b) const {
  return base::CompareCaseInsensitiveASCII(a, b) < 0;
}

RegistryDict::RegistryDict() {}

RegistryDict::~RegistryDict() {
  ClearKeys();
  ClearValues();
}

RegistryDict* RegistryDict::GetKey(const std::string& name) {
  KeyMap::iterator entry = keys_.find(name);
  return entry != keys_.end() ? entry->second.get() : nullptr;
}

const RegistryDict* RegistryDict::GetKey(const std::string& name) const {
  KeyMap::const_iterator entry = keys_.find(name);
  return entry != keys_.end() ? entry->second.get() : nullptr;
}

void RegistryDict::SetKey(const std::string& name,
                          std::unique_ptr<RegistryDict> dict) {
  if (!dict) {
    RemoveKey(name);
    return;
  }

  keys_[name] = std::move(dict);
}

std::unique_ptr<RegistryDict> RegistryDict::RemoveKey(const std::string& name) {
  std::unique_ptr<RegistryDict> result;
  KeyMap::iterator entry = keys_.find(name);
  if (entry != keys_.end()) {
    result = std::move(entry->second);
    keys_.erase(entry);
  }
  return result;
}

void RegistryDict::ClearKeys() {
  keys_.clear();
}

base::Value* RegistryDict::GetValue(const std::string& name) {
  ValueMap::iterator entry = values_.find(name);
  return entry != values_.end() ? entry->second.get() : nullptr;
}

const base::Value* RegistryDict::GetValue(const std::string& name) const {
  ValueMap::const_iterator entry = values_.find(name);
  return entry != values_.end() ? entry->second.get() : nullptr;
}

void RegistryDict::SetValue(const std::string& name,
                            std::unique_ptr<base::Value> dict) {
  if (!dict) {
    RemoveValue(name);
    return;
  }

  values_[name] = std::move(dict);
}

std::unique_ptr<base::Value> RegistryDict::RemoveValue(
    const std::string& name) {
  std::unique_ptr<base::Value> result;
  ValueMap::iterator entry = values_.find(name);
  if (entry != values_.end()) {
    result = std::move(entry->second);
    values_.erase(entry);
  }
  return result;
}

void RegistryDict::ClearValues() {
  values_.clear();
}

void RegistryDict::Merge(const RegistryDict& other) {
  for (KeyMap::const_iterator entry(other.keys_.begin());
       entry != other.keys_.end(); ++entry) {
    std::unique_ptr<RegistryDict>& subdict = keys_[entry->first];
    if (!subdict)
      subdict = base::MakeUnique<RegistryDict>();
    subdict->Merge(*entry->second);
  }

  for (ValueMap::const_iterator entry(other.values_.begin());
       entry != other.values_.end(); ++entry) {
    SetValue(entry->first, entry->second->CreateDeepCopy());
  }
}

void RegistryDict::Swap(RegistryDict* other) {
  keys_.swap(other->keys_);
  values_.swap(other->values_);
}

#if defined(OS_WIN)
void RegistryDict::ReadRegistry(HKEY hive, const base::string16& root) {
  ClearKeys();
  ClearValues();

  // First, read all the values of the key.
  for (RegistryValueIterator it(hive, root.c_str()); it.Valid(); ++it) {
    const std::string name = base::UTF16ToUTF8(it.Name());
    switch (it.Type()) {
      case REG_SZ:
      case REG_EXPAND_SZ:
        SetValue(name, std::unique_ptr<base::Value>(
                           new base::Value(base::UTF16ToUTF8(it.Value()))));
        continue;
      case REG_DWORD_LITTLE_ENDIAN:
      case REG_DWORD_BIG_ENDIAN:
        if (it.ValueSize() == sizeof(DWORD)) {
          DWORD dword_value = *(reinterpret_cast<const DWORD*>(it.Value()));
          if (it.Type() == REG_DWORD_BIG_ENDIAN)
            dword_value = base::NetToHost32(dword_value);
          else
            dword_value = base::ByteSwapToLE32(dword_value);
          SetValue(name, std::unique_ptr<base::Value>(
                             new base::Value(static_cast<int>(dword_value))));
          continue;
        }
      case REG_NONE:
      case REG_LINK:
      case REG_MULTI_SZ:
      case REG_RESOURCE_LIST:
      case REG_FULL_RESOURCE_DESCRIPTOR:
      case REG_RESOURCE_REQUIREMENTS_LIST:
      case REG_QWORD_LITTLE_ENDIAN:
        // Unsupported type, message gets logged below.
        break;
    }

    LOG(WARNING) << "Failed to read hive " << hive << " at "
                 << root << "\\" << name
                 << " type " << it.Type();
  }

  // Recurse for all subkeys.
  for (RegistryKeyIterator it(hive, root.c_str()); it.Valid(); ++it) {
    std::string name(base::UTF16ToUTF8(it.Name()));
    std::unique_ptr<RegistryDict> subdict(new RegistryDict());
    subdict->ReadRegistry(hive, root + L"\\" + it.Name());
    SetKey(name, std::move(subdict));
  }
}

std::unique_ptr<base::Value> RegistryDict::ConvertToJSON(
    const Schema& schema) const {
  base::Value::Type type =
      schema.valid() ? schema.type() : base::Value::Type::DICTIONARY;
  switch (type) {
    case base::Value::Type::DICTIONARY: {
      std::unique_ptr<base::DictionaryValue> result(
          new base::DictionaryValue());
      for (RegistryDict::ValueMap::const_iterator entry(values_.begin());
           entry != values_.end(); ++entry) {
        Schema subschema =
            schema.valid() ? schema.GetProperty(entry->first) : Schema();
        std::unique_ptr<base::Value> converted =
            ConvertValue(*entry->second, subschema);
        if (converted)
          result->SetWithoutPathExpansion(entry->first, converted.release());
      }
      for (RegistryDict::KeyMap::const_iterator entry(keys_.begin());
           entry != keys_.end(); ++entry) {
        Schema subschema =
            schema.valid() ? schema.GetProperty(entry->first) : Schema();
        std::unique_ptr<base::Value> converted =
            entry->second->ConvertToJSON(subschema);
        if (converted)
          result->SetWithoutPathExpansion(entry->first, converted.release());
      }
      return std::move(result);
    }
    case base::Value::Type::LIST: {
      std::unique_ptr<base::ListValue> result(new base::ListValue());
      Schema item_schema = schema.valid() ? schema.GetItems() : Schema();
      for (RegistryDict::KeyMap::const_iterator entry(keys_.begin());
           entry != keys_.end(); ++entry) {
        if (!IsKeyNumerical(entry->first))
          continue;
        std::unique_ptr<base::Value> converted =
            entry->second->ConvertToJSON(item_schema);
        if (converted)
          result->Append(std::move(converted));
      }
      for (RegistryDict::ValueMap::const_iterator entry(values_.begin());
           entry != values_.end(); ++entry) {
        if (!IsKeyNumerical(entry->first))
          continue;
        std::unique_ptr<base::Value> converted =
            ConvertValue(*entry->second, item_schema);
        if (converted)
          result->Append(std::move(converted));
      }
      return std::move(result);
    }
    default:
      LOG(WARNING) << "Can't convert registry key to schema type " << type;
  }

  return nullptr;
}
#endif  // #if defined(OS_WIN)
}  // namespace policy
