2021-05-03 22:15:11 -04:00
|
|
|
package geodata
|
|
|
|
|
|
|
|
import (
|
|
|
|
"strings"
|
2021-10-28 06:34:19 -04:00
|
|
|
|
|
|
|
"github.com/v2fly/v2ray-core/v4/app/router/routercommon"
|
2021-05-03 22:15:11 -04:00
|
|
|
)
|
|
|
|
|
|
|
|
type loader struct {
|
|
|
|
LoaderImplementation
|
|
|
|
}
|
|
|
|
|
2021-09-07 04:13:58 -04:00
|
|
|
func (l *loader) LoadGeoSite(list string) ([]*routercommon.Domain, error) {
|
2021-05-04 19:28:09 -04:00
|
|
|
return l.LoadGeoSiteWithAttr("geosite.dat", list)
|
2021-05-03 22:15:11 -04:00
|
|
|
}
|
|
|
|
|
2021-09-07 04:13:58 -04:00
|
|
|
func (l *loader) LoadGeoSiteWithAttr(file string, siteWithAttr string) ([]*routercommon.Domain, error) {
|
2021-05-03 22:15:11 -04:00
|
|
|
parts := strings.Split(siteWithAttr, "@")
|
|
|
|
if len(parts) == 0 {
|
|
|
|
return nil, newError("empty rule")
|
|
|
|
}
|
|
|
|
list := strings.TrimSpace(parts[0])
|
|
|
|
attrVal := parts[1:]
|
|
|
|
|
|
|
|
if len(list) == 0 {
|
|
|
|
return nil, newError("empty listname in rule: ", siteWithAttr)
|
|
|
|
}
|
|
|
|
|
|
|
|
domains, err := l.LoadSite(file, list)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
attrs := parseAttrs(attrVal)
|
|
|
|
if attrs.IsEmpty() {
|
|
|
|
if strings.Contains(siteWithAttr, "@") {
|
|
|
|
newError("empty attribute list: ", siteWithAttr)
|
|
|
|
}
|
|
|
|
return domains, nil
|
|
|
|
}
|
|
|
|
|
2021-09-07 04:13:58 -04:00
|
|
|
filteredDomains := make([]*routercommon.Domain, 0, len(domains))
|
2021-05-03 22:15:11 -04:00
|
|
|
hasAttrMatched := false
|
|
|
|
for _, domain := range domains {
|
|
|
|
if attrs.Match(domain) {
|
|
|
|
hasAttrMatched = true
|
|
|
|
filteredDomains = append(filteredDomains, domain)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !hasAttrMatched {
|
|
|
|
newError("attribute match no rule: geosite:", siteWithAttr)
|
|
|
|
}
|
|
|
|
|
|
|
|
return filteredDomains, nil
|
|
|
|
}
|
|
|
|
|
2021-09-07 04:13:58 -04:00
|
|
|
func (l *loader) LoadGeoIP(country string) ([]*routercommon.CIDR, error) {
|
2021-05-03 22:15:11 -04:00
|
|
|
return l.LoadIP("geoip.dat", country)
|
|
|
|
}
|
|
|
|
|
|
|
|
var loaders map[string]func() LoaderImplementation
|
|
|
|
|
|
|
|
func RegisterGeoDataLoaderImplementationCreator(name string, loader func() LoaderImplementation) {
|
|
|
|
if loaders == nil {
|
|
|
|
loaders = map[string]func() LoaderImplementation{}
|
|
|
|
}
|
|
|
|
loaders[name] = loader
|
|
|
|
}
|
|
|
|
|
|
|
|
func getGeoDataLoaderImplementation(name string) (LoaderImplementation, error) {
|
|
|
|
if geoLoader, ok := loaders[name]; ok {
|
|
|
|
return geoLoader(), nil
|
|
|
|
}
|
|
|
|
return nil, newError("unable to locate GeoData loader ", name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func GetGeoDataLoader(name string) (Loader, error) {
|
2021-05-04 10:04:08 -04:00
|
|
|
loadImpl, err := getGeoDataLoaderImplementation(name)
|
|
|
|
if err == nil {
|
2021-05-03 22:15:11 -04:00
|
|
|
return &loader{loadImpl}, nil
|
|
|
|
}
|
2021-05-04 10:04:08 -04:00
|
|
|
return nil, err
|
2021-05-03 22:15:11 -04:00
|
|
|
}
|