From 9aee04b58764fc48687b5b3448ac45dc34de1335 Mon Sep 17 00:00:00 2001 From: WaterLemons2k <62788816+WaterLemons2k@users.noreply.github.com> Date: Sun, 10 Mar 2024 21:14:06 +0800 Subject: [PATCH] fix(web): logging if no domain is entered (#1038) * fix(web): IPv4/6 cannot be enabled without domains Currently, if IPv4/6 is enabled but there is no domain, nothing happens. In this case, we should throw an error. * fix: replace errors with logs * fix: logging only if no domain is entered * feat: logging index --- util/messages.go | 1 + util/ordinal.go | 36 ++++++++++++++++++++++++++++++++++++ util/ordinal_test.go | 38 ++++++++++++++++++++++++++++++++++++++ web/save.go | 32 +++++++++++++++++++------------- 4 files changed, 94 insertions(+), 13 deletions(-) create mode 100644 util/ordinal.go create mode 100644 util/ordinal_test.go diff --git a/util/messages.go b/util/messages.go index 7187c52da..215ac52a1 100644 --- a/util/messages.go +++ b/util/messages.go @@ -57,6 +57,7 @@ func init() { message.SetString(language.English, "修改 '通过命令获取' 必须设置帐号密码,请先设置帐号密码", "Modify 'Get by command' must set username/password, please set username/password first") message.SetString(language.English, "密码不安全!尝试使用更长的密码", "insecure password, try using a longer password") message.SetString(language.English, "数据解析失败, 请刷新页面重试", "Data parsing failed, please refresh the page and try again") + message.SetString(language.English, "第 %s 个配置未填写域名", "The %s config does not fill in the domain") // config message.SetString(language.English, "从网卡获得IPv4失败", "Get IPv4 from network card failed") diff --git a/util/ordinal.go b/util/ordinal.go new file mode 100644 index 000000000..0afb9470c --- /dev/null +++ b/util/ordinal.go @@ -0,0 +1,36 @@ +package util + +import ( + "strconv" + + "golang.org/x/text/language" +) + +// Ordinal returns the ordinal format of the given number. +// +// See also: https://github.com/dustin/go-humanize/blob/master/ordinals.go +func Ordinal(x int, lang string) string { + s := strconv.Itoa(x) + + // Chinese doesn't require an ordinal + if lang == language.Chinese.String() { + return s + } + + suffix := "th" + switch x % 10 { + case 1: + if x%100 != 11 { + suffix = "st" + } + case 2: + if x%100 != 12 { + suffix = "nd" + } + case 3: + if x%100 != 13 { + suffix = "rd" + } + } + return s + suffix +} diff --git a/util/ordinal_test.go b/util/ordinal_test.go new file mode 100644 index 000000000..de34983e0 --- /dev/null +++ b/util/ordinal_test.go @@ -0,0 +1,38 @@ +package util + +import "testing" + +func TestOrdinal(t *testing.T) { + lang := "en" + + tests := []struct { + name string + got string + want string + }{ + {"0", Ordinal(0, lang), "0th"}, + {"1", Ordinal(1, lang), "1st"}, + {"2", Ordinal(2, lang), "2nd"}, + {"3", Ordinal(3, lang), "3rd"}, + {"4", Ordinal(4, lang), "4th"}, + {"10", Ordinal(10, lang), "10th"}, + {"11", Ordinal(11, lang), "11th"}, + {"12", Ordinal(12, lang), "12th"}, + {"13", Ordinal(13, lang), "13th"}, + {"21", Ordinal(21, lang), "21st"}, + {"32", Ordinal(32, lang), "32nd"}, + {"43", Ordinal(43, lang), "43rd"}, + {"101", Ordinal(101, lang), "101st"}, + {"102", Ordinal(102, lang), "102nd"}, + {"103", Ordinal(103, lang), "103rd"}, + {"211", Ordinal(211, lang), "211th"}, + {"212", Ordinal(212, lang), "212th"}, + {"213", Ordinal(213, lang), "213th"}, + } + + for _, tt := range tests { + if tt.got != tt.want { + t.Errorf("On %s, Expected %s, but got %s", tt.name, tt.want, tt.got) + } + } +} diff --git a/web/save.go b/web/save.go index bca8b971e..14c8a99e0 100755 --- a/web/save.go +++ b/web/save.go @@ -28,7 +28,8 @@ func Save(writer http.ResponseWriter, request *http.Request) { } func checkAndSave(request *http.Request) string { - conf, _ := config.GetConfigCached() + conf, confErr := config.GetConfigCached() + firstTime := confErr != nil // 从请求中读取 JSON 数据 var data struct { @@ -55,8 +56,6 @@ func checkAndSave(request *http.Request) string { // 验证安全性后才允许设置保存配置文件: if time.Now().Unix()-startTime > 5*60 { - firstTime := err != nil - // 首次设置 && 通过外网访问 必需在服务启动的 5 分钟内 if firstTime && (!util.IsPrivateNetwork(request.RemoteAddr) || !util.IsPrivateNetwork(request.Host)) { @@ -107,27 +106,25 @@ func checkAndSave(request *http.Request) string { dnsConf.DNS.Name = v.DnsName dnsConf.DNS.ID = strings.TrimSpace(v.DnsID) dnsConf.DNS.Secret = strings.TrimSpace(v.DnsSecret) + + if v.Ipv4Domains == "" && v.Ipv6Domains == "" { + util.Log("第 %s 个配置未填写域名", util.Ordinal(k+1, conf.Lang)) + } + dnsConf.Ipv4.Enable = v.Ipv4Enable dnsConf.Ipv4.GetType = v.Ipv4GetType dnsConf.Ipv4.URL = strings.TrimSpace(v.Ipv4Url) dnsConf.Ipv4.NetInterface = v.Ipv4NetInterface dnsConf.Ipv4.Cmd = strings.TrimSpace(v.Ipv4Cmd) - if strings.Contains(v.Ipv4Domains, "\r\n") { - dnsConf.Ipv4.Domains = strings.Split(v.Ipv4Domains, "\r\n") - } else { - dnsConf.Ipv4.Domains = strings.Split(v.Ipv4Domains, "\n") - } + dnsConf.Ipv4.Domains = splitLines(v.Ipv4Domains) + dnsConf.Ipv6.Enable = v.Ipv6Enable dnsConf.Ipv6.GetType = v.Ipv6GetType dnsConf.Ipv6.URL = strings.TrimSpace(v.Ipv6Url) dnsConf.Ipv6.NetInterface = v.Ipv6NetInterface dnsConf.Ipv6.Cmd = strings.TrimSpace(v.Ipv6Cmd) dnsConf.Ipv6.Ipv6Reg = strings.TrimSpace(v.Ipv6Reg) - if strings.Contains(v.Ipv6Domains, "\r\n") { - dnsConf.Ipv6.Domains = strings.Split(v.Ipv6Domains, "\r\n") - } else { - dnsConf.Ipv6.Domains = strings.Split(v.Ipv6Domains, "\n") - } + dnsConf.Ipv6.Domains = splitLines(v.Ipv6Domains) if k < len(conf.DnsConf) { c := &conf.DnsConf[k] @@ -163,3 +160,12 @@ func checkAndSave(request *http.Request) string { } return "ok" } + +// splitLines splits a string into lines by '\r\n' or '\n'. +func splitLines(s string) []string { + if strings.Contains(s, "\r\n") { + return strings.Split(s, "\r\n") + } + + return strings.Split(s, "\n") +}