// 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/cellular/mobile_operator_info_impl.h"

#include <regex.h>

#include <memory>
#include <utility>

#include <base/bind.h>
#include <base/files/file_util.h>
#include <base/strings/string_util.h>
#include <chromeos/dbus/service_constants.h>
#include <google/protobuf/repeated_field.h>

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

using base::Bind;
using base::FilePath;
using base::PathExists;
using google::protobuf::RepeatedPtrField;
using google::protobuf::io::CopyingInputStreamAdaptor;
using shill::mobile_operator_db::Data;
using shill::mobile_operator_db::Filter;
using shill::mobile_operator_db::LocalizedName;
using shill::mobile_operator_db::MobileAPN;
using shill::mobile_operator_db::MobileNetworkOperator;
using shill::mobile_operator_db::MobileOperatorDB;
using shill::mobile_operator_db::MobileVirtualNetworkOperator;
using std::string;
using std::vector;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kCellular;
static string ObjectID(const MobileOperatorInfoImpl* m) {
  return "(mobile_operator_info_impl)";
}
}  // namespace Logging

// static
const char MobileOperatorInfoImpl::kDefaultDatabasePath[] =
    "/usr/share/shill/serviceproviders.pbf";
// Warning: changing this can break overlays!
const char MobileOperatorInfoImpl::kOverrideDatabasePath[] =
    "/usr/share/shill/serviceproviders-override.pbf";
const int MobileOperatorInfoImpl::kMCCMNCMinLen = 5;

namespace {

// Wrap some low level functions from the GNU regex librarly.
string GetRegError(int code, const regex_t* compiled) {
  size_t length = regerror(code, compiled, nullptr, 0);
  vector<char> buffer(length);
  DCHECK_EQ(length, regerror(code, compiled, buffer.data(), length));
  return buffer.data();
}

string GetApnAuthentication(const MobileAPN& apn) {
  if (apn.has_authentication()) {
    switch (apn.authentication()) {
      case mobile_operator_db::MobileAPN_Authentication_PAP:
        return kApnAuthenticationPap;
      case mobile_operator_db::MobileAPN_Authentication_CHAP:
        return kApnAuthenticationChap;
      default:
        break;
    }
  }
  return string();
}

}  // namespace

MobileOperatorInfoImpl::MobileOperatorInfoImpl(EventDispatcher* dispatcher,
                                               const string& info_owner,
                                               const FilePath& default_db_path,
                                               const FilePath& override_db_path)
    : dispatcher_(dispatcher),
      info_owner_(info_owner),
      operator_code_type_(OperatorCodeType::kUnknown),
      current_mno_(nullptr),
      current_mvno_(nullptr),
      requires_roaming_(false),
      mtu_(0),
      user_olp_empty_(true),
      weak_ptr_factory_(this) {
  // Overrides need to be installed before defaults
  if (PathExists(override_db_path)) {
    AddDatabasePath(override_db_path);
  }
  AddDatabasePath(default_db_path);
}

MobileOperatorInfoImpl::MobileOperatorInfoImpl(EventDispatcher* dispatcher,
                                               const string& info_owner)
    : MobileOperatorInfoImpl::MobileOperatorInfoImpl(
          dispatcher,
          info_owner,
          base::FilePath(kDefaultDatabasePath),
          base::FilePath(kOverrideDatabasePath)) {}

MobileOperatorInfoImpl::~MobileOperatorInfoImpl() = default;

void MobileOperatorInfoImpl::ClearDatabasePaths() {
  database_paths_.clear();
}

void MobileOperatorInfoImpl::AddDatabasePath(const FilePath& absolute_path) {
  database_paths_.push_back(absolute_path);
}

bool MobileOperatorInfoImpl::Init() {
  // |database_| is guaranteed to be set once |Init| is called.
  database_.reset(new MobileOperatorDB());

  bool found_databases = false;
  for (const auto& database_path : database_paths_) {
    const char* database_path_cstr = database_path.value().c_str();
    std::unique_ptr<CopyingInputStreamAdaptor> database_stream;
    database_stream.reset(protobuf_lite_file_input_stream(database_path_cstr));
    if (!database_stream) {
      LOG(ERROR) << "Failed to read mobile operator database: "
                 << database_path_cstr;
      continue;
    }

    MobileOperatorDB database;
    if (!database.ParseFromZeroCopyStream(database_stream.get())) {
      LOG(ERROR) << "Could not parse mobile operator database: "
                 << database_path_cstr;
      continue;
    }
    SLOG(this, 1) << "Successfully loaded database: " << database_path_cstr;
    // Collate loaded databases into one as they're found.
    // TODO(pprabhu) This merge might be very costly. Determine if we need to
    // implement move semantics / bias the merge to use the largest database
    // as the base database and merge other databases into it.
    database_->MergeFrom(database);
    found_databases = true;
  }

  if (!found_databases) {
    LOG(ERROR) << "Could not read any mobile operator database. "
               << "Will not be able to determine MVNO.";
    return false;
  }

  PreprocessDatabase();
  return true;
}

void MobileOperatorInfoImpl::AddObserver(
    MobileOperatorInfo::Observer* observer) {
  observers_.AddObserver(observer);
}

void MobileOperatorInfoImpl::RemoveObserver(
    MobileOperatorInfo::Observer* observer) {
  observers_.RemoveObserver(observer);
}

bool MobileOperatorInfoImpl::IsMobileNetworkOperatorKnown() const {
  return (current_mno_ != nullptr);
}

bool MobileOperatorInfoImpl::IsMobileVirtualNetworkOperatorKnown() const {
  return (current_mvno_ != nullptr);
}

// ///////////////////////////////////////////////////////////////////////////
// Getters.
const string& MobileOperatorInfoImpl::info_owner() const {
  return info_owner_;
}

const string& MobileOperatorInfoImpl::uuid() const {
  return uuid_;
}

const string& MobileOperatorInfoImpl::operator_name() const {
  // TODO(pprabhu) I'm not very sure yet what is the right thing to do here.
  // It is possible that we obtain a name OTA, and then using some other
  // information (say the iccid range), determine that this is an MVNO. In
  // that case, we may want to *override* |user_operator_name_| by the name
  // obtained from the DB for the MVNO.
  return operator_name_;
}

const string& MobileOperatorInfoImpl::country() const {
  return country_;
}

const string& MobileOperatorInfoImpl::mccmnc() const {
  return mccmnc_;
}

const string& MobileOperatorInfoImpl::MobileOperatorInfoImpl::sid() const {
  return sid_;
}

const string& MobileOperatorInfoImpl::nid() const {
  return (user_nid_ == "") ? nid_ : user_nid_;
}

const vector<string>& MobileOperatorInfoImpl::mccmnc_list() const {
  return mccmnc_list_;
}

const vector<string>& MobileOperatorInfoImpl::sid_list() const {
  return sid_list_;
}

const vector<MobileOperatorInfo::LocalizedName>&
MobileOperatorInfoImpl::operator_name_list() const {
  return operator_name_list_;
}

const std::vector<std::unique_ptr<MobileOperatorInfo::MobileAPN>>&
MobileOperatorInfoImpl::apn_list() const {
  return apn_list_;
}

const vector<MobileOperatorInfo::OnlinePortal>&
MobileOperatorInfoImpl::olp_list() const {
  return olp_list_;
}

const string& MobileOperatorInfoImpl::activation_code() const {
  return activation_code_;
}

bool MobileOperatorInfoImpl::requires_roaming() const {
  return requires_roaming_;
}

int32_t MobileOperatorInfoImpl::mtu() const {
  return mtu_;
}

// ///////////////////////////////////////////////////////////////////////////
// Functions used to notify this object of operator data changes.
void MobileOperatorInfoImpl::UpdateIMSI(const string& imsi) {
  bool operator_changed = false;
  if (user_imsi_ == imsi) {
    return;
  }

  user_imsi_ = imsi;

  if (!user_mccmnc_.empty()) {
    if (!base::StartsWith(imsi, user_mccmnc_,
                          base::CompareCase::INSENSITIVE_ASCII)) {
      LOG(WARNING) << "MCCMNC [" << user_mccmnc_ << "] is not a substring of "
                   << "the IMSI [" << imsi << "].";
    }
  } else {
    // Attempt to determine the MNO from IMSI since MCCMNC is absent.
    AppendToCandidatesByMCCMNC(imsi.substr(0, kMCCMNCMinLen));
    AppendToCandidatesByMCCMNC(imsi.substr(0, kMCCMNCMinLen + 1));
    if (!candidates_by_operator_code_.empty()) {
      // We found some candidates using IMSI.
      operator_changed |= UpdateMNO();
    }
  }
  operator_changed |= UpdateMVNO();

  // No special notification should be sent for this property, since the object
  // does not expose |imsi| as a property at all.
  if (operator_changed) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateICCID(const string& iccid) {
  if (user_iccid_ == iccid) {
    return;
  }

  user_iccid_ = iccid;
  // |iccid| is not an exposed property, so don't raise event for just this
  // property update.
  if (UpdateMVNO()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateMCCMNC(const string& mccmnc) {
  if (user_mccmnc_ == mccmnc) {
    return;
  }

  user_mccmnc_ = mccmnc;
  HandleMCCMNCUpdate();
  candidates_by_operator_code_.clear();
  AppendToCandidatesByMCCMNC(mccmnc);

  // Always update M[V]NO, even if we found no candidates, since we might have
  // lost some candidates due to an incorrect MCCMNC.
  bool operator_changed = false;
  operator_changed |= UpdateMNO();
  operator_changed |= UpdateMVNO();
  if (operator_changed || ShouldNotifyPropertyUpdate()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateSID(const string& sid) {
  if (user_sid_ == sid) {
    return;
  }

  user_sid_ = sid;
  HandleSIDUpdate();
  candidates_by_operator_code_.clear();
  AppendToCandidatesBySID(sid);

  // Always update M[V]NO, even if we found no candidates, since we might have
  // lost some candidates due to an incorrect SID.
  bool operator_changed = false;
  operator_changed |= UpdateMNO();
  operator_changed |= UpdateMVNO();
  if (operator_changed || ShouldNotifyPropertyUpdate()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateNID(const string& nid) {
  if (user_nid_ == nid) {
    return;
  }

  user_nid_ = nid;
  if (UpdateMVNO() || ShouldNotifyPropertyUpdate()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateOperatorName(const string& operator_name) {
  bool operator_changed = false;
  if (user_operator_name_ == operator_name) {
    return;
  }

  user_operator_name_ = operator_name;
  HandleOperatorNameUpdate();

  // We must update the candidates by name anyway.
  StringToMNOListMap::const_iterator cit =
      name_to_mnos_.find(NormalizeOperatorName(operator_name));
  candidates_by_name_.clear();
  if (cit != name_to_mnos_.end()) {
    candidates_by_name_ = cit->second;
    // We should never have inserted an empty vector into the map.
    DCHECK(!candidates_by_name_.empty());
  } else {
    LOG(INFO) << "Operator name [" << operator_name << "] "
              << "(Normalized: [" << NormalizeOperatorName(operator_name)
              << "]) does not match any MNO.";
  }

  operator_changed |= UpdateMNO();
  operator_changed |= UpdateMVNO();
  if (operator_changed || ShouldNotifyPropertyUpdate()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::UpdateOnlinePortal(const string& url,
                                                const string& method,
                                                const string& post_data) {
  if (!user_olp_empty_ && user_olp_.url == url && user_olp_.method == method &&
      user_olp_.post_data == post_data) {
    return;
  }

  user_olp_empty_ = false;
  user_olp_.url = url;
  user_olp_.method = method;
  user_olp_.post_data = post_data;
  HandleOnlinePortalUpdate();

  // OnlinePortal is never used in deciding M[V]NO.
  if (ShouldNotifyPropertyUpdate()) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::Reset() {
  bool should_notify = current_mno_ != nullptr || current_mvno_ != nullptr;

  current_mno_ = nullptr;
  current_mvno_ = nullptr;
  operator_code_type_ = OperatorCodeType::kUnknown;
  candidates_by_operator_code_.clear();
  candidates_by_name_.clear();

  ClearDBInformation();

  user_imsi_.clear();
  user_iccid_.clear();
  user_mccmnc_.clear();
  user_sid_.clear();
  user_nid_.clear();
  user_operator_name_.clear();
  user_olp_empty_ = true;
  user_olp_.url.clear();
  user_olp_.method.clear();
  user_olp_.post_data.clear();

  if (should_notify) {
    PostNotifyOperatorChanged();
  }
}

void MobileOperatorInfoImpl::PreprocessDatabase() {
  SLOG(this, 3) << __func__;

  mccmnc_to_mnos_.clear();
  sid_to_mnos_.clear();
  name_to_mnos_.clear();

  const RepeatedPtrField<MobileNetworkOperator>& mnos = database_->mno();
  for (const auto& mno : mnos) {
    // MobileNetworkOperator::data is a required field.
    DCHECK(mno.has_data());
    const Data& data = mno.data();

    const RepeatedPtrField<string>& mccmncs = data.mccmnc();
    for (const auto& mccmnc : mccmncs) {
      InsertIntoStringToMNOListMap(&mccmnc_to_mnos_, mccmnc, &mno);
    }

    const RepeatedPtrField<string>& sids = data.sid();
    for (const auto& sid : sids) {
      InsertIntoStringToMNOListMap(&sid_to_mnos_, sid, &mno);
    }

    const RepeatedPtrField<LocalizedName>& localized_names =
        data.localized_name();
    for (const auto& localized_name : localized_names) {
      // LocalizedName::name is a required field.
      DCHECK(localized_name.has_name());
      InsertIntoStringToMNOListMap(
          &name_to_mnos_, NormalizeOperatorName(localized_name.name()), &mno);
    }
  }
}

// This function assumes that duplicate |values| are never inserted for the
// same |key|. If you do that, the function is too dumb to deduplicate the
// |value|s, and two copies will get stored.
void MobileOperatorInfoImpl::InsertIntoStringToMNOListMap(
    StringToMNOListMap* table,
    const string& key,
    const MobileNetworkOperator* value) {
  (*table)[key].push_back(value);
}

bool MobileOperatorInfoImpl::AppendToCandidatesByMCCMNC(const string& mccmnc) {
  // First check that we haven't determined candidates using SID.
  if (operator_code_type_ == OperatorCodeType::kSID) {
    LOG(WARNING) << "SID update will be overridden by the MCCMNC update for "
                    "determining MNO.";
    candidates_by_operator_code_.clear();
  }

  operator_code_type_ = OperatorCodeType::kMCCMNC;
  StringToMNOListMap::const_iterator cit = mccmnc_to_mnos_.find(mccmnc);
  if (cit == mccmnc_to_mnos_.end()) {
    LOG(WARNING) << "Unknown MCCMNC value [" << mccmnc << "].";
    return false;
  }

  // We should never have inserted an empty vector into the map.
  DCHECK(!cit->second.empty());
  for (const auto& mno : cit->second) {
    candidates_by_operator_code_.push_back(mno);
  }
  return true;
}

bool MobileOperatorInfoImpl::AppendToCandidatesBySID(const string& sid) {
  // First check that we haven't determined candidates using MCCMNC.
  if (operator_code_type_ == OperatorCodeType::kMCCMNC) {
    LOG(WARNING) << "MCCMNC update will be overriden by the SID update for "
                    "determining MNO.";
    candidates_by_operator_code_.clear();
  }

  operator_code_type_ = OperatorCodeType::kSID;
  StringToMNOListMap::const_iterator cit = sid_to_mnos_.find(sid);
  if (cit == sid_to_mnos_.end()) {
    LOG(WARNING) << "Unknown SID value [" << sid << "].";
    return false;
  }

  // We should never have inserted an empty vector into the map.
  DCHECK(!cit->second.empty());
  for (const auto& mno : cit->second) {
    candidates_by_operator_code_.push_back(mno);
  }
  return true;
}

string MobileOperatorInfoImpl::OperatorCodeString() const {
  switch (operator_code_type_) {
    case OperatorCodeType::kMCCMNC:
      return "MCCMNC";
    case OperatorCodeType::kSID:
      return "SID";
    case OperatorCodeType::kUnknown:
      return "UnknownOperatorCodeType";
  }
}

bool MobileOperatorInfoImpl::UpdateMNO() {
  SLOG(this, 3) << __func__;
  const MobileNetworkOperator* candidate = nullptr;

  // The only way |operator_code_type_| can be |OperatorCodeType::kUnknown| is
  // that we haven't received any operator_code updates yet.
  DCHECK(operator_code_type_ == OperatorCodeType::kMCCMNC ||
         operator_code_type_ == OperatorCodeType::kSID ||
         (user_mccmnc_.empty() && user_sid_.empty()));

  // TODO(pprabhu) Remove this despicable hack. (crosbug.com/p/30200)
  // We currently have no principled way to handle an MVNO for which the
  // database does not have MCCMNC data. It is possible that some other MNO
  // matches the MCCMNC, while the MVNO matches the operator name. We special
  // case one such operator here and override all the logic below.
  const char kCubicUUID[] = "2de39b14-c3ba-4143-abb5-c67a390034ee";
  for (auto candidate_by_name : candidates_by_name_) {
    CHECK(candidate_by_name->has_data());
    CHECK(candidate_by_name->data().has_uuid());
    if (candidate_by_name->data().uuid() == kCubicUUID) {
      current_mno_ = candidate_by_name;
      RefreshDBInformation();
      return true;
    }
  }

  if (candidates_by_operator_code_.size() == 1) {
    candidate = candidates_by_operator_code_[0];
    if (!candidates_by_name_.empty()) {
      bool found_match = false;
      for (auto candidate_by_name : candidates_by_name_) {
        if (candidate_by_name == candidate) {
          found_match = true;
          break;
        }
      }
      if (!found_match) {
        const string& operator_code =
            (operator_code_type_ == OperatorCodeType::kMCCMNC) ? user_mccmnc_
                                                               : user_sid_;
        SLOG(this, 1) << "MNO determined by " << OperatorCodeString() << " ["
                      << operator_code
                      << "] does not match any suggested by name["
                      << user_operator_name_ << "]. " << OperatorCodeString()
                      << " overrides name!";
      }
    }
  } else if (candidates_by_operator_code_.size() > 1) {
    // Try to find an intersection of the two candidate lists. These lists
    // should be almost always of length 1. Simply iterate.
    for (auto candidate_by_mccmnc : candidates_by_operator_code_) {
      for (auto candidate_by_name : candidates_by_name_) {
        if (candidate_by_mccmnc == candidate_by_name) {
          candidate = candidate_by_mccmnc;
          break;
        }
      }
      if (candidate != nullptr) {
        break;
      }
    }
    if (candidate == nullptr) {
      const string& operator_code =
          (operator_code_type_ == OperatorCodeType::kMCCMNC) ? user_mccmnc_
                                                             : user_sid_;
      SLOG(this, 1) << "MNOs suggested by " << OperatorCodeString() << " ["
                    << operator_code
                    << "] are multiple and disjoint from those suggested "
                    << "by name[" << user_operator_name_ << "].";
      candidate = PickOneFromDuplicates(candidates_by_operator_code_);
    }
  } else {  // candidates_by_operator_code_.size() == 0
    // Special case: In case we had a *wrong* operator_code update, we want
    // to override the suggestions from |user_operator_name_|. We should not
    // determine an MNO in this case.
    if ((operator_code_type_ == OperatorCodeType::kMCCMNC &&
         !user_mccmnc_.empty()) ||
        (operator_code_type_ == OperatorCodeType::kSID && !user_sid_.empty())) {
      SLOG(this, 1) << "A non-matching " << OperatorCodeString() << " "
                    << "was reported by the user."
                    << "We fail the MNO match in this case.";
    } else if (candidates_by_name_.size() == 1) {
      candidate = candidates_by_name_[0];
    } else if (candidates_by_name_.size() > 1) {
      SLOG(this, 1) << "Multiple MNOs suggested by name[" << user_operator_name_
                    << "], and none by MCCMNC.";
      candidate = PickOneFromDuplicates(candidates_by_name_);
    } else {  // candidates_by_name_.size() == 0
      SLOG(this, 1) << "No candidates suggested.";
    }
  }

  if (candidate != current_mno_) {
    current_mno_ = candidate;
    RefreshDBInformation();
    return true;
  }
  return false;
}

bool MobileOperatorInfoImpl::UpdateMVNO() {
  SLOG(this, 3) << __func__;

  vector<const MobileVirtualNetworkOperator*> candidate_mvnos;
  for (const auto& mvno : database_->mvno()) {
    candidate_mvnos.push_back(&mvno);
  }
  if (current_mno_) {
    for (const auto& mvno : current_mno_->mvno()) {
      candidate_mvnos.push_back(&mvno);
    }
  }

  for (const auto* candidate_mvno : candidate_mvnos) {
    bool passed_all_filters = true;
    for (const auto& filter : candidate_mvno->mvno_filter()) {
      if (!FilterMatches(filter)) {
        passed_all_filters = false;
        break;
      }
    }
    if (passed_all_filters) {
      if (current_mvno_ == candidate_mvno) {
        return false;
      }
      current_mvno_ = candidate_mvno;
      RefreshDBInformation();
      return true;
    }
  }

  // We did not find any valid MVNO.
  if (current_mvno_ != nullptr) {
    current_mvno_ = nullptr;
    RefreshDBInformation();
    return true;
  }
  return false;
}

const MobileNetworkOperator* MobileOperatorInfoImpl::PickOneFromDuplicates(
    const vector<const MobileNetworkOperator*>& duplicates) const {
  if (duplicates.empty())
    return nullptr;

  for (auto candidate : duplicates) {
    if (candidate->earmarked()) {
      SLOG(this, 2) << "Picking earmarked candidate: "
                    << candidate->data().uuid();
      return candidate;
    }
  }
  SLOG(this, 2) << "No earmarked candidate found. Choosing the first.";
  return duplicates[0];
}

bool MobileOperatorInfoImpl::FilterMatches(const Filter& filter) {
  DCHECK(filter.has_regex());
  string to_match;
  switch (filter.type()) {
    case mobile_operator_db::Filter_Type_IMSI:
      to_match = user_imsi_;
      break;
    case mobile_operator_db::Filter_Type_ICCID:
      to_match = user_iccid_;
      break;
    case mobile_operator_db::Filter_Type_SID:
      to_match = user_sid_;
      break;
    case mobile_operator_db::Filter_Type_OPERATOR_NAME:
      to_match = user_operator_name_;
      break;
    case mobile_operator_db::Filter_Type_MCCMNC:
      to_match = user_mccmnc_;
      break;
    default:
      SLOG(this, 1) << "Unknown filter type [" << filter.type() << "]";
      return false;
  }
  // |to_match| can be empty if we have no *user provided* information of the
  // correct type.
  if (to_match.empty()) {
    SLOG(this, 2) << "Nothing to match against (filter: " << filter.regex()
                  << ").";
    return false;
  }

  // Must use GNU regex implementation, since C++11 implementation is
  // incomplete.
  regex_t filter_regex;
  string filter_regex_str = filter.regex();

  // |regexec| matches the given regular expression to a substring of the
  // given query string. Ensure that |filter_regex_str| uses anchors to
  // accept only a full match.
  if (filter_regex_str.front() != '^') {
    filter_regex_str = "^" + filter_regex_str;
  }
  if (filter_regex_str.back() != '$') {
    filter_regex_str = filter_regex_str + "$";
  }

  int regcomp_error = regcomp(&filter_regex, filter_regex_str.c_str(),
                              REG_EXTENDED | REG_NOSUB);
  if (regcomp_error) {
    LOG(WARNING) << "Could not compile regex '" << filter.regex() << "'. "
                 << "Error returned: "
                 << GetRegError(regcomp_error, &filter_regex) << ". ";
    regfree(&filter_regex);
    return false;
  }

  int regexec_error = regexec(&filter_regex, to_match.c_str(), 0, nullptr, 0);
  if (regexec_error) {
    string error_string;
    error_string = GetRegError(regcomp_error, &filter_regex);
    SLOG(this, 2) << "Could not match string " << to_match << " "
                  << "against regexp " << filter.regex() << ". "
                  << "Error returned: " << error_string << ". ";
    regfree(&filter_regex);
    return false;
  }
  regfree(&filter_regex);
  return true;
}

void MobileOperatorInfoImpl::RefreshDBInformation() {
  ClearDBInformation();

  if (current_mno_ == nullptr) {
    return;
  }

  // |data| is a required field.
  DCHECK(current_mno_->has_data());
  SLOG(this, 2) << "Reloading MNO data.";
  ReloadData(current_mno_->data());

  if (current_mvno_ != nullptr) {
    // |data| is a required field.
    DCHECK(current_mvno_->has_data());
    SLOG(this, 2) << "Reloading MVNO data.";
    ReloadData(current_mvno_->data());
  }
}

void MobileOperatorInfoImpl::ClearDBInformation() {
  uuid_.clear();
  country_.clear();
  nid_.clear();
  mccmnc_list_.clear();
  HandleMCCMNCUpdate();
  sid_list_.clear();
  HandleSIDUpdate();
  operator_name_list_.clear();
  HandleOperatorNameUpdate();
  apn_list_.clear();
  olp_list_.clear();
  raw_olp_list_.clear();
  HandleOnlinePortalUpdate();
  activation_code_.clear();
  requires_roaming_ = false;
  mtu_ = 0;
}

void MobileOperatorInfoImpl::ReloadData(const Data& data) {
  SLOG(this, 3) << __func__;
  // |uuid_| is *always* overwritten. An MNO and MVNO should not share the
  // |uuid_|.
  CHECK(data.has_uuid());
  uuid_ = data.uuid();

  if (data.has_country()) {
    country_ = data.country();
  }

  if (data.localized_name_size() > 0) {
    operator_name_list_.clear();
    for (const auto& localized_name : data.localized_name()) {
      operator_name_list_.push_back(
          {localized_name.name(), localized_name.language()});
    }
    HandleOperatorNameUpdate();
  }

  if (data.has_requires_roaming()) {
    requires_roaming_ = data.requires_roaming();
  }

  if (data.mtu()) {
    mtu_ = data.mtu();
  }

  if (data.olp_size() > 0) {
    raw_olp_list_.clear();
    // Copy the olp list so we can mutate it.
    for (const auto& olp : data.olp()) {
      raw_olp_list_.push_back(olp);
    }
    HandleOnlinePortalUpdate();
  }

  if (data.mccmnc_size() > 0) {
    mccmnc_list_.clear();
    for (const auto& mccmnc : data.mccmnc()) {
      mccmnc_list_.push_back(mccmnc);
    }
    HandleMCCMNCUpdate();
  }

  if (data.mobile_apn_size() > 0) {
    apn_list_.clear();
    for (const auto& apn_data : data.mobile_apn()) {
      auto apn = std::make_unique<MobileOperatorInfo::MobileAPN>();
      apn->apn = apn_data.apn();
      apn->username = apn_data.username();
      apn->password = apn_data.password();
      for (const auto& localized_name : apn_data.localized_name()) {
        apn->operator_name_list.push_back(
            {localized_name.name(), localized_name.language()});
      }
      apn->authentication = GetApnAuthentication(apn_data);
      apn_list_.push_back(std::move(apn));
    }
  }

  if (data.sid_size() > 0) {
    sid_list_.clear();
    for (const auto& sid : data.sid()) {
      sid_list_.push_back(sid);
    }
    HandleSIDUpdate();
  }

  if (data.has_activation_code()) {
    activation_code_ = data.activation_code();
  }
}

void MobileOperatorInfoImpl::HandleMCCMNCUpdate() {
  if (!user_mccmnc_.empty()) {
    bool append_to_list = true;
    for (const auto& mccmnc : mccmnc_list_) {
      append_to_list &= (user_mccmnc_ != mccmnc);
    }
    if (append_to_list) {
      mccmnc_list_.push_back(user_mccmnc_);
    }
  }

  if (!user_mccmnc_.empty()) {
    mccmnc_ = user_mccmnc_;
  } else if (!mccmnc_list_.empty()) {
    mccmnc_ = mccmnc_list_[0];
  } else {
    mccmnc_.clear();
  }
}

void MobileOperatorInfoImpl::HandleOperatorNameUpdate() {
  if (!user_operator_name_.empty()) {
    bool append_user_operator_name = true;
    for (const auto& localized_name : operator_name_list_) {
      append_user_operator_name &= (user_operator_name_ != localized_name.name);
    }
    if (append_user_operator_name) {
      MobileOperatorInfo::LocalizedName localized_name{user_operator_name_, ""};
      operator_name_list_.push_back(localized_name);
    }
  }

  if (!operator_name_list_.empty()) {
    operator_name_ = operator_name_list_[0].name;
  } else if (!user_operator_name_.empty()) {
    operator_name_ = user_operator_name_;
  } else {
    operator_name_.clear();
  }
}

void MobileOperatorInfoImpl::HandleSIDUpdate() {
  if (!user_sid_.empty()) {
    bool append_user_sid = true;
    for (const auto& sid : sid_list_) {
      append_user_sid &= (user_sid_ != sid);
    }
    if (append_user_sid) {
      sid_list_.push_back(user_sid_);
    }
  }

  if (!user_sid_.empty()) {
    sid_ = user_sid_;
  } else if (!sid_list_.empty()) {
    sid_ = sid_list_[0];
  } else {
    sid_.clear();
  }
}

// Warning: Currently, an MCCMNC/SID update by itself does not result into
// recomputation of the |olp_list_|. This means that if the new MCCMNC/SID
// causes an online portal filter to match, we'll miss that.
// This won't be a problem if either the MNO or the MVNO changes, since data is
// reloaded then.
// This is a corner case that we don't expect to hit, since MCCMNC doesn't
// really change in a running system.
void MobileOperatorInfoImpl::HandleOnlinePortalUpdate() {
  // Always recompute |olp_list_|. We don't expect this list to be big.
  olp_list_.clear();
  for (const auto& raw_olp : raw_olp_list_) {
    if (!raw_olp.has_olp_filter() || FilterMatches(raw_olp.olp_filter())) {
      olp_list_.push_back(MobileOperatorInfo::OnlinePortal{
          raw_olp.url(), (raw_olp.method() == raw_olp.GET) ? "GET" : "POST",
          raw_olp.post_data()});
    }
  }
  if (!user_olp_empty_) {
    bool append_user_olp = true;
    for (const auto& olp : olp_list_) {
      append_user_olp &=
          (olp.url != user_olp_.url || olp.method != user_olp_.method ||
           olp.post_data != user_olp_.post_data);
    }
    if (append_user_olp) {
      olp_list_.push_back(user_olp_);
    }
  }
}

void MobileOperatorInfoImpl::PostNotifyOperatorChanged() {
  SLOG(this, 3) << __func__;
  // If there was an outstanding task, it will get replaced.
  notify_operator_changed_task_.Reset(
      Bind(&MobileOperatorInfoImpl::NotifyOperatorChanged,
           weak_ptr_factory_.GetWeakPtr()));
  dispatcher_->PostTask(FROM_HERE, notify_operator_changed_task_.callback());
}

void MobileOperatorInfoImpl::NotifyOperatorChanged() {
  for (MobileOperatorInfo::Observer& observer : observers_)
    observer.OnOperatorChanged();
}

bool MobileOperatorInfoImpl::ShouldNotifyPropertyUpdate() const {
  return IsMobileNetworkOperatorKnown() ||
         IsMobileVirtualNetworkOperatorKnown();
}

string MobileOperatorInfoImpl::NormalizeOperatorName(const string& name) const {
  string result = base::ToLowerASCII(name);
  base::RemoveChars(result, base::kWhitespaceASCII, &result);
  return result;
}

}  // namespace shill
