private static PhoneNumbers.PhoneNumber ParseFromString(PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string regionCode) { try { return(phoneUtil.Parse(numberString, regionCode)); } catch (NumberParseException) { return(null); } }
/// <summary> /// Returns the PhoneNumbers.PhoneNumber object of the phonenumber /// </summary> /// <param name="phoneUtil">PhoneUtil instance</param> /// <param name="numberString">Phonenumber</param> /// <param name="regionCodes">The region code for global networks</param> /// <returns>Null if it was invalid phonenumber</returns> public static PhoneNumbers.PhoneNumber GetValidMobileNumber(this PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string[] regionCodes) { var number = phoneUtil.GetValidNumber(numberString, regionCodes); if (number == null) { return(null); } return(phoneUtil.GetNumberType(number) == PhoneNumberType.MOBILE ? number : null); }
/// <summary> /// Tries get the PhoneNumber object if the phonenumber is a valid phoneNumber for the regions specified /// </summary> /// <param name="phoneUtil"></param> /// <param name="numberString"></param> /// <param name="regionCodes">The region code for global networks</param> /// <param name="phoneNumber">PhoneNumber object</param> /// <returns>True if successful; else false</returns> public static bool TryGetValidMobileNumber(this PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string[] regionCodes, out PhoneNumbers.PhoneNumber phoneNumber) { phoneNumber = null; var number = phoneUtil.GetValidNumber(numberString, regionCodes); if (number == null) { return(false); } return(phoneUtil.GetNumberType(number) == PhoneNumberType.MOBILE); }
/// <summary> /// Try gets the phonenumber formatted in E164 if it was valid for the first country as specified in order of countries passed in /// </summary> /// <param name="phoneUtil">PhoneNumberUtil instance</param> /// <param name="numberString">The phonenumber to get </param> /// <param name="countryCodes">The countries to check for a valid phonenumber</param> /// <param name="formattedPhoneNumber">The phonenumber formatted in E164</param> /// <returns>True if successfully retrieves the formatted phonenumber; else false</returns> public static bool TryGetFormattedPhoneNumber(this PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string[] countryCodes, out string formattedPhoneNumber) { formattedPhoneNumber = null; foreach (var countryCode in countryCodes) { var phoneNumber = phoneUtil.Parse(numberString, countryCode); if (phoneUtil.IsValidNumber(phoneNumber)) { formattedPhoneNumber = phoneUtil.Format(phoneNumber, PhoneNumberFormat.E164); return(true); } } return(false); }
public PhoneNumberHelper() { Debug.WriteLine(""); Debug.WriteLine("PhoneNumberHelper:Constructor I am being constructed!"); Debug.WriteLine(""); // TODO: Not sure if best place to put this yet, may not matter much Debug.WriteLine(""); Debug.WriteLine("PhoneNumberHelper:Constructor Resetting PhoneNumberUtil Instance and getting a new one."); Debug.WriteLine(""); PhoneNumberUtil.ResetInstance(); _phoneUtil = PhoneNumberUtil.GetInstance( PHONE_NUMBER_META_DATA_FILE_PREFIX, CountryCodeToRegionCodeMap.GetCountryCodeToRegionCodeMap()); }
/// <summary> /// Returns the PhoneNumbers.PhoneNumber object if it is a valid number /// </summary> /// <param name="phoneUtil">PhoneUtil instance</param> /// <param name="numberString">The number to validate against</param> /// <param name="regionCodes">The regions to check</param> /// <returns>Null if phonenumber was invalid</returns> public static PhoneNumbers.PhoneNumber GetValidNumber(this PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string[] regionCodes) { foreach (var regionCode in regionCodes) { var phoneNumber = ParseFromString(phoneUtil, numberString, regionCode); if (phoneNumber == null) { continue; } if (phoneUtil.IsValidNumberForRegion(phoneNumber, regionCode)) { return(phoneNumber); } } return(null); }
/// <summary> /// Tries get a valid number for the regions passed in /// </summary> /// <param name="phoneUtil">PhoneUtil instance</param> /// <param name="numberString">Phonenumber</param> /// <param name="regionCodes">The region code for global networks</param> /// <param name="phoneNumber">PhoneNumbers.PhoneNumber object of the number passed in</param> /// <returns>True if successful; else false</returns> public static bool TryGetValidNumber(this PhoneNumbers.PhoneNumberUtil phoneUtil, string numberString, string[] regionCodes, out PhoneNumbers.PhoneNumber phoneNumber) { phoneNumber = null; foreach (var regionCode in regionCodes) { phoneNumber = ParseFromString(phoneUtil, numberString, regionCode); if (phoneNumber == null) { continue; } if (phoneUtil.IsValidNumberForRegion(phoneNumber, regionCode)) { return(true); } } return(false); }
public void SetUp() { _phoneNumberUtil = PhoneNumberUtil.GetInstance(); }
// @VisibleForTesting public ShortNumberUtil(PhoneNumberUtil util) { phoneUtil = util; }
public ShortNumberUtil() { phoneUtil = PhoneNumberUtil.GetInstance(); }
/** * Used for testing purposes only to reset the PhoneNumberUtil singleton to null. */ public static void ResetInstance() { lock (thisLock) { instance_ = null; } }
public static PhoneNumberUtil GetInstance(String baseFileLocation, Dictionary<int, List<String>> countryCallingCodeToRegionCodeMap) { lock (thisLock) { if (instance_ == null) { instance_ = new PhoneNumberUtil(); instance_.countryCallingCodeToRegionCodeMap_ = countryCallingCodeToRegionCodeMap; instance_.Init(baseFileLocation); } return instance_; } }
public bool Verify(Leniency leniency, PhoneNumber number, String candidate, PhoneNumberUtil util) { switch (leniency) { case Leniency.POSSIBLE: return IsPossibleNumber(number); case Leniency.VALID: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util)) return false; return PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util); } case Leniency.STRICT_GROUPING: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberMatcher.ContainsMoreThanOneSlash(candidate) || !PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.CheckNumberGroupingIsValid( number, candidate, util, (PhoneNumberUtil u, PhoneNumber n, StringBuilder nc, String[] eg) => { return PhoneNumberMatcher.AllNumberGroupsRemainGrouped(u, n, nc, eg); } ); } case Leniency.EXACT_GROUPING: default: { if (!util.IsValidNumber(number) || !PhoneNumberMatcher.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberMatcher.ContainsMoreThanOneSlash(candidate) || !PhoneNumberMatcher.IsNationalPrefixPresentIfRequired(number, util)) { return false; } return PhoneNumberMatcher.CheckNumberGroupingIsValid( number, candidate, util, (PhoneNumberUtil u, PhoneNumber n, StringBuilder normalizedCandidate, String[] expectedNumberGroups) => { return PhoneNumberMatcher.AllNumberGroupsAreExactlyPresent( u, n, normalizedCandidate, expectedNumberGroups); } ); } } }
internal static bool ContainsOnlyValidXChars( PhoneNumber number, String candidate, PhoneNumberUtil util) { // The characters 'x' and 'X' can be (1) a carrier code, in which case they always precede the // national significant number or (2) an extension sign, in which case they always precede the // extension number. We assume a carrier code is more than 1 digit, so the first case has to // have more than 1 consecutive 'x' or 'X', whereas the second case can only have exactly 1 // 'x' or 'X'. We ignore the character if it appears as the last character of the string. for (int index = 0; index < candidate.Length - 1; index++) { char charAtIndex = candidate[index]; if (charAtIndex == 'x' || charAtIndex == 'X') { char charAtNextIndex = candidate[index + 1]; if (charAtNextIndex == 'x' || charAtNextIndex == 'X') { // This is the carrier code case, in which the 'X's always precede the national // significant number. index++; if (util.IsNumberMatch(number, candidate.Substring(index)) != MatchType.NSN_MATCH) { return false; } // This is the extension sign case, in which the 'x' or 'X' should always precede the // extension number. } else if (!PhoneNumberUtil.NormalizeDigitsOnly(candidate.Substring(index)).Equals( number.Extension)) { return false; } } } return true; }
public bool Verify(Leniency leniency, PhoneNumber number, String candidate, PhoneNumberUtil util) { switch (leniency) { case Leniency.POSSIBLE: return IsPossibleNumber(number); case Leniency.VALID: { if (!util.IsValidNumber(number) || !PhoneNumberUtil.ContainsOnlyValidXChars(number, candidate, util)) return false; return PhoneNumberUtil.IsNationalPrefixPresentIfRequired(number, util); } case Leniency.STRICT_GROUPING: { if (!util.IsValidNumber(number) || !PhoneNumberUtil.ContainsOnlyValidXChars(number, candidate, util) || PhoneNumberUtil.ContainsMoreThanOneSlash(candidate) || !PhoneNumberUtil.IsNationalPrefixPresentIfRequired(number, util)) { return false; } // TODO: Evaluate how this works for other locales (testing has been // limited to NANPA regions) and optimise if necessary. String[] formattedNumberGroups = PhoneNumberUtil.GetNationalNumberGroups(util, number); StringBuilder normalizedCandidate = PhoneNumberUtil.NormalizeDigits(candidate, true /* keep strip non-digits */); int fromIndex = 0; // Check each group of consecutive digits are not broken into separate groups in the // {@code candidate} string. for (int i = 0; i < formattedNumberGroups.Length; i++) { // Fails if the substring of {@code candidate} starting from {@code fromIndex} doesn't // contain the consecutive digits in formattedNumberGroups[i]. fromIndex = normalizedCandidate.ToString().IndexOf(formattedNumberGroups[i], fromIndex); if (fromIndex < 0) { return false; } // Moves {@code fromIndex} forward. fromIndex += formattedNumberGroups[i].Length; if (i == 0 && fromIndex < normalizedCandidate.Length) { // We are at the position right after the NDC. if (char.IsDigit(normalizedCandidate[fromIndex])) { // This means there is no formatting symbol after the NDC. In this case, we only // accept the number if there is no formatting symbol at all in the number, except // for extensions. String nationalSignificantNumber = util.GetNationalSignificantNumber(number); return normalizedCandidate.ToString().Substring(fromIndex - formattedNumberGroups[i].Length) .StartsWith(nationalSignificantNumber); } } } // The check here makes sure that we haven't mistakenly already used the extension to // match the last group of the subscriber number. Note the extension cannot have // formatting in-between digits. return normalizedCandidate.ToString().Substring(fromIndex).Contains(number.Extension); } case Leniency.EXACT_GROUPING: default: { if (!util.IsValidNumber(number) || !ContainsOnlyValidXChars(number, candidate, util) || ContainsMoreThanOneSlash(candidate) || !IsNationalPrefixPresentIfRequired(number, util)) { return false; } // TODO: Evaluate how this works for other locales (testing has been // limited to NANPA regions) and optimise if necessary. StringBuilder normalizedCandidate = PhoneNumberUtil.NormalizeDigits(candidate, true /* keep strip non-digits */); String[] candidateGroups = NON_DIGITS_PATTERN.Split(normalizedCandidate.ToString()); // Set this to the last group, skipping it if the number has an extension. int candidateNumberGroupIndex = number.HasExtension ? candidateGroups.Length - 2 : candidateGroups.Length - 1; // First we check if the national significant number is formatted as a block. // We use contains and not equals, since the national significant number may be present with // a prefix such as a national number prefix, or the country code itself. if (candidateGroups.Length == 1 || candidateGroups[candidateNumberGroupIndex].Contains( util.GetNationalSignificantNumber(number))) { return true; } String[] formattedNumberGroups = PhoneNumberUtil.GetNationalNumberGroups(util, number); // Starting from the end, go through in reverse, excluding the first group, and check the // candidate and number groups are the same. for (int formattedNumberGroupIndex = (formattedNumberGroups.Length - 1); formattedNumberGroupIndex > 0 && candidateNumberGroupIndex >= 0; formattedNumberGroupIndex--, candidateNumberGroupIndex--) { if (!candidateGroups[candidateNumberGroupIndex].Equals( formattedNumberGroups[formattedNumberGroupIndex])) { return false; } } // Now check the first group. There may be a national prefix at the start, so we only check // that the candidate group ends with the formatted number group. return (candidateNumberGroupIndex >= 0 && candidateGroups[candidateNumberGroupIndex].EndsWith(formattedNumberGroups[0])); } } }
/** * Helper method to get the national-number part of a number, formatted without any national * prefix, and return it as a set of digit blocks that would be formatted together. */ internal static String[] GetNationalNumberGroups(PhoneNumberUtil util, PhoneNumber number) { // This will be in the format +CC-DG;ext=EXT where DG represents groups of digits. String rfc3966Format = util.Format(number, PhoneNumberFormat.RFC3966); // We remove the extension part from the formatted string before splitting it into different // groups. int endIndex = rfc3966Format.IndexOf(';'); if (endIndex < 0) { endIndex = rfc3966Format.Length; } // The country-code will have a '-' following it. int startIndex = rfc3966Format.IndexOf('-') + 1; return rfc3966Format.Substring(startIndex, endIndex - startIndex).Split('-'); }
internal static bool IsNationalPrefixPresentIfRequired( PhoneNumber number, PhoneNumberUtil util) { // First, check how we deduced the country code. If it was written in international format, // then the national prefix is not required. if (number.CountryCodeSource != CountryCodeSource.FROM_DEFAULT_COUNTRY) { return true; } String phoneNumberRegion = util.GetRegionCodeForCountryCode(number.CountryCode); PhoneMetadata metadata = util.GetMetadataForRegion(phoneNumberRegion); if (metadata == null) { return true; } // Check if a national prefix should be present when formatting this number. String nationalNumber = util.GetNationalSignificantNumber(number); NumberFormat formatRule = util.ChooseFormattingPatternForNumber(metadata.NumberFormatList, nationalNumber); // To do this, we check that a national prefix formatting rule was present and that it wasn't // just the first-group symbol ($1) with punctuation. if ((formatRule != null) && formatRule.NationalPrefixFormattingRule.Length > 0) { if (formatRule.NationalPrefixOptionalWhenFormatting) { // The national-prefix is optional in these cases, so we don't need to check if it was // present. return true; } // Remove the first-group symbol. String candidateNationalPrefixRule = formatRule.NationalPrefixFormattingRule; // We assume that the first-group symbol will never be _before_ the national prefix. candidateNationalPrefixRule = candidateNationalPrefixRule.Substring(0, candidateNationalPrefixRule.IndexOf("${1}")); candidateNationalPrefixRule = PhoneNumberUtil.NormalizeDigitsOnly(candidateNationalPrefixRule); if (candidateNationalPrefixRule.Length == 0) { // National Prefix not needed for this number. return true; } // Normalize the remainder. String rawInputCopy = PhoneNumberUtil.NormalizeDigitsOnly(number.RawInput); StringBuilder rawInput = new StringBuilder(rawInputCopy); // Check if we found a national prefix and/or carrier code at the start of the raw input, // and return the result. return util.MaybeStripNationalPrefixAndCarrierCode(rawInput, metadata, null); } return true; }
static PhoneFormatter() { _util = PhoneNumberUtil.GetInstance(); }
public PhoneNumberService(PhoneNumbers.PhoneNumberUtil phoneNumberUtility) { _fnu = phoneNumberUtility; }