/** * Attempts to extract a match from a {@code candidate} character sequence. * * @param candidate the candidate text that might contain a phone number * @param offset the offset of {@code candidate} within {@link #text} * @return the match found, null if none can be found */ private PhoneNumberMatch ExtractMatch(String candidate, int offset) { // Skip a match that is more likely a publication page reference or a date. if (PUB_PAGES.Match(candidate).Success || SLASH_SEPARATED_DATES.Match(candidate).Success) { return(null); } // Skip potential time-stamps. if (TIME_STAMPS.Match(candidate).Success) { String followingText = text.ToString().Substring(offset + candidate.Length); if (TIME_STAMPS_SUFFIX.MatchBeginning(followingText).Success) { return(null); } } // Try to come up with a valid match given the entire candidate. String rawString = candidate; PhoneNumberMatch match = ParseAndVerify(rawString, offset); if (match != null) { return(match); } // If that failed, try to find an "inner match" - there might be a phone number within this // candidate. return(ExtractInnerMatch(rawString, offset)); }
private bool MatchesEmergencyNumberHelper(String number, String regionCode, bool allowPrefixMatch) { number = PhoneNumberUtil.ExtractPossibleNumber(number); if (PhoneNumberUtil.PlusCharsPattern.MatchBeginning(number).Success) { // Returns false if the number starts with a plus sign. We don't believe dialing the country // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can // add additional logic here to handle it. return(false); } var metadata = phoneUtil.GetMetadataForRegion(regionCode); if (metadata == null || !metadata.HasEmergency) { return(false); } var emergencyNumberPattern = new PhoneRegex(metadata.Emergency.NationalNumberPattern); var normalizedNumber = PhoneNumberUtil.NormalizeDigitsOnly(number); // In Brazil, it is impossible to append additional digits to an emergency number to dial the // number. return((!allowPrefixMatch || regionCode.Equals("BR")) ? emergencyNumberPattern.MatchAll(normalizedNumber).Success : emergencyNumberPattern.MatchBeginning(normalizedNumber).Success); }
/** * Attempts to extract a match from a {@code candidate} character sequence. * * @param candidate the candidate text that might contain a phone number * @param offset the offset of {@code candidate} within {@link #text} * @return the match found, null if none can be found */ private PhoneNumberMatch ExtractMatch(string candidate, int offset) { // Skip a match that is more likely a publication page reference or a date. if (PubPages.Match(candidate).Success || SlashSeparatedDates.Match(candidate).Success) { return(null); } // Skip potential time-stamps. if (TimeStamps.Match(candidate).Success) { var followingText = text.Substring(offset + candidate.Length); if (TimeStampsSuffix.MatchBeginning(followingText).Success) { return(null); } } // Try to come up with a valid match given the entire candidate. var rawString = candidate; var match = ParseAndVerify(rawString, offset); return(match ?? ExtractInnerMatch(rawString, offset)); // If that failed, try to find an "inner match" - there might be a phone number within this // candidate. }
/** * Parses a phone number from the {@code candidate} using {@link PhoneNumberUtil#parse} and * verifies it matches the requested {@link #leniency}. If parsing and verification succeed, a * corresponding {@link PhoneNumberMatch} is returned, otherwise this method returns null. * * @param candidate the candidate match * @param offset the offset of {@code candidate} within {@link #text} * @return the parsed and validated phone number match, or null */ private PhoneNumberMatch ParseAndVerify(String candidate, int offset) { // Check the candidate doesn't contain any formatting which would indicate that it really // isn't a phone number. if (!MATCHING_BRACKETS.MatchAll(candidate).Success) { return(null); } // If leniency is set to VALID or stricter, we also want to skip numbers that are surrounded // by Latin alphabetic characters, to skip cases like abc8005001234 or 8005001234def. if (leniency >= PhoneNumberUtil.Leniency.VALID) { // If the candidate is not at the start of the text, and does not start with phone-number // punctuation, check the previous character. if (offset > 0 && !LEAD_CLASS.MatchBeginning(candidate).Success) { char previousChar = text[offset - 1]; // We return null if it is a latin letter or an invalid punctuation symbol. if (IsInvalidPunctuationSymbol(previousChar) || IsLatinLetter(previousChar)) { return(null); } } int lastCharIndex = offset + candidate.Length; if (lastCharIndex < text.Length) { char nextChar = text[lastCharIndex]; if (IsInvalidPunctuationSymbol(nextChar) || IsLatinLetter(nextChar)) { return(null); } } } PhoneNumber number; var result = phoneUtil.ParseAndKeepRawInput(candidate, preferredRegion, out number); if (result != ErrorType.NO_ERROR) { return(null); } if (phoneUtil.Verify(leniency, number, candidate, phoneUtil)) { // We used parseAndKeepRawInput to create this number, but for now we don't return the extra // values parsed. TODO: stop clearing all values here and switch all users over // to using rawInput() rather than the rawString() of PhoneNumberMatch. var bnumber = number.ToBuilder(); bnumber.ClearCountryCodeSource(); bnumber.ClearRawInput(); bnumber.ClearPreferredDomesticCarrierCode(); return(new PhoneNumberMatch(offset, candidate, bnumber.Build())); } return(null); }
private bool MatchesEmergencyNumberHelper(String number, String regionCode, bool allowPrefixMatch) { number = PhoneNumberUtil.ExtractPossibleNumber(number); if (PhoneNumberUtil.PLUS_CHARS_PATTERN.MatchBeginning(number).Success) { // Returns false if the number starts with a plus sign. We don't believe dialing the country // code before emergency numbers (e.g. +1911) works, but later, if that proves to work, we can // add additional logic here to handle it. return false; } PhoneMetadata metadata = phoneUtil.GetMetadataForRegion(regionCode); if (metadata == null || !metadata.HasEmergency) { return false; } var emergencyNumberPattern = new PhoneRegex(metadata.Emergency.NationalNumberPattern); String normalizedNumber = PhoneNumberUtil.NormalizeDigitsOnly(number); // In Brazil, it is impossible to append additional digits to an emergency number to dial the // number. return (!allowPrefixMatch || regionCode.Equals("BR")) ? emergencyNumberPattern.MatchAll(normalizedNumber).Success : emergencyNumberPattern.MatchBeginning(normalizedNumber).Success; }
/** * Helper method to check a number against a particular pattern and determine whether it matches, * or is too short or too long. Currently, if a number pattern suggests that numbers of length 7 * and 10 are possible, and a number in between these possible lengths is entered, such as of * length 8, this will return TOO_LONG. */ private ValidationResult TestNumberLengthAgainstPattern(PhoneRegex numberPattern, String number) { if (numberPattern.MatchAll(number).Success) return ValidationResult.IS_POSSIBLE; if (numberPattern.MatchBeginning(number).Success) return ValidationResult.TOO_LONG; return ValidationResult.TOO_SHORT; }
/** * Strips the IDD from the start of the number if present. Helper function used by * maybeStripInternationalPrefixAndNormalize. */ private bool ParsePrefixAsIdd(PhoneRegex iddPattern, StringBuilder number) { var m = iddPattern.MatchBeginning(number.ToString()); if (m.Success) { int matchEnd = m.Index + m.Length; // Only strip this if the first digit after the match is not a 0, since country calling codes // cannot begin with 0. var digitMatcher = CAPTURING_DIGIT_PATTERN.Match(number.ToString().Substring(matchEnd)); //XXX: ToString if (digitMatcher.Success) { String normalizedGroup = NormalizeDigitsOnly(digitMatcher.Groups[1].Value); if (normalizedGroup == "0") return false; } number.Remove(0, matchEnd); return true; } return false; }