mirror of
https://github.com/portainer/portainer.git
synced 2025-07-19 05:19:39 +02:00
fix(validate): refactor validate functions [BE-11574] (#683)
This commit is contained in:
parent
1a3df54c04
commit
4e4fd5a4b4
2 changed files with 25 additions and 39 deletions
|
@ -6,62 +6,33 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode/utf8"
|
"unicode/utf8"
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
"github.com/google/uuid"
|
||||||
minURLRuneCount = 3
|
|
||||||
maxURLRuneCount = 2083
|
|
||||||
|
|
||||||
ipPattern = `(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9]))`
|
|
||||||
urlSchemaPattern = `((ftp|tcp|udp|wss?|https?):\/\/)`
|
|
||||||
urlUsernamePattern = `(\S+(:\S*)?@)`
|
|
||||||
urlPathPattern = `((\/|\?|#)[^\s]*)`
|
|
||||||
urlPortPattern = `(:(\d{1,5}))`
|
|
||||||
urlIPPattern = `([1-9]\d?|1\d\d|2[01]\d|22[0-3]|24\d|25[0-5])(\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-5]))`
|
|
||||||
urlSubdomainPattern = `((www\.)|([a-zA-Z0-9]+([-_\.]?[a-zA-Z0-9])*[a-zA-Z0-9]\.[a-zA-Z0-9]+))`
|
|
||||||
urlPattern = `^` + urlSchemaPattern + `?` + urlUsernamePattern + `?` + `((` + urlIPPattern + `|(\[` + ipPattern + `\])|(([a-zA-Z0-9]([a-zA-Z0-9-_]+)?[a-zA-Z0-9]([-\.][a-zA-Z0-9]+)*)|(` + urlSubdomainPattern + `?))?(([a-zA-Z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-zA-Z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-zA-Z\x{00a1}-\x{ffff}]{1,}))?))\.?` + urlPortPattern + `?` + urlPathPattern + `?$`
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
urlRegex = regexp.MustCompile(urlPattern)
|
|
||||||
uuidRegex = regexp.MustCompile(`^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$`)
|
|
||||||
hexadecimalRegex = regexp.MustCompile(`^[0-9a-fA-F]+$`)
|
hexadecimalRegex = regexp.MustCompile(`^[0-9a-fA-F]+$`)
|
||||||
whitespaceRegex = regexp.MustCompile(`^[[:space:]]+$`)
|
|
||||||
dnsNameRegex = regexp.MustCompile(`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`)
|
dnsNameRegex = regexp.MustCompile(`^([a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62}){1}(\.[a-zA-Z0-9_]{1}[a-zA-Z0-9_-]{0,62})*[\._]?$`)
|
||||||
)
|
)
|
||||||
|
|
||||||
func IsURL(urlString string) bool {
|
func IsURL(urlString string) bool {
|
||||||
if urlString == "" ||
|
if len(urlString) == 0 {
|
||||||
utf8.RuneCountInString(urlString) >= maxURLRuneCount ||
|
|
||||||
len(urlString) <= minURLRuneCount ||
|
|
||||||
strings.HasPrefix(urlString, ".") {
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
strTemp := urlString
|
strTemp := urlString
|
||||||
if strings.Contains(urlString, ":") && !strings.Contains(urlString, "://") {
|
if !strings.Contains(urlString, "://") {
|
||||||
// support no indicated urlscheme but with colon for port number
|
// support no indicated urlscheme
|
||||||
// http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
|
// http:// is appended so url.Parse will succeed
|
||||||
strTemp = "http://" + urlString
|
strTemp = "http://" + urlString
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(strTemp)
|
u, err := url.Parse(strTemp)
|
||||||
if err != nil {
|
return err == nil && u.Host != ""
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if strings.HasPrefix(u.Host, ".") {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return urlRegex.MatchString(urlString)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsUUID(uuidString string) bool {
|
func IsUUID(uuidString string) bool {
|
||||||
return uuidRegex.MatchString(uuidString)
|
return uuid.Validate(uuidString) == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsHexadecimal(hexString string) bool {
|
func IsHexadecimal(hexString string) bool {
|
||||||
|
@ -69,7 +40,7 @@ func IsHexadecimal(hexString string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func HasWhitespaceOnly(s string) bool {
|
func HasWhitespaceOnly(s string) bool {
|
||||||
return len(s) > 0 && whitespaceRegex.MatchString(s)
|
return len(s) > 0 && strings.TrimSpace(s) == ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func MinStringLength(s string, len int) bool {
|
func MinStringLength(s string, len int) bool {
|
||||||
|
|
|
@ -17,6 +17,11 @@ func Test_IsURL(t *testing.T) {
|
||||||
url: "https://google.com",
|
url: "https://google.com",
|
||||||
expectedResult: true,
|
expectedResult: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
url: "",
|
||||||
|
expectedResult: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "no schema",
|
name: "no schema",
|
||||||
url: "google.com",
|
url: "google.com",
|
||||||
|
@ -33,9 +38,14 @@ func Test_IsURL(t *testing.T) {
|
||||||
expectedResult: true,
|
expectedResult: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "invalid",
|
name: "no top level domain",
|
||||||
url: "google",
|
url: "google",
|
||||||
expectedResult: false,
|
expectedResult: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Unicode URL",
|
||||||
|
url: "www.xn--exampe-7db.ai",
|
||||||
|
expectedResult: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,6 +155,11 @@ func Test_HasWhitespaceOnly(t *testing.T) {
|
||||||
s: "something like this",
|
s: "something like this",
|
||||||
expectedResult: false,
|
expectedResult: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "all whitespace",
|
||||||
|
s: "\t\n\v\f\r ",
|
||||||
|
expectedResult: true,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue