diff --git a/src/Hostname.php b/src/Hostname.php index 97d543bc4..5914fb175 100644 --- a/src/Hostname.php +++ b/src/Hostname.php @@ -2090,6 +2090,7 @@ public function isValid($value) // Check each hostname part $check = 0; + $lastDomainPart = end($domainParts); foreach ($domainParts as $domainPart) { // Decode Punycode domain names to IDN if (strpos($domainPart, 'xn--') === 0) { @@ -2118,7 +2119,9 @@ public function isValid($value) // Check each domain part $checked = false; - foreach ($regexChars as $regexKey => $regexChar) { + $isSubDomain = $domainPart != $lastDomainPart; + $partRegexChars = $isSubDomain ? ['/^[a-z0-9_\x2d]{1,63}$/i'] + $regexChars : $regexChars; + foreach ($partRegexChars as $regexKey => $regexChar) { $status = preg_match($regexChar, $domainPart); if ($status > 0) { $length = 63; diff --git a/test/HostnameTest.php b/test/HostnameTest.php index 64b28f14a..9ef8d509c 100644 --- a/test/HostnameTest.php +++ b/test/HostnameTest.php @@ -119,6 +119,30 @@ public function testDashes() } } + /** + * Ensure the underscore character tests work as expected + * + */ + public function testUnderscores() + { + $valuesExpected = [ + [Hostname::ALLOW_DNS, true, [ + '_subdomain.domain.com', 'subdomain_.domain.com', 'sub_domain.domain.com', 'sub__domain.domain.com' + ]], + [Hostname::ALLOW_DNS, false, ['_domain.com', 'domain_.com', 'do_main.com']] + ]; + foreach ($valuesExpected as $element) { + $validator = new Hostname($element[0]); + foreach ($element[2] as $input) { + $this->assertEquals( + $element[1], + $validator->isValid($input), + implode("\n", $validator->getMessages()) . $input + ); + } + } + } + /** * Ensures that getMessages() returns expected default value *