Fix non-contact lookup for non-US users.

// FREEBIE
pull/1/head
Matthew Chen 8 years ago
parent 7368c5f754
commit e12bd4773a

@ -14,11 +14,25 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable SignalRecipient *)synchronousLookup:(NSString *)identifier error:(NSError **)error;
// This asynchronously updates the SignalRecipient for a given contactId.
// This asynchronously tries to verify whether or not a contact id
// corresponds to a service account.
//
// The failure callback is invoked if the lookup fails _or_ if the
// contact id doesn't correspond to an account.
- (void)lookupIdentifier:(NSString *)identifier
success:(void (^)(SignalRecipient *recipient))success
failure:(void (^)(NSError *error))failure;
// This asynchronously tries to verify whether or not group of possible
// contact ids correspond to service accounts.
//
// The failure callback is only invoked if the lookup fails. Otherwise,
// the success callback is invoked with the (possibly empty) set of contacts
// that were found.
- (void)lookupIdentifiers:(NSArray<NSString *> *)identifiers
success:(void (^)(NSArray<SignalRecipient *> *recipients))success
failure:(void (^)(NSError *error))failure;
- (void)updateSignalContactIntersectionWithABContacts:(NSArray<Contact *> *)abContacts
success:(void (^)())success
failure:(void (^)(NSError *error))failure;

@ -60,7 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
failure(OWSErrorWithCodeDescription(OWSErrorCodeInvalidMethodParameters, @"Cannot lookup nil identifier"));
return;
}
[self contactIntersectionWithSet:[NSSet setWithObject:identifier]
success:^(NSSet<NSString *> *_Nonnull matchedIds) {
if (matchedIds.count == 1) {
@ -72,6 +72,31 @@ NS_ASSUME_NONNULL_BEGIN
failure:failure];
}
- (void)lookupIdentifiers:(NSArray<NSString *> *)identifiers
success:(void (^)(NSArray<SignalRecipient *> *recipients))success
failure:(void (^)(NSError *error))failure
{
if (identifiers.count < 1) {
OWSAssert(NO);
failure(OWSErrorWithCodeDescription(OWSErrorCodeInvalidMethodParameters, @"Cannot lookup zero identifiers"));
return;
}
[self contactIntersectionWithSet:[NSSet setWithArray:identifiers]
success:^(NSSet<NSString *> *_Nonnull matchedIds) {
if (matchedIds.count == 1) {
NSMutableArray<SignalRecipient *> *recipients = [NSMutableArray new];
for (NSString *identifier in matchedIds) {
[recipients addObject:[SignalRecipient recipientWithTextSecureIdentifier:identifier]];
}
success(recipients);
} else {
failure(OWSErrorMakeNoSuchSignalRecipientError());
}
}
failure:failure];
}
- (void)updateSignalContactIntersectionWithABContacts:(NSArray<Contact *> *)abContacts
success:(void (^)())success
failure:(void (^)(NSError *error))failure {

@ -1,3 +1,7 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <libPhoneNumber-iOS/NBPhoneNumberUtil.h>
@ -24,6 +28,14 @@
+ (PhoneNumber *)tryParsePhoneNumberFromUserSpecifiedText:(NSString *)text;
+ (PhoneNumber *)tryParsePhoneNumberFromE164:(NSString *)text;
// This will try to parse the input text as a phone number using
// the default region and the country code for this client's phone
// number.
//
// Order matters; better results will appear first.
+ (NSArray *)tryParsePhoneNumbersFromsUserSpecifiedText:(NSString *)text
clientPhoneNumber:(NSString *)clientPhoneNumber;
+ (NSString *)removeFormattingCharacters:(NSString *)inputString;
+ (NSString *)bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString *)input;
+ (NSString *)bestEffortFormatPartialUserSpecifiedTextToLookLikeAPhoneNumber:(NSString *)input

@ -1,3 +1,7 @@
//
// Copyright (c) 2017 Open Whisper Systems. All rights reserved.
//
#import "NBAsYouTypeFormatter.h"
#import "NBPhoneNumber.h"
#import "PhoneNumber.h"
@ -115,6 +119,60 @@ static NSString *const RPDefaultsKeyPhoneNumberCanonical = @"RPDefaultsKeyPhoneN
return [self phoneNumberFromUserSpecifiedText:sanitizedString];
}
+ (NSArray *)tryParsePhoneNumbersFromsUserSpecifiedText:(NSString *)text
clientPhoneNumber:(NSString *)clientPhoneNumber {
assert(text != nil);
text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
if ([text isEqualToString:@""]) {
return nil;
}
NSString *sanitizedString = [self removeFormattingCharacters:text];
assert(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 &&
![phoneNumberSet containsObject:[phoneNumber toE164]]) {
[result addObject:phoneNumber];
[phoneNumberSet addObject:[phoneNumber toE164]];
}
};
// Order matters; better results should appear first so
// prefer matches using this client's phone number.
if (clientPhoneNumber.length > 0) {
NSNumber *callingCodeForLocalNumber = [[PhoneNumber phoneNumberFromE164:clientPhoneNumber] getCountryCode];
if (callingCodeForLocalNumber != nil) {
tryParsingWithCountryCode([NSString stringWithFormat:@"+%@%@",
callingCodeForLocalNumber,
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];

@ -10,9 +10,10 @@
@property (nonatomic, retain) NBPhoneNumberUtil *nbPhoneNumberUtil;
+ (NSString *)callingCodeFromCountryCode:(NSString *)code;
+ (NSString *)countryNameFromCountryCode:(NSString *)code;
+ (NSString *)callingCodeFromCountryCode:(NSString *)countryCode;
+ (NSString *)countryNameFromCountryCode:(NSString *)countryCode;
+ (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm;
+ (NSArray *)countryCodesFromCallingCode:(NSString *)callingCode;
+ (NSUInteger)translateCursorPosition:(NSUInteger)offset
from:(NSString *)source

@ -30,8 +30,8 @@
}
// country code -> country name
+ (NSString *)countryNameFromCountryCode:(NSString *)code {
NSDictionary *countryCodeComponent = @{NSLocaleCountryCode : code};
+ (NSString *)countryNameFromCountryCode:(NSString *)countryCode {
NSDictionary *countryCodeComponent = @{NSLocaleCountryCode : countryCode};
NSString *identifier = [NSLocale localeIdentifierFromComponents:countryCodeComponent];
NSString *country = [NSLocale.currentLocale displayNameForKey:NSLocaleIdentifier value:identifier];
return country;
@ -86,6 +86,17 @@
return callingCode;
}
+ (NSArray *)countryCodesFromCallingCode:(NSString *)callingCode {
NSMutableArray *countryCodes = [NSMutableArray new];
for (NSString *countryCode in NSLocale.ISOCountryCodes) {
NSString *callingCodeForCountryCode = [self callingCodeFromCountryCode:countryCode];
if ([callingCode isEqualToString:callingCodeForCountryCode]) {
[countryCodes addObject:countryCode];
}
}
return countryCodes;
}
// search term -> country codes
+ (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm {
searchTerm = [searchTerm stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];

Loading…
Cancel
Save