|
|
|
@ -1,3 +1,7 @@
|
|
|
|
|
//
|
|
|
|
|
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
#import "NBAsYouTypeFormatter.h"
|
|
|
|
|
#import "NBPhoneNumber.h"
|
|
|
|
|
#import "PhoneNumber.h"
|
|
|
|
@ -9,8 +13,8 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
@implementation PhoneNumber
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)phoneNumberFromText:(NSString *)text andRegion:(NSString *)regionCode {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
assert(regionCode != nil);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
OWSAssert(regionCode != nil);
|
|
|
|
|
|
|
|
|
|
NBPhoneNumberUtil *phoneUtil = [PhoneNumberUtil sharedUtil].nbPhoneNumberUtil;
|
|
|
|
|
|
|
|
|
@ -36,7 +40,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)phoneNumberFromUserSpecifiedText:(NSString *)text {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
|
|
|
|
|
return [PhoneNumber phoneNumberFromText:text andRegion:[self defaultRegionCode]];
|
|
|
|
|
}
|
|
|
|
@ -56,11 +60,11 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)phoneNumberFromE164:(NSString *)text {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
assert([text hasPrefix:COUNTRY_CODE_PREFIX]);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
OWSAssert([text hasPrefix:COUNTRY_CODE_PREFIX]);
|
|
|
|
|
PhoneNumber *number = [PhoneNumber phoneNumberFromText:text andRegion:@"ZZ"];
|
|
|
|
|
|
|
|
|
|
assert(number != nil);
|
|
|
|
|
OWSAssert(number != nil);
|
|
|
|
|
return number;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -98,14 +102,14 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)tryParsePhoneNumberFromText:(NSString *)text fromRegion:(NSString *)regionCode {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
assert(regionCode != nil);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
OWSAssert(regionCode != nil);
|
|
|
|
|
|
|
|
|
|
return [self phoneNumberFromText:text andRegion:regionCode];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)tryParsePhoneNumberFromUserSpecifiedText:(NSString *)text {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
|
|
|
|
|
if ([text isEqualToString:@""]) {
|
|
|
|
|
return nil;
|
|
|
|
@ -115,6 +119,76 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
return [self phoneNumberFromUserSpecifiedText:sanitizedString];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSArray<PhoneNumber *> *)tryParsePhoneNumbersFromsUserSpecifiedText:(NSString *)text
|
|
|
|
|
clientPhoneNumber:(NSString *)clientPhoneNumber
|
|
|
|
|
{
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
|
|
|
|
|
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
|
|
|
if ([text isEqualToString:@""]) {
|
|
|
|
|
return nil;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NSString *sanitizedString = [self removeFormattingCharacters:text];
|
|
|
|
|
OWSAssert(sanitizedString != nil);
|
|
|
|
|
|
|
|
|
|
NSMutableArray *result = [NSMutableArray new];
|
|
|
|
|
NSMutableSet *phoneNumberSet = [NSMutableSet new];
|
|
|
|
|
void (^tryParsingWithCountryCode)(NSString *, NSString *) = ^(NSString *text,
|
|
|
|
|
NSString *countryCode) {
|
|
|
|
|
PhoneNumber *phoneNumber = [PhoneNumber phoneNumberFromText:text
|
|
|
|
|
andRegion:countryCode];
|
|
|
|
|
if (phoneNumber && [phoneNumber toE164] && ![phoneNumberSet containsObject:[phoneNumber toE164]]) {
|
|
|
|
|
[result addObject:phoneNumber];
|
|
|
|
|
[phoneNumberSet addObject:[phoneNumber toE164]];
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
if ([sanitizedString hasPrefix:@"+"]) {
|
|
|
|
|
// If the text starts with "+", just parse it.
|
|
|
|
|
tryParsingWithCountryCode(sanitizedString, [self defaultRegionCode]);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Order matters; better results should appear first so prefer
|
|
|
|
|
// matches with the same country code as this client's phone number.
|
|
|
|
|
OWSAssert(clientPhoneNumber.length > 0);
|
|
|
|
|
if (clientPhoneNumber.length > 0) {
|
|
|
|
|
NSNumber *callingCodeForLocalNumber = [[PhoneNumber phoneNumberFromE164:clientPhoneNumber] getCountryCode];
|
|
|
|
|
if (callingCodeForLocalNumber != nil) {
|
|
|
|
|
tryParsingWithCountryCode([NSString stringWithFormat:@"+%@%@",
|
|
|
|
|
callingCodeForLocalNumber,
|
|
|
|
|
sanitizedString],
|
|
|
|
|
[self defaultRegionCode]);
|
|
|
|
|
|
|
|
|
|
if ([sanitizedString hasPrefix:[NSString stringWithFormat:@"%d", callingCodeForLocalNumber.intValue]]) {
|
|
|
|
|
// If the text starts with the calling code for the local number, try
|
|
|
|
|
// just adding "+" and parsing it.
|
|
|
|
|
tryParsingWithCountryCode(
|
|
|
|
|
[NSString stringWithFormat:@"+%@", sanitizedString], [self defaultRegionCode]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// It's gratuitous to try all country codes associated with a given
|
|
|
|
|
// calling code, but it can't hurt and this isn't a performance
|
|
|
|
|
// hotspot.
|
|
|
|
|
NSArray *possibleLocalCountryCodes = [PhoneNumberUtil countryCodesFromCallingCode:[NSString stringWithFormat:@"+%@",
|
|
|
|
|
callingCodeForLocalNumber]];
|
|
|
|
|
for (NSString *countryCode in possibleLocalCountryCodes) {
|
|
|
|
|
tryParsingWithCountryCode([NSString stringWithFormat:@"+%@%@",
|
|
|
|
|
callingCodeForLocalNumber,
|
|
|
|
|
sanitizedString],
|
|
|
|
|
countryCode);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Also try matches using the phone's default region.
|
|
|
|
|
tryParsingWithCountryCode(sanitizedString, [self defaultRegionCode]);
|
|
|
|
|
|
|
|
|
|
return result;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (NSString *)removeFormattingCharacters:(NSString *)inputString {
|
|
|
|
|
char outputString[inputString.length + 1];
|
|
|
|
|
|
|
|
|
@ -131,7 +205,7 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ (PhoneNumber *)tryParsePhoneNumberFromE164:(NSString *)text {
|
|
|
|
|
assert(text != nil);
|
|
|
|
|
OWSAssert(text != nil);
|
|
|
|
|
|
|
|
|
|
return [self phoneNumberFromE164:text];
|
|
|
|
|
}
|
|
|
|
|