diff --git a/app/geodata/download_test.go b/app/geodata/download_test.go index 981ebab77..0d6324c29 100644 --- a/app/geodata/download_test.go +++ b/app/geodata/download_test.go @@ -76,6 +76,16 @@ func TestDownloadOneLuaGuard(t *testing.T) { } func TestProtobufConfigValidation(t *testing.T) { + dir := t.TempDir() + t.Setenv("xray.location.asset", dir) + for _, name := range []string{"asset.dat", "asset.DAT"} { + if err := os.WriteFile(filepath.Join(dir, name), nil, 0o600); err != nil { + t.Fatal(err) + } + } + if err := os.Mkdir(filepath.Join(dir, "directory.dat"), 0o700); err != nil { + t.Fatal(err) + } server, err := core.New(&core.Config{}) if err != nil { t.Fatal(err) @@ -95,6 +105,8 @@ func TestProtobufConfigValidation(t *testing.T) { {"uppercase extension", &Config{Cron: "@daily", Assets: []*Asset{{Url: "https://example.com/asset.dat", File: "asset.DAT"}}}, ""}, {"invalid extension", &Config{Cron: "@daily", Assets: []*Asset{{Url: "https://example.com/asset.dat", File: "asset.lua"}}}, "extension must be .dat"}, {"missing extension", &Config{Cron: "@daily", Assets: []*Asset{{Url: "https://example.com/asset.dat", File: "asset"}}}, "extension must be .dat"}, + {"missing file", &Config{Cron: "@daily", Assets: []*Asset{{Url: "https://example.com/asset.dat", File: "missing.dat"}}}, "invalid geodata asset file"}, + {"directory", &Config{Cron: "@daily", Assets: []*Asset{{Url: "https://example.com/asset.dat", File: "directory.dat"}}}, "asset is not a regular file"}, } { t.Run(tc.name, func(t *testing.T) { config, err := serial.ToTypedMessage(tc.config).GetInstance() diff --git a/app/geodata/geodata.go b/app/geodata/geodata.go index c69ba3c61..6f06d3e7c 100644 --- a/app/geodata/geodata.go +++ b/app/geodata/geodata.go @@ -11,6 +11,7 @@ import ( "github.com/xtls/xray-core/common" "github.com/xtls/xray-core/common/errors" commongeodata "github.com/xtls/xray-core/common/geodata" + "github.com/xtls/xray-core/common/platform/filesystem" "github.com/xtls/xray-core/core" "github.com/xtls/xray-core/features/routing" ) @@ -35,6 +36,9 @@ func New(ctx context.Context, config *Config) (*Instance, error) { if !strings.EqualFold(filepath.Ext(asset.GetFile()), ".dat") { return nil, errors.New("geodata asset file extension must be .dat") } + if _, err := filesystem.StatAsset(asset.GetFile()); err != nil { + return nil, errors.New("invalid geodata asset file: ", asset.GetFile()).Base(err) + } } schedule, err := cron.ParseStandard(config.Cron) if err != nil { diff --git a/infra/conf/geodata.go b/infra/conf/geodata.go index f79a37e23..20e7520a2 100644 --- a/infra/conf/geodata.go +++ b/infra/conf/geodata.go @@ -2,13 +2,10 @@ package conf import ( "net/url" - "path/filepath" - "strings" "github.com/robfig/cron/v3" "github.com/xtls/xray-core/app/geodata" "github.com/xtls/xray-core/common/errors" - "github.com/xtls/xray-core/common/platform/filesystem" "google.golang.org/protobuf/proto" ) @@ -21,12 +18,6 @@ func (c *GeodataAssetConfig) Build() (*geodata.Asset, error) { if err := validateHTTPS(c.URL); err != nil { return nil, errors.New("invalid geodata asset url: ", c.URL).Base(err) } - if !strings.EqualFold(filepath.Ext(c.File), ".dat") { - return nil, errors.New("geodata asset file extension must be .dat") - } - if _, err := filesystem.StatAsset(c.File); err != nil { - return nil, errors.New("invalid geodata asset file: ", c.File).Base(err) - } return &geodata.Asset{ Url: c.URL, File: c.File, diff --git a/infra/conf/geodata_test.go b/infra/conf/geodata_test.go index 4944d850a..4ce47c886 100644 --- a/infra/conf/geodata_test.go +++ b/infra/conf/geodata_test.go @@ -1,9 +1,6 @@ package conf_test import ( - "os" - "path/filepath" - "strings" "testing" "github.com/xtls/xray-core/app/geodata" @@ -11,8 +8,6 @@ import ( ) func TestGeodataConfig(t *testing.T) { - t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources")) - creator := func() Buildable { return new(GeodataConfig) } @@ -40,27 +35,7 @@ func TestGeodataConfig(t *testing.T) { }) } -func TestGeodataAssetConfig(t *testing.T) { - t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources")) - - if _, err := (&GeodataAssetConfig{ - URL: "https://example.com/geoip.dat", - File: "geoip.dat", - }).Build(); err != nil { - t.Fatal(err) - } - - if _, err := (&GeodataAssetConfig{ - URL: "https://example.com/geoip.dat", - File: "missing.dat", - }).Build(); err == nil { - t.Fatal("expected error") - } -} - func TestGeodataAssetConfigInvalidURL(t *testing.T) { - t.Setenv("xray.location.asset", filepath.Join("..", "..", "resources")) - for _, rawURL := range []string{ "", "http://example.com/geoip.dat", @@ -75,34 +50,3 @@ func TestGeodataAssetConfigInvalidURL(t *testing.T) { } } } - -func TestGeodataAssetConfigFileExtension(t *testing.T) { - dir := t.TempDir() - t.Setenv("xray.location.asset", dir) - for _, tc := range []struct { - name string - valid bool - }{ - {"custom.dat", true}, - {"custom.DAT", true}, - {"launcher.cmd", false}, - {"script.lua", false}, - {"config.json", false}, - {"asset", false}, - } { - if err := os.WriteFile(filepath.Join(dir, tc.name), nil, 0o600); err != nil { - t.Fatal(err) - } - _, err := (&GeodataAssetConfig{ - URL: "https://example.com/download", - File: tc.name, - }).Build() - if tc.valid { - if err != nil { - t.Fatalf("Build(%q): %v", tc.name, err) - } - } else if err == nil || !strings.Contains(err.Error(), "extension must be .dat") { - t.Fatalf("Build(%q) = %v; want .dat extension error", tc.name, err) - } - } -}