diff --git a/pkg/utils/helper.go b/pkg/utils/helper.go index ba11029e..7919e2fd 100644 --- a/pkg/utils/helper.go +++ b/pkg/utils/helper.go @@ -3,6 +3,7 @@ package utils import ( "errors" "fmt" + "net" "regexp" "strconv" "strings" @@ -39,6 +40,59 @@ func FormatUrl(url string) string { return url } +// ValidateDomain validates subdomain, IP, or top-level domain formats +func ValidateDomain(domain string) error { + if strings.Contains(domain, ":") { + parts := strings.Split(domain, ":") + if len(parts) != 2 { + return errors.New("invalid domain format: too many colons") + } + port, err := strconv.Atoi(parts[1]) + if err != nil || port < 0 || port > 65535 { + return errors.New("invalid port number") + } + domain = parts[0] + } + + if net.ParseIP(domain) != nil { + return nil + } + + parts := strings.Split(domain, ".") + if len(parts) < 2 { + return errors.New("invalid domain: must have at least one dot") + } + + for _, part := range parts { + if !isValidLabel(part) { + return fmt.Errorf("invalid domain label: %s", part) + } + } + + if len(parts[len(parts)-1]) < 2 { + return errors.New("invalid top-level domain: must be at least 2 characters") + } + + return nil +} + +// Helper function to validate individual domain labels +func isValidLabel(label string) bool { + if len(label) == 0 || len(label) > 63 { + return false + } + + for i, ch := range label { + if !(ch >= 'a' && ch <= 'z' || ch >= 'A' && ch <= 'Z' || ch >= '0' && ch <= '9' || ch == '-') { + return false + } + if (i == 0 || i == len(label)-1) && ch == '-' { + return false + } + } + return true +} + func FormatSize(size int64) string { mbSize := float64(size) / (1024 * 1024) return fmt.Sprintf("%.2fMiB", mbSize) diff --git a/pkg/views/login/create.go b/pkg/views/login/create.go index ad653521..17bb9c90 100644 --- a/pkg/views/login/create.go +++ b/pkg/views/login/create.go @@ -3,7 +3,6 @@ package login import ( "errors" "fmt" - "net/url" "strings" "github.com/charmbracelet/huh" @@ -32,10 +31,11 @@ func CreateView(loginView *LoginView) { if strings.TrimSpace(str) == "" { return errors.New("server cannot be empty or only spaces") } - formattedUrl := utils.FormatUrl(str) - if _, err := url.ParseRequestURI(formattedUrl); err != nil { - return errors.New("please enter the correct server format") + err := utils.ValidateDomain(str) + if err != nil { + return err } + return nil }), huh.NewInput().