diff --git a/internal/api/domain.go b/internal/api/domain.go index 2049c3a2..0aed55f7 100644 --- a/internal/api/domain.go +++ b/internal/api/domain.go @@ -10,19 +10,27 @@ import ( //nolint:gochecknoglobals // profile does C2 in UTS#46 with all checks on + removing leading dots. // This is the main conversion profile in use. -var profile = idna.New( - idna.MapForLookup(), - idna.BidiRule(), - // idna.Transitional(false), // https://go-review.googlesource.com/c/text/+/317729/ - idna.RemoveLeadingDots(true), +var ( + profileDroppingLeadingDots = idna.New( + idna.MapForLookup(), + idna.BidiRule(), + // idna.Transitional(false), // https://go-review.googlesource.com/c/text/+/317729/ + idna.RemoveLeadingDots(true), + ) + profileKeepingLeadingDots = idna.New( + idna.MapForLookup(), + idna.BidiRule(), + // idna.Transitional(false), // https://go-review.googlesource.com/c/text/+/317729/ + idna.RemoveLeadingDots(false), + ) ) // safelyToUnicode takes an ASCII form and returns the Unicode form // when the round trip gives the same ASCII form back without errors. // Otherwise, the input ASCII form is returned. func safelyToUnicode(ascii string) (string, bool) { - unicode, errToA := profile.ToUnicode(ascii) - roundTrip, errToU := profile.ToASCII(unicode) + unicode, errToA := profileKeepingLeadingDots.ToUnicode(ascii) + roundTrip, errToU := profileKeepingLeadingDots.ToASCII(unicode) if errToA != nil || errToU != nil || roundTrip != ascii { return ascii, false } @@ -35,7 +43,7 @@ func safelyToUnicode(ascii string) (string, bool) { // gives back the same ASCII form without errors. Otherwise, // the ASCII form (possibly using Punycode) is stored to avoid ambiguity. func NewDomain(domain string) (Domain, error) { - normalized, err := profile.ToASCII(domain) + normalized, err := profileDroppingLeadingDots.ToASCII(domain) // Remove the final dot for consistency normalized = strings.TrimRight(normalized, ".") @@ -45,7 +53,7 @@ func NewDomain(domain string) (Domain, error) { return Wildcard(""), nil case strings.HasPrefix(normalized, "*."): // redo the normalization after removing the offending "*" - normalized, err := profile.ToASCII(strings.TrimPrefix(normalized, "*.")) + normalized, err := profileKeepingLeadingDots.ToASCII(strings.TrimPrefix(normalized, "*.")) return Wildcard(normalized), err default: return FQDN(normalized), err diff --git a/internal/api/domain_test.go b/internal/api/domain_test.go index b562ee35..f40232a1 100644 --- a/internal/api/domain_test.go +++ b/internal/api/domain_test.go @@ -93,7 +93,7 @@ func TestNewDomain(t *testing.T) { {"..。..a.com", f("a.com"), true, ""}, {"*.xn--a.xn--a.xn--a.com", w("xn--a.xn--a.xn--a.com"), false, `idna: invalid label "\u0080"`}, {"*.a.com...。", w("a.com"), true, ""}, - {"*...。..a.com", w("a.com"), true, ""}, + {"*...。..a.com", w(".....a.com"), true, ""}, {"*......", w(""), true, ""}, {"*。。。。。。", w(""), true, ""}, } {