package whois import ( "errors" "fmt" "net" "strconv" "strings" "golang.org/x/net/idna" ) type lookupTargetKind int const ( lookupTargetDomain lookupTargetKind = iota lookupTargetIP lookupTargetASN ) func normalizeQueryDomainInput(domain string) (string, error) { domain = strings.Trim(strings.TrimSpace(domain), ".") if domain == "" { return "", errors.New("whois: domain is empty") } if strings.ContainsAny(domain, "/\\") { return "", fmt.Errorf("whois: invalid domain=%q", domain) } if IsASN(domain) { if strings.HasPrefix(strings.ToUpper(domain), "AS") { return strings.ToUpper(domain), nil } return "AS" + strings.ToUpper(domain), nil } if ip := net.ParseIP(domain); ip != nil { return ip.String(), nil } ascii, err := idna.Lookup.ToASCII(domain) if err != nil { return "", fmt.Errorf("whois: invalid domain=%q: %w", domain, err) } ascii = strings.ToLower(strings.Trim(ascii, ".")) if ascii == "" { return "", errors.New("whois: domain is empty") } return ascii, nil } func normalizeLookupDomainInput(domain string) (string, error) { normalized, kind, err := normalizeLookupTargetInput(domain) if err != nil { return "", err } if kind != lookupTargetDomain { return "", fmt.Errorf("whois/lookup: invalid domain=%q", domain) } return normalized, nil } func normalizeLookupTargetInput(input string) (string, lookupTargetKind, error) { normalized, err := normalizeQueryDomainInput(input) if err != nil { return "", lookupTargetDomain, err } if IsASN(normalized) { return normalized, lookupTargetASN, nil } if net.ParseIP(normalized) != nil { return normalized, lookupTargetIP, nil } return normalized, lookupTargetDomain, nil } func normalizeASNNumeric(asn string) (string, error) { asn = strings.TrimSpace(strings.ToUpper(asn)) if !IsASN(asn) { return "", fmt.Errorf("whois/rdap: invalid asn=%q", asn) } asn = strings.TrimPrefix(asn, "AS") asn = strings.TrimSpace(asn) if asn == "" { return "", fmt.Errorf("whois/rdap: invalid asn=%q", asn) } if _, err := strconv.ParseUint(asn, 10, 32); err != nil { return "", fmt.Errorf("whois/rdap: invalid asn=%q: %w", asn, err) } return asn, nil }