| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197 | 
							- package json
 
- import (
 
- 	"encoding/json"
 
- 	"errors"
 
- 	"net"
 
- 	"regexp"
 
- 	"strings"
 
- 	v2net "github.com/v2ray/v2ray-core/common/net"
 
- 	v2netjson "github.com/v2ray/v2ray-core/common/net/json"
 
- )
 
- type StringList []string
 
- func NewStringList(str ...string) *StringList {
 
- 	list := StringList(str)
 
- 	return &list
 
- }
 
- func (this *StringList) UnmarshalJSON(data []byte) error {
 
- 	var strList []string
 
- 	err := json.Unmarshal(data, &strList)
 
- 	if err == nil {
 
- 		*this = make([]string, len(strList))
 
- 		copy(*this, strList)
 
- 		return nil
 
- 	}
 
- 	var str string
 
- 	err = json.Unmarshal(data, &str)
 
- 	if err == nil {
 
- 		*this = make([]string, 0, 1)
 
- 		*this = append(*this, str)
 
- 		return nil
 
- 	}
 
- 	return errors.New("Failed to unmarshal string list: " + string(data))
 
- }
 
- func (this *StringList) Len() int {
 
- 	return len([]string(*this))
 
- }
 
- type DomainMatcher interface {
 
- 	Match(domain string) bool
 
- }
 
- type PlainDomainMatcher struct {
 
- 	pattern string
 
- }
 
- func NewPlainDomainMatcher(pattern string) *PlainDomainMatcher {
 
- 	return &PlainDomainMatcher{
 
- 		pattern: strings.ToLower(pattern),
 
- 	}
 
- }
 
- func (this *PlainDomainMatcher) Match(domain string) bool {
 
- 	return strings.Contains(this.pattern, strings.ToLower(domain))
 
- }
 
- type RegexpDomainMatcher struct {
 
- 	pattern *regexp.Regexp
 
- }
 
- func NewRegexpDomainMatcher(pattern string) (*RegexpDomainMatcher, error) {
 
- 	r, err := regexp.Compile(pattern)
 
- 	if err != nil {
 
- 		return nil, err
 
- 	}
 
- 	return &RegexpDomainMatcher{
 
- 		pattern: r,
 
- 	}, nil
 
- }
 
- func (this *RegexpDomainMatcher) Match(domain string) bool {
 
- 	return this.pattern.MatchString(strings.ToLower(domain))
 
- }
 
- type FieldRule struct {
 
- 	Rule
 
- 	Domain  []DomainMatcher
 
- 	IP      []*net.IPNet
 
- 	Port    v2net.PortRange
 
- 	Network v2net.NetworkList
 
- }
 
- func (this *FieldRule) Apply(dest v2net.Destination) bool {
 
- 	address := dest.Address()
 
- 	if len(this.Domain) > 0 {
 
- 		if !address.IsDomain() {
 
- 			return false
 
- 		}
 
- 		foundMatch := false
 
- 		for _, domain := range this.Domain {
 
- 			if domain.Match(address.Domain()) {
 
- 				foundMatch = true
 
- 				break
 
- 			}
 
- 		}
 
- 		if !foundMatch {
 
- 			return false
 
- 		}
 
- 	}
 
- 	if this.IP != nil && len(this.IP) > 0 {
 
- 		if !(address.IsIPv4() || address.IsIPv6()) {
 
- 			return false
 
- 		}
 
- 		foundMatch := false
 
- 		for _, ipnet := range this.IP {
 
- 			if ipnet.Contains(address.IP()) {
 
- 				foundMatch = true
 
- 				break
 
- 			}
 
- 		}
 
- 		if !foundMatch {
 
- 			return false
 
- 		}
 
- 	}
 
- 	if this.Port != nil {
 
- 		port := address.Port()
 
- 		if port.Value() < this.Port.From().Value() || port.Value() > this.Port.To().Value() {
 
- 			return false
 
- 		}
 
- 	}
 
- 	if this.Network != nil {
 
- 		if !this.Network.HasNetwork(v2net.Network(dest.Network())) {
 
- 			return false
 
- 		}
 
- 	}
 
- 	return true
 
- }
 
- func (this *FieldRule) UnmarshalJSON(data []byte) error {
 
- 	type RawFieldRule struct {
 
- 		Rule
 
- 		Domain  *StringList            `json:"domain"`
 
- 		IP      *StringList            `json:"ip"`
 
- 		Port    *v2netjson.PortRange   `json:"port"`
 
- 		Network *v2netjson.NetworkList `json:"network"`
 
- 	}
 
- 	rawFieldRule := RawFieldRule{}
 
- 	err := json.Unmarshal(data, &rawFieldRule)
 
- 	if err != nil {
 
- 		return err
 
- 	}
 
- 	this.Type = rawFieldRule.Type
 
- 	this.OutboundTag = rawFieldRule.OutboundTag
 
- 	hasField := false
 
- 	if rawFieldRule.Domain != nil && rawFieldRule.Domain.Len() > 0 {
 
- 		this.Domain = make([]DomainMatcher, rawFieldRule.Domain.Len())
 
- 		for idx, rawDomain := range *(rawFieldRule.Domain) {
 
- 			var matcher DomainMatcher
 
- 			if strings.HasPrefix(rawDomain, "regexp:") {
 
- 				rawMatcher, err := NewRegexpDomainMatcher(rawDomain[7:])
 
- 				if err != nil {
 
- 					return err
 
- 				}
 
- 				matcher = rawMatcher
 
- 			} else {
 
- 				matcher = NewPlainDomainMatcher(rawDomain)
 
- 			}
 
- 			this.Domain[idx] = matcher
 
- 		}
 
- 		hasField = true
 
- 	}
 
- 	if rawFieldRule.IP != nil && rawFieldRule.IP.Len() > 0 {
 
- 		this.IP = make([]*net.IPNet, 0, rawFieldRule.IP.Len())
 
- 		for _, ipStr := range *(rawFieldRule.IP) {
 
- 			_, ipNet, err := net.ParseCIDR(ipStr)
 
- 			if err != nil {
 
- 				return errors.New("Invalid IP range in router rule: " + err.Error())
 
- 			}
 
- 			this.IP = append(this.IP, ipNet)
 
- 		}
 
- 		hasField = true
 
- 	}
 
- 	if rawFieldRule.Port != nil {
 
- 		this.Port = rawFieldRule.Port
 
- 		hasField = true
 
- 	}
 
- 	if rawFieldRule.Network != nil {
 
- 		this.Network = rawFieldRule.Network
 
- 		hasField = true
 
- 	}
 
- 	if !hasField {
 
- 		return errors.New("This rule has no effective fields.")
 
- 	}
 
- 	return nil
 
- }
 
 
  |