From a2334430c1b41d0d60a483571dc752bb0f540352 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B1=90=E6=AE=87?= <95160953+xishang0128@users.noreply.github.com> Date: Thu, 15 Jun 2023 22:45:02 +0800 Subject: [PATCH] feat: optional provider path (#624) --- adapter/provider/parser.go | 17 +++++++++++------ constant/path.go | 8 ++++++++ rules/provider/parse.go | 24 ++++++++++++++++++++---- 3 files changed, 39 insertions(+), 10 deletions(-) diff --git a/adapter/provider/parser.go b/adapter/provider/parser.go index 2281c89b..f04bb77a 100644 --- a/adapter/provider/parser.go +++ b/adapter/provider/parser.go @@ -27,7 +27,7 @@ type healthCheckSchema struct { type proxyProviderSchema struct { Type string `provider:"type"` - Path string `provider:"path"` + Path string `provider:"path,omitempty"` URL string `provider:"url,omitempty"` Interval int `provider:"interval,omitempty"` Filter string `provider:"filter,omitempty"` @@ -60,17 +60,22 @@ func ParseProxyProvider(name string, mapping map[string]any) (types.ProxyProvide } hc := NewHealthCheck([]C.Proxy{}, schema.HealthCheck.URL, hcInterval, schema.HealthCheck.Lazy, expectedStatus) - path := C.Path.Resolve(schema.Path) - var vehicle types.Vehicle switch schema.Type { case "file": + path := C.Path.Resolve(schema.Path) vehicle = resource.NewFileVehicle(path) case "http": - if !C.Path.IsSafePath(path) { - return nil, fmt.Errorf("%w: %s", errSubPath, path) + if schema.Path != "" { + path := C.Path.Resolve(schema.Path) + if !C.Path.IsSafePath(path) { + return nil, fmt.Errorf("%w: %s", errSubPath, path) + } + vehicle = resource.NewHTTPVehicle(schema.URL, path) + } else { + path := C.Path.GetRandomPath("proxies", schema.URL) + vehicle = resource.NewHTTPVehicle(schema.URL, path) } - vehicle = resource.NewHTTPVehicle(schema.URL, path) default: return nil, fmt.Errorf("%w: %s", errVehicleType, schema.Type) } diff --git a/constant/path.go b/constant/path.go index a3124b24..68129838 100644 --- a/constant/path.go +++ b/constant/path.go @@ -1,6 +1,8 @@ package constant import ( + "crypto/md5" + "encoding/hex" "os" P "path" "path/filepath" @@ -72,6 +74,12 @@ func (p *path) IsSafePath(path string) bool { return !strings.Contains(rel, "..") } +func (p *path) GetRandomPath(prefix, name string) string { + hash := md5.Sum([]byte(name)) + filename := hex.EncodeToString(hash[:]) + return filepath.Join(p.HomeDir(), prefix, filename) +} + func (p *path) MMDB() string { files, err := os.ReadDir(p.homeDir) if err != nil { diff --git a/rules/provider/parse.go b/rules/provider/parse.go index 6a001b50..ef7beec5 100644 --- a/rules/provider/parse.go +++ b/rules/provider/parse.go @@ -1,18 +1,24 @@ package provider import ( + "errors" "fmt" + "time" + "github.com/Dreamacro/clash/common/structure" "github.com/Dreamacro/clash/component/resource" C "github.com/Dreamacro/clash/constant" P "github.com/Dreamacro/clash/constant/provider" - "time" +) + +var ( + errSubPath = errors.New("path is not subpath of home directory") ) type ruleProviderSchema struct { Type string `provider:"type"` Behavior string `provider:"behavior"` - Path string `provider:"path"` + Path string `provider:"path,omitempty"` URL string `provider:"url,omitempty"` Format string `provider:"format,omitempty"` Interval int `provider:"interval,omitempty"` @@ -48,13 +54,23 @@ func ParseRuleProvider(name string, mapping map[string]interface{}, parse func(t return nil, fmt.Errorf("unsupported format type: %s", schema.Format) } - path := C.Path.Resolve(schema.Path) var vehicle P.Vehicle switch schema.Type { case "file": + path := C.Path.Resolve(schema.Path) vehicle = resource.NewFileVehicle(path) case "http": - vehicle = resource.NewHTTPVehicle(schema.URL, path) + if schema.Path != "" { + path := C.Path.Resolve(schema.Path) + if !C.Path.IsSafePath(path) { + return nil, fmt.Errorf("%w: %s", errSubPath, path) + } + vehicle = resource.NewHTTPVehicle(schema.URL, path) + } else { + path := C.Path.GetRandomPath("rules", schema.URL) + vehicle = resource.NewHTTPVehicle(schema.URL, path) + } + default: return nil, fmt.Errorf("unsupported vehicle type: %s", schema.Type) }