github.com/binbinly/pkg@v0.0.11-0.20240321014439-f4fbf666eb0f/util/validator/validator.go (about)

     1  package validator
     2  
     3  import (
     4  	"encoding/json"
     5  	"net"
     6  	"net/url"
     7  	"regexp"
     8  	"strconv"
     9  	"strings"
    10  	"unicode"
    11  )
    12  
    13  var (
    14  	AlphaMatcher         = regexp.MustCompile(`^[a-zA-Z]+$`)
    15  	LetterRegexMatcher   = regexp.MustCompile(`[a-zA-Z]`)
    16  	NumberRegexMatcher   = regexp.MustCompile(`\d`)
    17  	IntStrMatcher        = regexp.MustCompile(`^[\+-]?\d+$`)
    18  	UrlMatcher           = regexp.MustCompile(`^((ftp|http|https?):\/\/)?(\S+(:\S*)?@)?((([1-9]\d?|1\d\d|2[01]\d|22[0-3])(\.(1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.([0-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(([a-zA-Z0-9]+([-\.][a-zA-Z0-9]+)*)|((www\.)?))?(([a-z\x{00a1}-\x{ffff}0-9]+-?-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.([a-z\x{00a1}-\x{ffff}]{2,}))?))(:(\d{1,5}))?((\/|\?|#)[^\s]*)?$`)
    19  	DnsMatcher           = regexp.MustCompile(`^[a-zA-Z]([a-zA-Z0-9\-]+[\.]?)*[a-zA-Z0-9]$`)
    20  	EmailMatcher         = regexp.MustCompile(`\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*`)
    21  	ChineseMobileMatcher = regexp.MustCompile(`^1(?:3\d|4[4-9]|5[0-35-9]|6[67]|7[013-8]|8\d|9\d)\d{8}$`)
    22  	ChineseIdMatcher     = regexp.MustCompile(`^[1-9]\d{5}(18|19|20|21|22)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$`)
    23  	ChineseMatcher       = regexp.MustCompile("[\u4e00-\u9fa5]")
    24  	ChinesePhoneMatcher  = regexp.MustCompile(`\d{3}-\d{8}|\d{4}-\d{7}|\d{4}-\d{8}`)
    25  	CreditCardMatcher    = regexp.MustCompile(`^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\\d{3})\\d{11}|6[27][0-9]{14})$`)
    26  	Base64Matcher        = regexp.MustCompile(`^(?:[A-Za-z0-9+\\/]{4})*(?:[A-Za-z0-9+\\/]{2}==|[A-Za-z0-9+\\/]{3}=|[A-Za-z0-9+\\/]{4})$`)
    27  )
    28  
    29  // RegexMatch check if the string match the regexp.
    30  func RegexMatch(str string, regex *regexp.Regexp) bool {
    31  	return regex.MatchString(str)
    32  }
    33  
    34  // IsAllUpper check if the string is all upper case letters A-Z.
    35  // Play: https://go.dev/play/p/ZHctgeK1n4Z
    36  func IsAllUpper(str string) bool {
    37  	for _, r := range str {
    38  		if !unicode.IsUpper(r) {
    39  			return false
    40  		}
    41  	}
    42  	return str != ""
    43  }
    44  
    45  // IsAllLower check if the string is all lower case letters a-z.
    46  // Play: https://go.dev/play/p/GjqCnOfV6cM
    47  func IsAllLower(str string) bool {
    48  	for _, r := range str {
    49  		if !unicode.IsLower(r) {
    50  			return false
    51  		}
    52  	}
    53  	return str != ""
    54  }
    55  
    56  // IsASCII checks if string is all ASCII char.
    57  // Play: https://go.dev/play/p/hfQNPLX0jNa
    58  func IsASCII(str string) bool {
    59  	for i := 0; i < len(str); i++ {
    60  		if str[i] > unicode.MaxASCII {
    61  			return false
    62  		}
    63  	}
    64  	return true
    65  }
    66  
    67  // IsPrintable checks if string is all printable chars.
    68  // Play: https://go.dev/play/p/Pe1FE2gdtTP
    69  func IsPrintable(str string) bool {
    70  	for _, r := range str {
    71  		if !unicode.IsPrint(r) {
    72  			if r == '\n' || r == '\r' || r == '\t' || r == '`' {
    73  				continue
    74  			}
    75  			return false
    76  		}
    77  	}
    78  	return true
    79  }
    80  
    81  // ContainUpper check if the string contain at least one upper case letter A-Z.
    82  // Play: https://go.dev/play/p/CmWeBEk27-z
    83  func ContainUpper(str string) bool {
    84  	for _, r := range str {
    85  		if unicode.IsUpper(r) && unicode.IsLetter(r) {
    86  			return true
    87  		}
    88  	}
    89  	return false
    90  }
    91  
    92  // ContainLower check if the string contain at least one lower case letter a-z.
    93  // Play: https://go.dev/play/p/Srqi1ItvnAA
    94  func ContainLower(str string) bool {
    95  	for _, r := range str {
    96  		if unicode.IsLower(r) && unicode.IsLetter(r) {
    97  			return true
    98  		}
    99  	}
   100  	return false
   101  }
   102  
   103  // IsJSON checks if the string is valid JSON.
   104  // Play: https://go.dev/play/p/8Kip1Itjiil
   105  func IsJSON(str string) bool {
   106  	var js json.RawMessage
   107  	return json.Unmarshal([]byte(str), &js) == nil
   108  }
   109  
   110  // IsNumberStr check if the string can convert to a number.
   111  // Play: https://go.dev/play/p/LzaKocSV79u
   112  func IsNumberStr(s string) bool {
   113  	return IsIntStr(s) || IsFloatStr(s)
   114  }
   115  
   116  // IsFloatStr check if the string can convert to a float.
   117  // Play: https://go.dev/play/p/LOYwS_Oyl7U
   118  func IsFloatStr(str string) bool {
   119  	_, e := strconv.ParseFloat(str, 64)
   120  	return e == nil
   121  }
   122  
   123  // IsIntStr check if the string can convert to a integer.
   124  // Play: https://go.dev/play/p/jQRtFv-a0Rk
   125  func IsIntStr(str string) bool {
   126  	return IntStrMatcher.MatchString(str)
   127  }
   128  
   129  // IsIp check if the string is a ip address.
   130  // Play: https://go.dev/play/p/FgcplDvmxoD
   131  func IsIp(ipstr string) bool {
   132  	ip := net.ParseIP(ipstr)
   133  	return ip != nil
   134  }
   135  
   136  // IsIpV4 check if the string is a ipv4 address.
   137  // Play: https://go.dev/play/p/zBGT99EjaIu
   138  func IsIpV4(ipstr string) bool {
   139  	ip := net.ParseIP(ipstr)
   140  	if ip == nil {
   141  		return false
   142  	}
   143  	return strings.Contains(ipstr, ".")
   144  }
   145  
   146  // IsIpV6 check if the string is a ipv6 address.
   147  // Play: https://go.dev/play/p/AHA0r0AzIdC
   148  func IsIpV6(ipstr string) bool {
   149  	ip := net.ParseIP(ipstr)
   150  	if ip == nil {
   151  		return false
   152  	}
   153  	return strings.Contains(ipstr, ":")
   154  }
   155  
   156  // IsPort check if the string is a valid net port.
   157  // Play:
   158  func IsPort(str string) bool {
   159  	if i, err := strconv.ParseInt(str, 10, 64); err == nil && i > 0 && i < 65536 {
   160  		return true
   161  	}
   162  	return false
   163  }
   164  
   165  // IsUrl check if the string is url.
   166  // Play: https://go.dev/play/p/pbJGa7F98Ka
   167  func IsUrl(str string) bool {
   168  	if str == "" || len(str) >= 2083 || len(str) <= 3 || strings.HasPrefix(str, ".") {
   169  		return false
   170  	}
   171  	u, err := url.Parse(str)
   172  	if err != nil {
   173  		return false
   174  	}
   175  	if strings.HasPrefix(u.Host, ".") {
   176  		return false
   177  	}
   178  	if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
   179  		return false
   180  	}
   181  
   182  	return UrlMatcher.MatchString(str)
   183  }
   184  
   185  // IsEmptyString check if the string is empty.
   186  // Play: https://go.dev/play/p/dpzgUjFnBCX
   187  func IsEmptyString(str string) bool {
   188  	return len(str) == 0
   189  }
   190  
   191  // IsRegexMatch check if the string match the regexp.
   192  // Play: https://go.dev/play/p/z_XeZo_litG
   193  func IsRegexMatch(str, regex string) bool {
   194  	reg := regexp.MustCompile(regex)
   195  	return reg.MatchString(str)
   196  }
   197  
   198  // IsStrongPassword check if the string is strong password, if len(password) is less than the length param, return false
   199  // Strong password: alpha(lower+upper) + number + special chars(!@#$%^&*()?><).
   200  // Play: https://go.dev/play/p/QHdVcSQ3uDg
   201  func IsStrongPassword(password string, length int) bool {
   202  	if len(password) < length {
   203  		return false
   204  	}
   205  	var num, lower, upper, special bool
   206  	for _, r := range password {
   207  		switch {
   208  		case unicode.IsDigit(r):
   209  			num = true
   210  		case unicode.IsUpper(r):
   211  			upper = true
   212  		case unicode.IsLower(r):
   213  			lower = true
   214  		case unicode.IsSymbol(r), unicode.IsPunct(r):
   215  			special = true
   216  		}
   217  	}
   218  
   219  	return num && lower && upper && special
   220  }
   221  
   222  // IsWeakPassword check if the string is weak password
   223  // Weak password: only letter or only number or letter + number.
   224  // Play: https://go.dev/play/p/wqakscZH5gH
   225  func IsWeakPassword(password string) bool {
   226  	var num, letter, special bool
   227  	for _, r := range password {
   228  		switch {
   229  		case unicode.IsDigit(r):
   230  			num = true
   231  		case unicode.IsLetter(r):
   232  			letter = true
   233  		case unicode.IsSymbol(r), unicode.IsPunct(r):
   234  			special = true
   235  		}
   236  	}
   237  
   238  	return (num || letter) && !special
   239  }
   240  
   241  // IsNumber check if the value is number(integer, float) or not.
   242  // Play: https://go.dev/play/p/mdJHOAvtsvF
   243  func IsNumber(v any) bool {
   244  	return IsInt(v) || IsFloat(v)
   245  }
   246  
   247  // IsFloat check if the value is float(float32, float34) or not.
   248  // Play: https://go.dev/play/p/vsyG-sxr99_Z
   249  func IsFloat(v any) bool {
   250  	switch v.(type) {
   251  	case float32, float64:
   252  		return true
   253  	}
   254  	return false
   255  }
   256  
   257  // IsInt check if the value is integer(int, unit) or not.
   258  // Play: https://go.dev/play/p/eFoIHbgzl-z
   259  func IsInt(v any) bool {
   260  	switch v.(type) {
   261  	case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64, uintptr:
   262  		return true
   263  	}
   264  	return false
   265  }