1b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// Copyright (C) 2012 The Libphonenumber Authors
2b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com//
3b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// Licensed under the Apache License, Version 2.0 (the "License");
4b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// you may not use this file except in compliance with the License.
5b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// You may obtain a copy of the License at
6b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com//
7b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// http://www.apache.org/licenses/LICENSE-2.0
8b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com//
9b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// Unless required by applicable law or agreed to in writing, software
10b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// distributed under the License is distributed on an "AS IS" BASIS,
11b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// See the License for the specific language governing permissions and
13b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// limitations under the License.
14b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
15b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// Author: David Yonge-Mallo
16b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
17b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/shortnumberinfo.h"
18b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
19b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include <string.h>
20b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include <iterator>
21b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include <map>
22b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
23b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/base/memory/scoped_ptr.h"
24b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/default_logger.h"
25b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/phonemetadata.pb.h"
26b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/phonenumberutil.h"
27b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/regexp_adapter.h"
28b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/regexp_factory.h"
29b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com#include "phonenumbers/short_metadata.h"
30b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
31b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comnamespace i18n {
32b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comnamespace phonenumbers {
33b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
34b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comusing std::make_pair;
35b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comusing std::map;
36b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comusing std::string;
37b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
38b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.combool LoadCompiledInMetadata(PhoneMetadataCollection* metadata) {
39b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  if (!metadata->ParseFromArray(short_metadata_get(), short_metadata_size())) {
408d8b5b3b2035197795d27573d4cf566b5d9ad689philip.liard@gmail.com    LOG(ERROR) << "Could not parse binary data.";
41b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    return false;
42b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
43b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  return true;
44b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
45b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
46b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
47b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comShortNumberInfo::ShortNumberInfo()
48b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    : phone_util_(*PhoneNumberUtil::GetInstance()),
49b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      region_to_short_metadata_map_(new map<string, PhoneMetadata>()) {
50b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  PhoneMetadataCollection metadata_collection;
51b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  if (!LoadCompiledInMetadata(&metadata_collection)) {
52b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    LOG(DFATAL) << "Could not parse compiled-in metadata.";
53b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    return;
54b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
55b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  for (RepeatedPtrField<PhoneMetadata>::const_iterator it =
56b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com           metadata_collection.metadata().begin();
57b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com       it != metadata_collection.metadata().end();
58b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com       ++it) {
59b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    const string& region_code = it->id();
60b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    region_to_short_metadata_map_->insert(make_pair(region_code, *it));
61b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
62b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
63b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
64b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// Returns a pointer to the phone metadata for the appropriate region or NULL
65b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com// if the region code is invalid or unknown.
66b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.comconst PhoneMetadata* ShortNumberInfo::GetMetadataForRegion(
67b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    const string& region_code) const {
68b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  map<string, PhoneMetadata>::const_iterator it =
69b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      region_to_short_metadata_map_->find(region_code);
70b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  if (it != region_to_short_metadata_map_->end()) {
71b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    return &it->second;
72b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
73b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  return NULL;
74b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
75b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
76b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.combool ShortNumberInfo::ConnectsToEmergencyNumber(const string& number,
77b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    const string& region_code) const {
78b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  return MatchesEmergencyNumberHelper(number, region_code,
79b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      true /* allows prefix match */);
80b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
81b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
82b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.combool ShortNumberInfo::IsEmergencyNumber(const string& number,
83b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    const string& region_code) const {
84b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  return MatchesEmergencyNumberHelper(number, region_code,
85b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      false /* doesn't allow prefix match */);
86b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
87b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
88b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.combool ShortNumberInfo::MatchesEmergencyNumberHelper(const string& number,
89b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    const string& region_code, bool allow_prefix_match) const {
90b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  string extracted_number;
91b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  phone_util_.ExtractPossibleNumber(number, &extracted_number);
92b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  if (phone_util_.StartsWithPlusCharsPattern(extracted_number)) {
93b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    // Returns false if the number starts with a plus sign. We don't believe
94b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    // dialing the country code before emergency numbers (e.g. +1911) works,
95b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    // but later, if that proves to work, we can add additional logic here to
96b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    // handle it.
97b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    return false;
98b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
99b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  const PhoneMetadata* metadata = GetMetadataForRegion(region_code);
100b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  if (!metadata || !metadata->has_emergency()) {
101b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com    return false;
102b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  }
103b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  const scoped_ptr<const AbstractRegExpFactory> regexp_factory(
104b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      new RegExpFactory());
105b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  const scoped_ptr<const RegExp> emergency_number_pattern(
106b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      regexp_factory->CreateRegExp(
107b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com          metadata->emergency().national_number_pattern()));
108b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  phone_util_.NormalizeDigitsOnly(&extracted_number);
109b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  const scoped_ptr<RegExpInput> normalized_number_input(
110b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      regexp_factory->CreateInput(extracted_number));
111b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
112b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  // In Brazil and Chile, emergency numbers don't work when additional digits
113b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  // are appended.
114b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com  return (!allow_prefix_match ||
115b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      region_code == "BR" || region_code == "CL")
116b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      ? emergency_number_pattern->FullMatch(extracted_number)
117b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com      : emergency_number_pattern->Consume(normalized_number_input.get());
118b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}
119b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com
120b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}  // namespace phonenumbers
121b3bfbbcb458043ddaaa1099b776014ba0968704dlararennie@google.com}  // namespace i18n
122