|
@@ -34,6 +34,8 @@ import (
|
|
|
"github.com/shirou/gopsutil/v4/load"
|
|
"github.com/shirou/gopsutil/v4/load"
|
|
|
"github.com/shirou/gopsutil/v4/mem"
|
|
"github.com/shirou/gopsutil/v4/mem"
|
|
|
"github.com/shirou/gopsutil/v4/net"
|
|
"github.com/shirou/gopsutil/v4/net"
|
|
|
|
|
+ "github.com/xtls/xray-core/app/router"
|
|
|
|
|
+ "google.golang.org/protobuf/proto"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
// ProcessState represents the current state of a system process.
|
|
// ProcessState represents the current state of a system process.
|
|
@@ -1055,6 +1057,48 @@ func (s *ServerService) IsValidGeofileName(filename string) bool {
|
|
|
return matched
|
|
return matched
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// NormalizeGeositeCountryCodes reads a geosite .dat file, uppercases all
|
|
|
|
|
+// country_code fields, and writes it back. This works around a case-sensitivity
|
|
|
|
|
+// mismatch in Xray-core: the router normalizes codes to uppercase before lookup,
|
|
|
|
|
+// but the find() function compares bytes case-sensitively. Some geosite.dat
|
|
|
|
|
+// providers (e.g. Loyalsoldier) store codes in lowercase, causing lookup failures.
|
|
|
|
|
+func NormalizeGeositeCountryCodes(path string) error {
|
|
|
|
|
+ data, err := os.ReadFile(path)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return fmt.Errorf("failed to read geosite file %s: %w", path, err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ var list router.GeoSiteList
|
|
|
|
|
+ if err := proto.Unmarshal(data, &list); err != nil {
|
|
|
|
|
+ return fmt.Errorf("failed to parse geosite file %s: %w", path, err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ changed := false
|
|
|
|
|
+ for _, entry := range list.Entry {
|
|
|
|
|
+ upper := strings.ToUpper(entry.CountryCode)
|
|
|
|
|
+ if entry.CountryCode != upper {
|
|
|
|
|
+ entry.CountryCode = upper
|
|
|
|
|
+ changed = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if !changed {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ normalized, err := proto.Marshal(&list)
|
|
|
|
|
+ if err != nil {
|
|
|
|
|
+ return fmt.Errorf("failed to serialize normalized geosite file %s: %w", path, err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if err := os.WriteFile(path, normalized, 0o644); err != nil {
|
|
|
|
|
+ return fmt.Errorf("failed to write normalized geosite file %s: %w", path, err)
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ logger.Infof("Normalized country codes to uppercase in %s (%d entries)", path, len(list.Entry))
|
|
|
|
|
+ return nil
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (s *ServerService) UpdateGeofile(fileName string) error {
|
|
func (s *ServerService) UpdateGeofile(fileName string) error {
|
|
|
type geofileEntry struct {
|
|
type geofileEntry struct {
|
|
|
URL string
|
|
URL string
|
|
@@ -1146,12 +1190,22 @@ func (s *ServerService) UpdateGeofile(fileName string) error {
|
|
|
|
|
|
|
|
var errorMessages []string
|
|
var errorMessages []string
|
|
|
|
|
|
|
|
|
|
+ normalizeIfGeosite := func(destPath, name string) {
|
|
|
|
|
+ if strings.Contains(name, "geosite") {
|
|
|
|
|
+ if err := NormalizeGeositeCountryCodes(destPath); err != nil {
|
|
|
|
|
+ logger.Warningf("Failed to normalize geosite country codes in %s: %v", name, err)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if fileName == "" {
|
|
if fileName == "" {
|
|
|
// Download all geofiles
|
|
// Download all geofiles
|
|
|
for _, entry := range geofileAllowlist {
|
|
for _, entry := range geofileAllowlist {
|
|
|
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
|
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
|
|
if err := downloadFile(entry.URL, destPath); err != nil {
|
|
if err := downloadFile(entry.URL, destPath); err != nil {
|
|
|
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
|
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ normalizeIfGeosite(destPath, entry.FileName)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
} else {
|
|
} else {
|
|
@@ -1159,6 +1213,8 @@ func (s *ServerService) UpdateGeofile(fileName string) error {
|
|
|
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
|
destPath := filepath.Join(config.GetBinFolderPath(), entry.FileName)
|
|
|
if err := downloadFile(entry.URL, destPath); err != nil {
|
|
if err := downloadFile(entry.URL, destPath); err != nil {
|
|
|
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
|
errorMessages = append(errorMessages, fmt.Sprintf("Error downloading Geofile '%s': %v", entry.FileName, err))
|
|
|
|
|
+ } else {
|
|
|
|
|
+ normalizeIfGeosite(destPath, entry.FileName)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|