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