diff --git a/Signal/src/environment/Release.m b/Signal/src/environment/Release.m index 9a340a020..49bbe8422 100644 --- a/Signal/src/environment/Release.m +++ b/Signal/src/environment/Release.m @@ -1,8 +1,11 @@ +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + #import "Release.h" #import "DiscardingLog.h" #import "NotificationsManager.h" #import "PhoneManager.h" -#import "PhoneNumberUtil.h" #import "RecentCallManager.h" #import #import diff --git a/Signal/src/view controllers/CountryCodeViewController.m b/Signal/src/view controllers/CountryCodeViewController.m index f96d3293f..1c57d3cb2 100644 --- a/Signal/src/view controllers/CountryCodeViewController.m +++ b/Signal/src/view controllers/CountryCodeViewController.m @@ -22,111 +22,11 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC - (void)viewDidLoad { [super viewDidLoad]; [self.navigationController.navigationBar setTranslucent:NO]; - _countryCodes = [self countryCodesForSearchTerm:nil]; + _countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:nil]; self.title = NSLocalizedString(@"COUNTRYCODE_SELECT_TITLE", @""); self.searchBar.delegate = self; } -- (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm { - NSMutableArray *result = [NSMutableArray array]; - for (NSString *countryCode in [PhoneNumberUtil countryCodesForSearchTerm:searchTerm]) { - NSString *callingCode = [self callingCodeFromCountryCode:countryCode]; - if (callingCode != nil && - ![callingCode isEqualToString:@"+0"]) { - [result addObject:countryCode]; - } - } - - if (searchTerm.length > 0) { - NSArray *allCountryCodes = [self countryCodesForSearchTerm:nil]; - // We want to ignore + when using a search term like "+44". - // We also want to ignore punctuation, etc. - // To keep things simple, we just remove everything except letters and numbers. - NSCharacterSet *charactersToRemove = [[NSMutableCharacterSet alphanumericCharacterSet] invertedSet]; - NSString *simplifiedSearchTerm = [[searchTerm componentsSeparatedByCharactersInSet:charactersToRemove] - componentsJoinedByString:@"" ]; - for (NSString *split in [simplifiedSearchTerm componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]) { - NSString *simplifiedSplit = split.lowercaseString; - OWSAssert(simplifiedSplit.length > 0); - for (NSString *countryCode in allCountryCodes) { - if ([countryCode.lowercaseString rangeOfString:simplifiedSplit].location != NSNotFound) { - [result addObject:countryCode]; - continue; - } - NSString *countryName = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; - OWSAssert(countryName.length > 0); - if ([countryName.lowercaseString rangeOfString:simplifiedSplit].location != NSNotFound) { - [result addObject:countryCode]; - continue; - } - NSString *callingCode = [self callingCodeFromCountryCode:countryCode]; - OWSAssert(callingCode.length > 0); - if ([callingCode.lowercaseString rangeOfString:simplifiedSplit].location != NSNotFound) { - [result addObject:countryCode]; - continue; - } - } - } - - // De-duplicate and sort. - // - // The results of this method should be sorted by _country name_, not - // country code, so we sort by filtering allCountryCodes, which is - // already sorted in the correct order. - NSSet *countryCodeSet = [NSSet setWithArray:result]; - return [allCountryCodes filter:^int(NSString *countryCode) { - return [countryCodeSet containsObject:countryCode]; - }]; - } - - return result; -} - -- (NSString *)callingCodeFromCountryCode:(NSString *)countryCode { - NSString *callingCode = [PhoneNumberUtil callingCodeFromCountryCode:countryCode]; - if ([countryCode isEqualToString:@"AQ"]) { - // Antarctica - callingCode = @"+672"; - } else if ([countryCode isEqualToString:@"BV"]) { - // Bouvet Island - callingCode = @"+55"; - } else if ([countryCode isEqualToString:@"IC"]) { - // Canary Islands - callingCode = @"+34"; - } else if ([countryCode isEqualToString:@"EA"]) { - // Ceuta & Melilla - callingCode = @"+34"; - } else if ([countryCode isEqualToString:@"CP"]) { - // Clipperton Island - // - // This country code should be filtered - it does not appear to have a calling code. - return nil; - } else if ([countryCode isEqualToString:@"DG"]) { - // Diego Garcia - callingCode = @"+246"; - } else if ([countryCode isEqualToString:@"TF"]) { - // French Southern Territories - callingCode = @"+262"; - } else if ([countryCode isEqualToString:@"HM"]) { - // Heard & McDonald Islands - callingCode = @"+672"; - } else if ([countryCode isEqualToString:@"XK"]) { - // Kosovo - callingCode = @"+383"; - } else if ([countryCode isEqualToString:@"PN"]) { - // Pitcairn Islands - callingCode = @"+64"; - } else if ([countryCode isEqualToString:@"GS"]) { - // So. Georgia & So. Sandwich Isl. - callingCode = @"+500"; - } else if ([countryCode isEqualToString:@"UM"]) { - // U.S. Outlying Islands - callingCode = @"+1"; - } - - return callingCode; -} - #pragma mark - UITableViewDelegate - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { @@ -143,10 +43,10 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC NSString *countryCode = _countryCodes[(NSUInteger)indexPath.row]; OWSAssert(countryCode.length > 0); OWSAssert([PhoneNumberUtil countryNameFromCountryCode:countryCode].length > 0); - OWSAssert([self callingCodeFromCountryCode:countryCode].length > 0); - OWSAssert(![[self callingCodeFromCountryCode:countryCode] isEqualToString:@"+0"]); + OWSAssert([PhoneNumberUtil callingCodeFromCountryCode:countryCode].length > 0); + OWSAssert(![[PhoneNumberUtil callingCodeFromCountryCode:countryCode] isEqualToString:@"+0"]); - [cell configureWithCountryCode:[self callingCodeFromCountryCode:countryCode] + [cell configureWithCountryCode:[PhoneNumberUtil callingCodeFromCountryCode:countryCode] andCountryName:[PhoneNumberUtil countryNameFromCountryCode:countryCode]]; return cell; @@ -154,7 +54,7 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSString *countryCode = _countryCodes[(NSUInteger)indexPath.row]; - _callingCodeSelected = [self callingCodeFromCountryCode:countryCode]; + _callingCodeSelected = [PhoneNumberUtil callingCodeFromCountryCode:countryCode]; _countryNameSelected = [PhoneNumberUtil countryNameFromCountryCode:countryCode]; [self.searchBar resignFirstResponder]; [self performSegueWithIdentifier:kUnwindToCountryCodeWasSelectedSegue sender:self]; @@ -167,12 +67,12 @@ static NSString *const kUnwindToCountryCodeWasSelectedSegue = @"UnwindToCountryC #pragma mark - UISearchBarDelegate - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText { - _countryCodes = [self countryCodesForSearchTerm:searchText]; + _countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:searchText]; [self.countryCodeTableView reloadData]; } - (void)filterContentForSearchText:(NSString *)searchText scope:(NSString *)scope { - _countryCodes = [self countryCodesForSearchTerm:searchText]; + _countryCodes = [PhoneNumberUtil countryCodesForSearchTerm:searchText]; } @end diff --git a/Signal/test/phone/PhoneNumberTest.m b/Signal/test/phone/PhoneNumberTest.m index 5ab244039..44d1fc0de 100644 --- a/Signal/test/phone/PhoneNumberTest.m +++ b/Signal/test/phone/PhoneNumberTest.m @@ -1,7 +1,13 @@ -#import -#import "TestUtil.h" +// +// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// + +#import "OWSContactsManager.h" #import "PhoneNumber.h" #import "PhoneNumberUtil.h" +#import "TestUtil.h" +#import "TextSecureKitEnv.h" +#import @interface PhoneNumberTest : XCTestCase @@ -75,5 +81,78 @@ test([PhoneNumberUtil translateCursorPosition:4 from:@"(5551) 234-567" to:@"(555) 123-4567" stickingRightward:false] == 4); test([PhoneNumberUtil translateCursorPosition:5 from:@"(5551) 234-567" to:@"(555) 123-4567" stickingRightward:false] == 7); } +//+ (NSString *)callingCodeFromCountryCode:(NSString *)code; +//+ (NSString *)countryNameFromCountryCode:(NSString *)code; +//+ (NSArray *)countryCodesForSearchTerm:(NSString *)searchTerm; + +- (void)testCallingCodeFromCountryCode +{ + XCTAssertEqualObjects([PhoneNumberUtil callingCodeFromCountryCode:@"US"], @"+1"); + XCTAssertEqualObjects([PhoneNumberUtil callingCodeFromCountryCode:@"GB"], @"+44"); + // Invalid country code. + XCTAssertEqualObjects([PhoneNumberUtil callingCodeFromCountryCode:@"EK"], @"+0"); + XCTAssertEqualObjects([PhoneNumberUtil callingCodeFromCountryCode:@"ZZZ"], @"+0"); + XCTAssertEqualObjects([PhoneNumberUtil callingCodeFromCountryCode:nil], @"+0"); +} + +- (void)testCountryNameFromCountryCode +{ + XCTAssertEqualObjects([PhoneNumberUtil countryNameFromCountryCode:@"US"], @"United States"); + XCTAssertEqualObjects([PhoneNumberUtil countryNameFromCountryCode:@"GB"], @"United Kingdom"); + // Invalid country code. + XCTAssertEqualObjects([PhoneNumberUtil countryNameFromCountryCode:@"EK"], @"EK"); + XCTAssertEqualObjects([PhoneNumberUtil countryNameFromCountryCode:@"ZZZ"], @"ZZZ"); + testThrows([PhoneNumberUtil countryNameFromCountryCode:nil]); +} + +- (void)testCountryCodesForSearchTerm +{ +// PhoneNumberUtil needs a valid OWSContactsManager in the TextSecureKitEnv, +// but we want to avoid constructing the entire app apparatus so we pass nil +// for the other parameters of the environemtn and disable nonnull warnings. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wnonnull" + TextSecureKitEnv *sharedEnv = [[TextSecureKitEnv alloc] initWithCallMessageHandler:nil + contactsManager:[OWSContactsManager new] + notificationsManager:nil]; +#pragma clang diagnostic pop + [TextSecureKitEnv setSharedEnv:sharedEnv]; + + // Empty search. + XCTAssertGreaterThan([PhoneNumberUtil countryCodesForSearchTerm:nil].count, (NSUInteger)30); + XCTAssertGreaterThan([PhoneNumberUtil countryCodesForSearchTerm:@""].count, (NSUInteger)30); + XCTAssertGreaterThan([PhoneNumberUtil countryCodesForSearchTerm:@" "].count, (NSUInteger)30); + + // Searches with no results. + XCTAssertEqual([PhoneNumberUtil countryCodesForSearchTerm:@" . "].count, (NSUInteger)0); + XCTAssertEqual([PhoneNumberUtil countryCodesForSearchTerm:@" XXXXX "].count, (NSUInteger)0); + XCTAssertEqual([PhoneNumberUtil countryCodesForSearchTerm:@" ! "].count, (NSUInteger)0); + + // Search by country code. + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@"GB"], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@"gb"], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@"GB "], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@" GB"], (@[ @"GB" ])); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" G"] containsObject:@"GB"]); + XCTAssertFalse([[PhoneNumberUtil countryCodesForSearchTerm:@" B"] containsObject:@"GB"]); + + // Search by country name. + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@"united kingdom"], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@" UNITED KINGDOM "], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@" UNITED KING "], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@" UNI KING "], (@[ @"GB" ])); + XCTAssertEqualObjects([PhoneNumberUtil countryCodesForSearchTerm:@" u k "], (@[ @"GB" ])); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" u"] containsObject:@"GB"]); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" k"] containsObject:@"GB"]); + XCTAssertFalse([[PhoneNumberUtil countryCodesForSearchTerm:@" m"] containsObject:@"GB"]); + + // Search by calling code. + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" +44 "] containsObject:@"GB"]); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" 44 "] containsObject:@"GB"]); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" +4 "] containsObject:@"GB"]); + XCTAssertTrue([[PhoneNumberUtil countryCodesForSearchTerm:@" 4 "] containsObject:@"GB"]); + XCTAssertFalse([[PhoneNumberUtil countryCodesForSearchTerm:@" +123 "] containsObject:@"GB"]); + XCTAssertFalse([[PhoneNumberUtil countryCodesForSearchTerm:@" +444 "] containsObject:@"GB"]); +} @end