Skip to content

Commit fdec722

Browse files
authored
Fix #363 - domain and subdomain wildcard (#364)
* test: private domain with subdomain wildcard When a private domain is listed, with an additional wildcard on a subdomain, the private domain itself is not resolved. Confirms #363 * fix: private domain with subdomain wildcard When a private domain is listed, with an additional wildcard on a subdomain, the private domain itself is not resolved. Fixes #363
1 parent 77878b8 commit fdec722

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

src/Rules.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
use SplTempFileObject;
99
use Stringable;
1010

11+
use function array_key_exists;
1112
use function array_pop;
1213
use function explode;
14+
use function in_array;
1315
use function preg_match;
1416
use function substr;
1517

@@ -19,6 +21,8 @@ final class Rules implements PublicSuffixList
1921
private const PRIVATE_DOMAINS = 'PRIVATE_DOMAINS';
2022
private const UNKNOWN_DOMAINS = 'UNKNOWN_DOMAINS';
2123

24+
private const DOMAIN_RULE_MARKER = '?';
25+
2226
private const REGEX_PSL_SECTION = ',^// ===(?<point>BEGIN|END) (?<type>ICANN|PRIVATE) DOMAINS===,';
2327
private const PSL_SECTION = [
2428
'ICANN' => [
@@ -134,7 +138,13 @@ private static function addRule(array $list, array $ruleParts): array
134138
$isDomain = false;
135139
}
136140

137-
$list[$rule] = $list[$rule] ?? ($isDomain ? [] : ['!' => '']);
141+
if (isset($list[$rule]) && [] === $list[$rule]) {
142+
$list[$rule] = [self::DOMAIN_RULE_MARKER => ''];
143+
}
144+
if (!isset($list[$rule])) {
145+
$list[$rule] = $isDomain ? [] : ['!' => ''];
146+
}
147+
138148
if ($isDomain && [] !== $ruleParts) {
139149
/** @var array<array-key, array> $tmpList */
140150
$tmpList = $list[$rule];
@@ -264,6 +274,9 @@ private function getPublicSuffixLengthFromSection(DomainName $domain, string $se
264274
//no match found
265275
if (!array_key_exists($label, $rules)) {
266276
// Suffix MUST be fully matched else no suffix is found for private domain
277+
if (self::PRIVATE_DOMAINS === $section && array_key_exists(self::DOMAIN_RULE_MARKER, $rules)) {
278+
return $labelCount;
279+
}
267280
if (self::PRIVATE_DOMAINS === $section && self::hasRemainingRules($rules)) {
268281
$labelCount = 0;
269282
}

src/RulesTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,4 +565,39 @@ public function testWithMultiLevelPrivateDomain(): void
565565
self::assertTrue($domain->suffix()->isPrivate());
566566
self::assertSame('lt.eu.org', $domain->suffix()->value());
567567
}
568+
569+
#[DataProvider('privateDomainWithWildcardProvider')]
570+
public function testWithPrivateDomainThatHasWildcardSubdomain(string $inputDomain, string $expectedSuffix): void
571+
{
572+
$domain = self::$rules->getPrivateDomain($inputDomain);
573+
574+
self::assertSame($expectedSuffix, $domain->suffix()->value());
575+
self::assertFalse($domain->suffix()->isICANN());
576+
self::assertTrue($domain->suffix()->isPrivate());
577+
}
578+
579+
/**
580+
* @return iterable<string, array{inputDomain: string, expectedSuffix: string}>
581+
*/
582+
public static function privateDomainWithWildcardProvider(): iterable
583+
{
584+
return [
585+
'appspot subdomain' => [
586+
'inputDomain' => 'test-domain.de.r.appspot.com',
587+
'expectedSuffix' => 'de.r.appspot.com',
588+
],
589+
'appspot root domain' => [
590+
'inputDomain' => 'test-domain.appspot.com',
591+
'expectedSuffix' => 'appspot.com',
592+
],
593+
'qcx subdomain' => [
594+
'inputDomain' => 'test-domain.de.sys.qcx.io',
595+
'expectedSuffix' => 'de.sys.qcx.io',
596+
],
597+
'qcx root domain' => [
598+
'inputDomain' => 'test-domain.qcx.io',
599+
'expectedSuffix' => 'qcx.io',
600+
],
601+
];
602+
}
568603
}

0 commit comments

Comments
 (0)