Files
elmprodvpn/selective-vpn-api/app/resolver/wildcard_matcher.go

71 lines
1.4 KiB
Go

package resolver
import "strings"
type WildcardMatcher struct {
exact map[string]struct{}
suffix []string
}
func NormalizeWildcardDomain(raw string) string {
d := strings.TrimSpace(strings.SplitN(raw, "#", 2)[0])
d = strings.ToLower(d)
d = strings.TrimPrefix(d, "*.")
d = strings.TrimPrefix(d, ".")
d = strings.TrimSuffix(d, ".")
return d
}
func NewWildcardMatcher(domains []string) WildcardMatcher {
seen := map[string]struct{}{}
m := WildcardMatcher{exact: map[string]struct{}{}}
for _, raw := range domains {
d := NormalizeWildcardDomain(raw)
if d == "" {
continue
}
if _, ok := seen[d]; ok {
continue
}
seen[d] = struct{}{}
m.exact[d] = struct{}{}
m.suffix = append(m.suffix, "."+d)
}
return m
}
func (m WildcardMatcher) Match(host string) bool {
if len(m.exact) == 0 {
return false
}
h := strings.TrimSuffix(strings.ToLower(strings.TrimSpace(host)), ".")
if h == "" {
return false
}
if _, ok := m.exact[h]; ok {
return true
}
for _, suffix := range m.suffix {
if strings.HasSuffix(h, suffix) {
return true
}
}
return false
}
func (m WildcardMatcher) IsExact(host string) bool {
if len(m.exact) == 0 {
return false
}
h := strings.TrimSuffix(strings.ToLower(strings.TrimSpace(host)), ".")
if h == "" {
return false
}
_, ok := m.exact[h]
return ok
}
func (m WildcardMatcher) Count() int {
return len(m.exact)
}