github.com/yaling888/clash@v1.53.0/component/script/expr_builtin.go (about) 1 package script 2 3 import ( 4 "time" 5 6 "github.com/expr-lang/expr/ast" 7 8 C "github.com/yaling888/clash/constant" 9 ) 10 11 type ( 12 scStringFunc = func(string) string 13 scStringBoolFunc = func(string) (bool, error) 14 scEmptyFunc = func() string 15 scStringStringFunc = func(string, string) bool 16 scStringStringErrFunc = func(string, string) (bool, error) 17 ) 18 19 type shortcutEnvironment struct { 20 Network string `expr:"network"` 21 Type string `expr:"type"` 22 SrcIP string `expr:"src_ip"` 23 DstIP string `expr:"dst_ip"` 24 SrcPort uint16 `expr:"src_port"` 25 DstPort uint16 `expr:"dst_port"` 26 InboundPort uint16 `expr:"inbound_port"` 27 Host string `expr:"host"` 28 ProcessName string `expr:"process_name"` 29 ProcessPath string `expr:"process_path"` 30 UserAgent string `expr:"user_agent"` 31 SpecialProxy string `expr:"special_proxy"` 32 Now nowExpr `expr:"now"` 33 34 ResolveIP scStringFunc `expr:"resolve_ip"` 35 InCidr scStringStringErrFunc `expr:"in_cidr"` 36 InIPSet scStringStringFunc `expr:"in_ipset"` 37 GeoIP scStringFunc `expr:"geoip"` 38 MatchProvider scStringBoolFunc `expr:"match_provider"` 39 ResolveProcessName scEmptyFunc `expr:"resolve_process_name"` 40 ResolveProcessPath scEmptyFunc `expr:"resolve_process_path"` 41 } 42 43 type nowExpr struct { 44 Year int `expr:"year"` 45 Month int `expr:"month"` 46 Day int `expr:"day"` 47 Hour int `expr:"hour"` 48 Minute int `expr:"minute"` 49 Second int `expr:"second"` 50 Nanosecond int `expr:"nanosecond"` 51 Unix int64 `expr:"unix"` 52 UnixNano int64 `expr:"unix_nano"` 53 Weekday int `expr:"weekday"` 54 } 55 56 type stringInString struct{} 57 58 func (*stringInString) Visit(node *ast.Node) { 59 switch n := (*node).(type) { 60 case *ast.BinaryNode: 61 if n.Operator == "in" { 62 switch n.Right.(type) { 63 case *ast.StringNode, *ast.IdentifierNode, *ast.CallNode: 64 if _, ok := n.Left.(*ast.StringNode); ok { 65 ast.Patch(node, &ast.BinaryNode{ 66 Operator: "contains", 67 Left: n.Right, 68 Right: n.Left, 69 }) 70 } 71 } 72 } 73 } 74 } 75 76 func parseEnv(mtd *C.Metadata, hasNow bool) shortcutEnvironment { 77 env := shortcutEnvironment{ 78 Network: mtd.NetWork.String(), 79 Type: mtd.Type.String(), 80 SrcPort: uint16(mtd.SrcPort), 81 DstPort: uint16(mtd.DstPort), 82 InboundPort: mtd.OriginDst.Port(), 83 Host: mtd.Host, 84 ProcessName: mtd.Process, 85 ProcessPath: mtd.ProcessPath, 86 UserAgent: mtd.UserAgent, 87 SpecialProxy: mtd.SpecialProxy, 88 89 InCidr: uInCidr, 90 InIPSet: uInIPSet, 91 GeoIP: uGeoIP, 92 } 93 94 if mtd.SrcIP.IsValid() { 95 env.SrcIP = mtd.SrcIP.String() 96 } 97 98 if mtd.DstIP.IsValid() { 99 env.DstIP = mtd.DstIP.String() 100 } 101 102 if hasNow { 103 env.Now = makeNowField() 104 } 105 106 env.ResolveIP = func(host string) string { 107 return uResolveIP(mtd, host) 108 } 109 110 env.MatchProvider = func(name string) (bool, error) { 111 return uMatchProvider(mtd, name) 112 } 113 114 env.ResolveProcessName = func() string { 115 uResolveProcess(mtd) 116 return mtd.Process 117 } 118 119 env.ResolveProcessPath = func() string { 120 uResolveProcess(mtd) 121 return mtd.ProcessPath 122 } 123 124 return env 125 } 126 127 func makeNowField() nowExpr { 128 t := time.Now() 129 return nowExpr{ 130 Year: t.Year(), 131 Month: int(t.Month()), 132 Day: t.Day(), 133 Hour: t.Hour(), 134 Minute: t.Minute(), 135 Second: t.Second(), 136 Nanosecond: t.Nanosecond(), 137 Unix: t.Unix(), 138 UnixNano: t.UnixNano(), 139 Weekday: int(t.Weekday()), 140 } 141 }