Codebase list zonedb / master zone.go
master

Tree @master (Download .tar.gz)

zone.go @masterraw · history · blame

package zonedb

import (
	"strings"
)

//go:generate go run cmd/zonedb/main.go -generate-go

// And performs a bitwise AND between tags and q,
// comparing the result to zero. Returns true if any
// tags match q.
func (tags Tags) And(q Tags) bool {
	return (tags & q) != 0
}

// String returns a space-delimited list of values for tags.
func (tags Tags) String() string {
	var a [numTags]string
	s := a[0:0]
	for i := uint64(0); i < numTags; i++ {
		t := Tags(1 << i)
		if (tags & t) != 0 {
			s = append(s, TagStrings[t])
		}
	}
	return strings.Join(s, " ")
}

// Zone represents a single DNS zone (a public suffix), where subdomains may be registered or created.
type Zone struct {
	// Normalized (ASCII, punycode) fully-qualified domain name
	Domain string

	// Parent Zone (nil if Zone is a TLD)
	Parent *Zone

	// Slice of subdomain (child) Zones (nil if empty)
	Subdomains []Zone

	// Tags stored as an integer bit field
	Tags Tags

	// Informational URL for this Zone
	InfoURL string

	// DNS name servers for the Zone
	NameServers []string

	// Wildcard addresses for unregistered subdomains
	Wildcards []string

	// Locations associated with the Zone
	Locations []string

	// BCP 47 language tags associated with this Zone
	// https://tools.ietf.org/html/bcp47
	languages []string

	// Whois server responding on port 43
	whoisServer string

	// URL to look up whois info for a subdomain of this Zone
	whoisURL string

	// Transitional: does the zone operator allow registration of non-ASCII subdomains?
	allowsIDN bool
}

// Languages returns a slice of BCP 47 language specifiers.
func (z *Zone) Languages() []string {
	return z.languages
}

// WhoisServer returns the whois server that responds on port 43
// for the zone. It first searches the specific zone, then the parent,
// returning an empty string if none found.
func (z *Zone) WhoisServer() string {
	if z.whoisServer != "" {
		return z.whoisServer
	}
	if z.Parent != nil {
		return z.Parent.WhoisServer()
	}
	return ""
}

// WhoisURL returns a URL to retrieve whois data for a subdomain
// of the zone. It first searches the specific zone, then the parent,
// returning an empty string if none found.
func (z *Zone) WhoisURL() string {
	if z.whoisURL != "" {
		return z.whoisURL
	}
	if z.Parent != nil {
		return z.Parent.WhoisURL()
	}
	return ""
}

// IsTLD returns true if the Zone is a top-level domain.
func (z *Zone) IsTLD() bool {
	return z.Parent == nil
}

// IsDelegated returns true if the Zone has name servers.
func (z *Zone) IsDelegated() bool {
	return len(z.NameServers) != 0
}

// IsInRootZone returns true if the Zone is a top-level domain.
// present in the root DNS zone.
func (z *Zone) IsInRootZone() bool {
	return z.IsTLD() && z.IsDelegated()
}

// IsValidDomain and IDNTable have been removed. We searched for public code
// on GitHub that imported the zonedb package and found no open-source clients
// using these methods.
//
// Rationale: the generation and validation of (IDN) labels requires state
// beyond what can be represented in simple list if code points.
//
// This branch attempts to reconcile the objective of documenting and normalizing
// zone metadata, including policies that define allowed labels such as
// IDN tables, Label Generation Rulesets (LGRs), and implicit or undocumented
// policies such as applied by ccTLDs.

// AllowsIDN returns true if the zone operator (registry)
// permits registration of non-ASCII labels under this Zone.
func (z *Zone) AllowsIDN() bool {
	return z.allowsIDN
}

// AllowsRegistration returns true if the Zone’s authority (registry)
// permits registration of subdomains of this Zone. Examples:
// closed, withdrawn, retired, or infrastructure zones.
func (z *Zone) AllowsRegistration() bool {
	return !z.Tags.And(TagClosed | TagWithdrawn | TagRetired | TagInfrastructure)
}

// IsZone returns true if the input domain is a Zone.
func IsZone(domain string) bool {
	_, ok := ZoneMap[domain]
	return ok
}

// IsTLD returns true if the input domain is a top-level domain.
func IsTLD(domain string) bool {
	z, ok := ZoneMap[domain]
	if !ok {
		return false
	}
	return z.IsTLD()
}

// PublicZone returns the public zone for a given domain name
// or nil if none found.
// Input must be normalized by the client (lowercase, ASCII-encoded).
func PublicZone(domain string) *Zone {
	sfx := domain
	for {
		if z, ok := ZoneMap[sfx]; ok {
			return z
		}
		if i := strings.Index(sfx, "."); i >= 0 {
			sfx = sfx[i+1:]
		} else {
			break
		}
	}
	return nil
}

// List implements the cookiejar.PublicSuffixList interface.
var List list

type list struct{}

// PublicSuffix returns the public suffix (zone) for a given domain name
// by calling PublicZone. Input must be normalized by the client
// (lowercase, ASCII, punycode). Malformed input, IP addresses, or other non-domain
// name strings will be returned unmodified.
func (l list) PublicSuffix(domain string) string {
	z := PublicZone(domain)
	if z == nil {
		return domain
	}
	return z.Domain
}

// String returns a description of source of this public suffix list.
func (l list) String() string {
	return "ZoneDB"
}