github.com/kelleygo/clashcore@v1.0.2/rules/provider/parse.go (about) 1 package provider 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/kelleygo/clashcore/common/structure" 9 "github.com/kelleygo/clashcore/component/resource" 10 C "github.com/kelleygo/clashcore/constant" 11 "github.com/kelleygo/clashcore/constant/features" 12 P "github.com/kelleygo/clashcore/constant/provider" 13 ) 14 15 var ( 16 errSubPath = errors.New("path is not subpath of home directory") 17 ) 18 19 type ruleProviderSchema struct { 20 Type string `provider:"type"` 21 Behavior string `provider:"behavior"` 22 Path string `provider:"path,omitempty"` 23 URL string `provider:"url,omitempty"` 24 Proxy string `provider:"proxy,omitempty"` 25 Format string `provider:"format,omitempty"` 26 Interval int `provider:"interval,omitempty"` 27 } 28 29 func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(tp, payload, target string, params []string, subRules map[string][]C.Rule) (parsed C.Rule, parseErr error)) (P.RuleProvider, error) { 30 schema := &ruleProviderSchema{} 31 decoder := structure.NewDecoder(structure.Option{TagName: "provider", WeaklyTypedInput: true}) 32 if err := decoder.Decode(mapping, schema); err != nil { 33 return nil, err 34 } 35 var behavior P.RuleBehavior 36 37 switch schema.Behavior { 38 case "domain": 39 behavior = P.Domain 40 case "ipcidr": 41 behavior = P.IPCIDR 42 case "classical": 43 behavior = P.Classical 44 default: 45 return nil, fmt.Errorf("unsupported behavior type: %s", schema.Behavior) 46 } 47 48 var format P.RuleFormat 49 50 switch schema.Format { 51 case "", "yaml": 52 format = P.YamlRule 53 case "text": 54 format = P.TextRule 55 default: 56 return nil, fmt.Errorf("unsupported format type: %s", schema.Format) 57 } 58 59 var vehicle P.Vehicle 60 switch schema.Type { 61 case "file": 62 path := C.Path.Resolve(schema.Path) 63 vehicle = resource.NewFileVehicle(path) 64 case "http": 65 path := C.Path.GetPathByHash("rules", schema.URL) 66 if schema.Path != "" { 67 path = C.Path.Resolve(schema.Path) 68 if !features.CMFA && !C.Path.IsSafePath(path) { 69 return nil, fmt.Errorf("%w: %s", errSubPath, path) 70 } 71 } 72 vehicle = resource.NewHTTPVehicle(schema.URL, path, schema.Proxy, nil) 73 default: 74 return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type) 75 } 76 77 return NewRuleSetProvider(name, behavior, format, time.Duration(uint(schema.Interval))*time.Second, vehicle, parse), nil 78 }