Skip to content

Commit c1a33a0

Browse files
authored
Fdl unit tests (#9516)
Refactoring custom domain validation logic with fixes and adding new unit tests.
1 parent af21292 commit c1a33a0

File tree

3 files changed

+60
-31
lines changed

3 files changed

+60
-31
lines changed

FirebaseDynamicLinks/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
# v8.15.0
2+
- [fixed] Fixed Custom domain long url validation logic. (#6978)
3+
14
# v8.9.0
25
- [fixed] Fixed Shortlink regression involving underscores and dashes introduced in 8.8.0. (#8786)
36
- [fixed] Reduce memory stress on `WebKit` API. (#8847)

FirebaseDynamicLinks/Sources/Utilities/FDLUtilities.m

Lines changed: 36 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -201,37 +201,46 @@ BOOL FIRDLOSVersionSupported(NSString *_Nullable systemVersion, NSString *minSup
201201
return timeZoneName;
202202
}
203203

204-
BOOL FIRDLIsURLForAllowedCustomDomain(NSURL *_Nullable URL) {
205-
BOOL customDomainMatchFound = false;
206-
for (NSURL *allowedCustomDomain in FIRDLCustomDomains) {
207-
// At least one custom domain host name should match at a minimum.
208-
if ([allowedCustomDomain.host isEqualToString:URL.host]) {
209-
NSString *urlStr = URL.absoluteString;
210-
NSString *domainURIPrefixStr = allowedCustomDomain.absoluteString;
211-
212-
// Next, do a string compare to check if entire domainURIPrefix matches as well.
213-
if (([urlStr rangeOfString:domainURIPrefixStr
214-
options:NSCaseInsensitiveSearch | NSAnchoredSearch]
215-
.location) == 0) {
216-
NSString *urlWithoutDomainURIPrefix = [urlStr substringFromIndex:domainURIPrefixStr.length];
217-
218-
// For a valid custom domain DL Suffix:
219-
// 1. At least one path exists OR
220-
// 2. Should have a link query param with an http/https link
221-
BOOL matchesRegularExpression =
222-
([urlWithoutDomainURIPrefix
223-
rangeOfString:@"((\\/[A-Za-z0-9]+)|((\\?|\\/\\?)link=https?.*))"
224-
options:NSRegularExpressionSearch]
225-
.location != NSNotFound);
226-
227-
if (matchesRegularExpression) {
228-
customDomainMatchFound = true;
229-
break;
204+
BOOL FIRDLIsURLForAllowedCustomDomain(NSURL *URL) {
205+
if (URL) {
206+
for (NSURL *allowedCustomDomain in FIRDLCustomDomains) {
207+
// At least one custom domain host name should match at a minimum.
208+
if ([URL.absoluteString hasPrefix:allowedCustomDomain.absoluteString]) {
209+
NSString *urlWithoutDomainURIPrefix =
210+
[URL.absoluteString substringFromIndex:allowedCustomDomain.absoluteString.length];
211+
212+
// The urlWithoutDomainURIPrefix should be starting with '/' or '?' otherwise it means the
213+
// allowed domain is not exactly matching the incoming URL domain prefix.
214+
if ([urlWithoutDomainURIPrefix hasPrefix:@"/"] ||
215+
[urlWithoutDomainURIPrefix hasPrefix:@"?"]) {
216+
// For a valid custom domain DL Suffix the urlWithoutDomainURIPrefix should have:
217+
// 1. At least one path exists OR
218+
// 2. Should have a link query param with an http/https link
219+
220+
NSURLComponents *components =
221+
[[NSURLComponents alloc] initWithString:urlWithoutDomainURIPrefix];
222+
if (components.path && components.path.length > 1) {
223+
// Have a path exists. So valid custom domain.
224+
return true;
225+
}
226+
227+
if (components.queryItems && components.queryItems.count > 0) {
228+
for (NSURLQueryItem *queryItem in components.queryItems) {
229+
// Checks whether we have a link query param
230+
if ([queryItem.name caseInsensitiveCompare:@"link"] == NSOrderedSame) {
231+
// Checks whether link query param value starts with http/https
232+
if (queryItem.value && ([queryItem.value hasPrefix:@"http://"] ||
233+
[queryItem.value hasPrefix:@"https://"])) {
234+
return true;
235+
}
236+
}
237+
}
238+
}
230239
}
231240
}
232241
}
233242
}
234-
return customDomainMatchFound;
243+
return false;
235244
}
236245

237246
/* We are validating following domains in proper format.

FirebaseDynamicLinks/Tests/Unit/FIRDynamicLinksTest.m

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,8 +1625,10 @@ - (void)testValidCustomDomainNames {
16251625
// argument.
16261626
@"https://google.com/?some=qry&link=https://somedomain", // Long FDL with link param as second
16271627
// argument
1628-
@"https://google.com/?a=b&c=d&link=https://somedomain&y=z", // Long FDL with link param as
1629-
// middle argument argument
1628+
@"https://google.com/?a=b&c=d&link=https://somedomain&y=z", // Long FDL with link param as
1629+
// middle argument argument
1630+
@"https://google.com?some=qry&link=https%3A%2F%2Fsomedomain", // Long FDL with Url encoded link
1631+
// param
16301632
];
16311633
for (NSString *urlString in urlStrings) {
16321634
NSURL *url = [NSURL URLWithString:urlString];
@@ -1661,12 +1663,27 @@ - (void)testInvalidCustomDomainNames {
16611663
@"mydomain.com", // https scheme not specified for domainURIPrefix.
16621664
@"http://mydomain", // Domain not in plist. No path after domainURIPrefix.
16631665
@"https://somecustom.com?", @"https://somecustom.com/?",
1664-
@"https://somecustom.com?somekey=someval"
1666+
@"https://somecustom.com?somekey=someval",
1667+
@"https://google.com?some=qry&somelink=https%3A%2F%2Fsomedomain", // Having somelink param
1668+
// instead of link param to
1669+
// confuse validation.
1670+
@"https://a.firebase.com/mypaths?some=qry&link=https%3A%2F%2Fsomedomain", // Additional 's' in
1671+
// path param
1672+
@"https://a.firebase.com/mypath/?some=qry#other=b&link=https://somedomain", // link param comes
1673+
// in fragmentation
1674+
@"https://a.firebase.com/mypath/?some=qry#other=b&link=https%3A%2F%2Fsomedomain", // link param
1675+
// which is
1676+
// url
1677+
// encoded
1678+
// and comes
1679+
// in
1680+
// fragmentation.
1681+
@"https://google.com?link=https1://abcd", // link query param is not a valid http link
16651682
];
16661683

16671684
for (NSString *urlString in urlStrings) {
16681685
NSURL *url = [NSURL URLWithString:urlString];
1669-
BOOL matchesShortLinkFormat = [self.service matchesShortLinkFormat:url];
1686+
BOOL matchesShortLinkFormat = [self.service canParseUniversalLinkURL:url];
16701687

16711688
XCTAssertFalse(matchesShortLinkFormat,
16721689
@"Non-DDL domain URL matched short link format with URL: %@", url);

0 commit comments

Comments
 (0)