package imgcache import ( "net/url" "strings" ) // HostWhitelist implements the Whitelist interface for checking allowed source hosts. // Only exact host matches are supported. Leading dots in patterns are stripped // (e.g. ".example.com" becomes an exact match for "example.com"). type HostWhitelist struct { // hosts contains hosts that must match exactly (e.g., "cdn.example.com") hosts map[string]struct{} } // NewHostWhitelist creates a whitelist from a list of host patterns. // All patterns are treated as exact matches. Leading dots are stripped // for backwards compatibility (e.g. ".example.com" matches "example.com" only). func NewHostWhitelist(patterns []string) *HostWhitelist { w := &HostWhitelist{ hosts: make(map[string]struct{}), } for _, pattern := range patterns { pattern = strings.ToLower(strings.TrimSpace(pattern)) if pattern == "" { continue } // Strip leading dot — suffix matching is not supported. // ".example.com" is treated as exact match for "example.com". pattern = strings.TrimPrefix(pattern, ".") if pattern == "" { continue } w.hosts[pattern] = struct{}{} } return w } // IsWhitelisted checks if a URL's host is in the whitelist. // Only exact host matches are supported. func (w *HostWhitelist) IsWhitelisted(u *url.URL) bool { if u == nil { return false } host := strings.ToLower(u.Hostname()) if host == "" { return false } _, ok := w.hosts[host] return ok } // IsEmpty returns true if the whitelist has no entries. func (w *HostWhitelist) IsEmpty() bool { return len(w.hosts) == 0 } // Count returns the total number of whitelist entries. func (w *HostWhitelist) Count() int { return len(w.hosts) }