baked_in.go 62 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285
  1. package validator
  2. import (
  3. "bytes"
  4. "context"
  5. "crypto/sha256"
  6. "encoding/hex"
  7. "encoding/json"
  8. "fmt"
  9. "net"
  10. "net/url"
  11. "os"
  12. "reflect"
  13. "strconv"
  14. "strings"
  15. "sync"
  16. "time"
  17. "unicode/utf8"
  18. "golang.org/x/crypto/sha3"
  19. urn "github.com/leodido/go-urn"
  20. )
  21. // Func accepts a FieldLevel interface for all validation needs. The return
  22. // value should be true when validation succeeds.
  23. type Func func(fl FieldLevel) bool
  24. // FuncCtx accepts a context.Context and FieldLevel interface for all
  25. // validation needs. The return value should be true when validation succeeds.
  26. type FuncCtx func(ctx context.Context, fl FieldLevel) bool
  27. // wrapFunc wraps noramal Func makes it compatible with FuncCtx
  28. func wrapFunc(fn Func) FuncCtx {
  29. if fn == nil {
  30. return nil // be sure not to wrap a bad function.
  31. }
  32. return func(ctx context.Context, fl FieldLevel) bool {
  33. return fn(fl)
  34. }
  35. }
  36. var (
  37. restrictedTags = map[string]struct{}{
  38. diveTag: {},
  39. keysTag: {},
  40. endKeysTag: {},
  41. structOnlyTag: {},
  42. omitempty: {},
  43. skipValidationTag: {},
  44. utf8HexComma: {},
  45. utf8Pipe: {},
  46. noStructLevelTag: {},
  47. requiredTag: {},
  48. isdefault: {},
  49. }
  50. // BakedInAliasValidators is a default mapping of a single validation tag that
  51. // defines a common or complex set of validation(s) to simplify
  52. // adding validation to structs.
  53. bakedInAliases = map[string]string{
  54. "iscolor": "hexcolor|rgb|rgba|hsl|hsla",
  55. "country_code": "iso3166_1_alpha2|iso3166_1_alpha3|iso3166_1_alpha_numeric",
  56. }
  57. // BakedInValidators is the default map of ValidationFunc
  58. // you can add, remove or even replace items to suite your needs,
  59. // or even disregard and use your own map if so desired.
  60. bakedInValidators = map[string]Func{
  61. "required": hasValue,
  62. "required_if": requiredIf,
  63. "required_unless": requiredUnless,
  64. "required_with": requiredWith,
  65. "required_with_all": requiredWithAll,
  66. "required_without": requiredWithout,
  67. "required_without_all": requiredWithoutAll,
  68. "excluded_with": excludedWith,
  69. "excluded_with_all": excludedWithAll,
  70. "excluded_without": excludedWithout,
  71. "excluded_without_all": excludedWithoutAll,
  72. "isdefault": isDefault,
  73. "len": hasLengthOf,
  74. "min": hasMinOf,
  75. "max": hasMaxOf,
  76. "eq": isEq,
  77. "ne": isNe,
  78. "lt": isLt,
  79. "lte": isLte,
  80. "gt": isGt,
  81. "gte": isGte,
  82. "eqfield": isEqField,
  83. "eqcsfield": isEqCrossStructField,
  84. "necsfield": isNeCrossStructField,
  85. "gtcsfield": isGtCrossStructField,
  86. "gtecsfield": isGteCrossStructField,
  87. "ltcsfield": isLtCrossStructField,
  88. "ltecsfield": isLteCrossStructField,
  89. "nefield": isNeField,
  90. "gtefield": isGteField,
  91. "gtfield": isGtField,
  92. "ltefield": isLteField,
  93. "ltfield": isLtField,
  94. "fieldcontains": fieldContains,
  95. "fieldexcludes": fieldExcludes,
  96. "alpha": isAlpha,
  97. "alphanum": isAlphanum,
  98. "alphaunicode": isAlphaUnicode,
  99. "alphanumunicode": isAlphanumUnicode,
  100. "numeric": isNumeric,
  101. "number": isNumber,
  102. "hexadecimal": isHexadecimal,
  103. "hexcolor": isHEXColor,
  104. "rgb": isRGB,
  105. "rgba": isRGBA,
  106. "hsl": isHSL,
  107. "hsla": isHSLA,
  108. "e164": isE164,
  109. "email": isEmail,
  110. "url": isURL,
  111. "uri": isURI,
  112. "urn_rfc2141": isUrnRFC2141, // RFC 2141
  113. "file": isFile,
  114. "base64": isBase64,
  115. "base64url": isBase64URL,
  116. "contains": contains,
  117. "containsany": containsAny,
  118. "containsrune": containsRune,
  119. "excludes": excludes,
  120. "excludesall": excludesAll,
  121. "excludesrune": excludesRune,
  122. "startswith": startsWith,
  123. "endswith": endsWith,
  124. "startsnotwith": startsNotWith,
  125. "endsnotwith": endsNotWith,
  126. "isbn": isISBN,
  127. "isbn10": isISBN10,
  128. "isbn13": isISBN13,
  129. "eth_addr": isEthereumAddress,
  130. "btc_addr": isBitcoinAddress,
  131. "btc_addr_bech32": isBitcoinBech32Address,
  132. "uuid": isUUID,
  133. "uuid3": isUUID3,
  134. "uuid4": isUUID4,
  135. "uuid5": isUUID5,
  136. "uuid_rfc4122": isUUIDRFC4122,
  137. "uuid3_rfc4122": isUUID3RFC4122,
  138. "uuid4_rfc4122": isUUID4RFC4122,
  139. "uuid5_rfc4122": isUUID5RFC4122,
  140. "ascii": isASCII,
  141. "printascii": isPrintableASCII,
  142. "multibyte": hasMultiByteCharacter,
  143. "datauri": isDataURI,
  144. "latitude": isLatitude,
  145. "longitude": isLongitude,
  146. "ssn": isSSN,
  147. "ipv4": isIPv4,
  148. "ipv6": isIPv6,
  149. "ip": isIP,
  150. "cidrv4": isCIDRv4,
  151. "cidrv6": isCIDRv6,
  152. "cidr": isCIDR,
  153. "tcp4_addr": isTCP4AddrResolvable,
  154. "tcp6_addr": isTCP6AddrResolvable,
  155. "tcp_addr": isTCPAddrResolvable,
  156. "udp4_addr": isUDP4AddrResolvable,
  157. "udp6_addr": isUDP6AddrResolvable,
  158. "udp_addr": isUDPAddrResolvable,
  159. "ip4_addr": isIP4AddrResolvable,
  160. "ip6_addr": isIP6AddrResolvable,
  161. "ip_addr": isIPAddrResolvable,
  162. "unix_addr": isUnixAddrResolvable,
  163. "mac": isMAC,
  164. "hostname": isHostnameRFC952, // RFC 952
  165. "hostname_rfc1123": isHostnameRFC1123, // RFC 1123
  166. "fqdn": isFQDN,
  167. "unique": isUnique,
  168. "oneof": isOneOf,
  169. "html": isHTML,
  170. "html_encoded": isHTMLEncoded,
  171. "url_encoded": isURLEncoded,
  172. "dir": isDir,
  173. "json": isJSON,
  174. "hostname_port": isHostnamePort,
  175. "lowercase": isLowercase,
  176. "uppercase": isUppercase,
  177. "datetime": isDatetime,
  178. "timezone": isTimeZone,
  179. "iso3166_1_alpha2": isIso3166Alpha2,
  180. "iso3166_1_alpha3": isIso3166Alpha3,
  181. "iso3166_1_alpha_numeric": isIso3166AlphaNumeric,
  182. }
  183. )
  184. var oneofValsCache = map[string][]string{}
  185. var oneofValsCacheRWLock = sync.RWMutex{}
  186. func parseOneOfParam2(s string) []string {
  187. oneofValsCacheRWLock.RLock()
  188. vals, ok := oneofValsCache[s]
  189. oneofValsCacheRWLock.RUnlock()
  190. if !ok {
  191. oneofValsCacheRWLock.Lock()
  192. vals = splitParamsRegex.FindAllString(s, -1)
  193. for i := 0; i < len(vals); i++ {
  194. vals[i] = strings.Replace(vals[i], "'", "", -1)
  195. }
  196. oneofValsCache[s] = vals
  197. oneofValsCacheRWLock.Unlock()
  198. }
  199. return vals
  200. }
  201. func isURLEncoded(fl FieldLevel) bool {
  202. return uRLEncodedRegex.MatchString(fl.Field().String())
  203. }
  204. func isHTMLEncoded(fl FieldLevel) bool {
  205. return hTMLEncodedRegex.MatchString(fl.Field().String())
  206. }
  207. func isHTML(fl FieldLevel) bool {
  208. return hTMLRegex.MatchString(fl.Field().String())
  209. }
  210. func isOneOf(fl FieldLevel) bool {
  211. vals := parseOneOfParam2(fl.Param())
  212. field := fl.Field()
  213. var v string
  214. switch field.Kind() {
  215. case reflect.String:
  216. v = field.String()
  217. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  218. v = strconv.FormatInt(field.Int(), 10)
  219. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  220. v = strconv.FormatUint(field.Uint(), 10)
  221. default:
  222. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  223. }
  224. for i := 0; i < len(vals); i++ {
  225. if vals[i] == v {
  226. return true
  227. }
  228. }
  229. return false
  230. }
  231. // isUnique is the validation function for validating if each array|slice|map value is unique
  232. func isUnique(fl FieldLevel) bool {
  233. field := fl.Field()
  234. param := fl.Param()
  235. v := reflect.ValueOf(struct{}{})
  236. switch field.Kind() {
  237. case reflect.Slice, reflect.Array:
  238. elem := field.Type().Elem()
  239. if elem.Kind() == reflect.Ptr {
  240. elem = elem.Elem()
  241. }
  242. if param == "" {
  243. m := reflect.MakeMap(reflect.MapOf(elem, v.Type()))
  244. for i := 0; i < field.Len(); i++ {
  245. m.SetMapIndex(reflect.Indirect(field.Index(i)), v)
  246. }
  247. return field.Len() == m.Len()
  248. }
  249. sf, ok := elem.FieldByName(param)
  250. if !ok {
  251. panic(fmt.Sprintf("Bad field name %s", param))
  252. }
  253. sfTyp := sf.Type
  254. if sfTyp.Kind() == reflect.Ptr {
  255. sfTyp = sfTyp.Elem()
  256. }
  257. m := reflect.MakeMap(reflect.MapOf(sfTyp, v.Type()))
  258. for i := 0; i < field.Len(); i++ {
  259. m.SetMapIndex(reflect.Indirect(reflect.Indirect(field.Index(i)).FieldByName(param)), v)
  260. }
  261. return field.Len() == m.Len()
  262. case reflect.Map:
  263. m := reflect.MakeMap(reflect.MapOf(field.Type().Elem(), v.Type()))
  264. for _, k := range field.MapKeys() {
  265. m.SetMapIndex(field.MapIndex(k), v)
  266. }
  267. return field.Len() == m.Len()
  268. default:
  269. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  270. }
  271. }
  272. // IsMAC is the validation function for validating if the field's value is a valid MAC address.
  273. func isMAC(fl FieldLevel) bool {
  274. _, err := net.ParseMAC(fl.Field().String())
  275. return err == nil
  276. }
  277. // IsCIDRv4 is the validation function for validating if the field's value is a valid v4 CIDR address.
  278. func isCIDRv4(fl FieldLevel) bool {
  279. ip, _, err := net.ParseCIDR(fl.Field().String())
  280. return err == nil && ip.To4() != nil
  281. }
  282. // IsCIDRv6 is the validation function for validating if the field's value is a valid v6 CIDR address.
  283. func isCIDRv6(fl FieldLevel) bool {
  284. ip, _, err := net.ParseCIDR(fl.Field().String())
  285. return err == nil && ip.To4() == nil
  286. }
  287. // IsCIDR is the validation function for validating if the field's value is a valid v4 or v6 CIDR address.
  288. func isCIDR(fl FieldLevel) bool {
  289. _, _, err := net.ParseCIDR(fl.Field().String())
  290. return err == nil
  291. }
  292. // IsIPv4 is the validation function for validating if a value is a valid v4 IP address.
  293. func isIPv4(fl FieldLevel) bool {
  294. ip := net.ParseIP(fl.Field().String())
  295. return ip != nil && ip.To4() != nil
  296. }
  297. // IsIPv6 is the validation function for validating if the field's value is a valid v6 IP address.
  298. func isIPv6(fl FieldLevel) bool {
  299. ip := net.ParseIP(fl.Field().String())
  300. return ip != nil && ip.To4() == nil
  301. }
  302. // IsIP is the validation function for validating if the field's value is a valid v4 or v6 IP address.
  303. func isIP(fl FieldLevel) bool {
  304. ip := net.ParseIP(fl.Field().String())
  305. return ip != nil
  306. }
  307. // IsSSN is the validation function for validating if the field's value is a valid SSN.
  308. func isSSN(fl FieldLevel) bool {
  309. field := fl.Field()
  310. if field.Len() != 11 {
  311. return false
  312. }
  313. return sSNRegex.MatchString(field.String())
  314. }
  315. // IsLongitude is the validation function for validating if the field's value is a valid longitude coordinate.
  316. func isLongitude(fl FieldLevel) bool {
  317. field := fl.Field()
  318. var v string
  319. switch field.Kind() {
  320. case reflect.String:
  321. v = field.String()
  322. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  323. v = strconv.FormatInt(field.Int(), 10)
  324. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  325. v = strconv.FormatUint(field.Uint(), 10)
  326. case reflect.Float32:
  327. v = strconv.FormatFloat(field.Float(), 'f', -1, 32)
  328. case reflect.Float64:
  329. v = strconv.FormatFloat(field.Float(), 'f', -1, 64)
  330. default:
  331. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  332. }
  333. return longitudeRegex.MatchString(v)
  334. }
  335. // IsLatitude is the validation function for validating if the field's value is a valid latitude coordinate.
  336. func isLatitude(fl FieldLevel) bool {
  337. field := fl.Field()
  338. var v string
  339. switch field.Kind() {
  340. case reflect.String:
  341. v = field.String()
  342. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  343. v = strconv.FormatInt(field.Int(), 10)
  344. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  345. v = strconv.FormatUint(field.Uint(), 10)
  346. case reflect.Float32:
  347. v = strconv.FormatFloat(field.Float(), 'f', -1, 32)
  348. case reflect.Float64:
  349. v = strconv.FormatFloat(field.Float(), 'f', -1, 64)
  350. default:
  351. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  352. }
  353. return latitudeRegex.MatchString(v)
  354. }
  355. // IsDataURI is the validation function for validating if the field's value is a valid data URI.
  356. func isDataURI(fl FieldLevel) bool {
  357. uri := strings.SplitN(fl.Field().String(), ",", 2)
  358. if len(uri) != 2 {
  359. return false
  360. }
  361. if !dataURIRegex.MatchString(uri[0]) {
  362. return false
  363. }
  364. return base64Regex.MatchString(uri[1])
  365. }
  366. // HasMultiByteCharacter is the validation function for validating if the field's value has a multi byte character.
  367. func hasMultiByteCharacter(fl FieldLevel) bool {
  368. field := fl.Field()
  369. if field.Len() == 0 {
  370. return true
  371. }
  372. return multibyteRegex.MatchString(field.String())
  373. }
  374. // IsPrintableASCII is the validation function for validating if the field's value is a valid printable ASCII character.
  375. func isPrintableASCII(fl FieldLevel) bool {
  376. return printableASCIIRegex.MatchString(fl.Field().String())
  377. }
  378. // IsASCII is the validation function for validating if the field's value is a valid ASCII character.
  379. func isASCII(fl FieldLevel) bool {
  380. return aSCIIRegex.MatchString(fl.Field().String())
  381. }
  382. // IsUUID5 is the validation function for validating if the field's value is a valid v5 UUID.
  383. func isUUID5(fl FieldLevel) bool {
  384. return uUID5Regex.MatchString(fl.Field().String())
  385. }
  386. // IsUUID4 is the validation function for validating if the field's value is a valid v4 UUID.
  387. func isUUID4(fl FieldLevel) bool {
  388. return uUID4Regex.MatchString(fl.Field().String())
  389. }
  390. // IsUUID3 is the validation function for validating if the field's value is a valid v3 UUID.
  391. func isUUID3(fl FieldLevel) bool {
  392. return uUID3Regex.MatchString(fl.Field().String())
  393. }
  394. // IsUUID is the validation function for validating if the field's value is a valid UUID of any version.
  395. func isUUID(fl FieldLevel) bool {
  396. return uUIDRegex.MatchString(fl.Field().String())
  397. }
  398. // IsUUID5RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v5 UUID.
  399. func isUUID5RFC4122(fl FieldLevel) bool {
  400. return uUID5RFC4122Regex.MatchString(fl.Field().String())
  401. }
  402. // IsUUID4RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v4 UUID.
  403. func isUUID4RFC4122(fl FieldLevel) bool {
  404. return uUID4RFC4122Regex.MatchString(fl.Field().String())
  405. }
  406. // IsUUID3RFC4122 is the validation function for validating if the field's value is a valid RFC4122 v3 UUID.
  407. func isUUID3RFC4122(fl FieldLevel) bool {
  408. return uUID3RFC4122Regex.MatchString(fl.Field().String())
  409. }
  410. // IsUUIDRFC4122 is the validation function for validating if the field's value is a valid RFC4122 UUID of any version.
  411. func isUUIDRFC4122(fl FieldLevel) bool {
  412. return uUIDRFC4122Regex.MatchString(fl.Field().String())
  413. }
  414. // IsISBN is the validation function for validating if the field's value is a valid v10 or v13 ISBN.
  415. func isISBN(fl FieldLevel) bool {
  416. return isISBN10(fl) || isISBN13(fl)
  417. }
  418. // IsISBN13 is the validation function for validating if the field's value is a valid v13 ISBN.
  419. func isISBN13(fl FieldLevel) bool {
  420. s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 4), " ", "", 4)
  421. if !iSBN13Regex.MatchString(s) {
  422. return false
  423. }
  424. var checksum int32
  425. var i int32
  426. factor := []int32{1, 3}
  427. for i = 0; i < 12; i++ {
  428. checksum += factor[i%2] * int32(s[i]-'0')
  429. }
  430. return (int32(s[12]-'0'))-((10-(checksum%10))%10) == 0
  431. }
  432. // IsISBN10 is the validation function for validating if the field's value is a valid v10 ISBN.
  433. func isISBN10(fl FieldLevel) bool {
  434. s := strings.Replace(strings.Replace(fl.Field().String(), "-", "", 3), " ", "", 3)
  435. if !iSBN10Regex.MatchString(s) {
  436. return false
  437. }
  438. var checksum int32
  439. var i int32
  440. for i = 0; i < 9; i++ {
  441. checksum += (i + 1) * int32(s[i]-'0')
  442. }
  443. if s[9] == 'X' {
  444. checksum += 10 * 10
  445. } else {
  446. checksum += 10 * int32(s[9]-'0')
  447. }
  448. return checksum%11 == 0
  449. }
  450. // IsEthereumAddress is the validation function for validating if the field's value is a valid Ethereum address.
  451. func isEthereumAddress(fl FieldLevel) bool {
  452. address := fl.Field().String()
  453. if !ethAddressRegex.MatchString(address) {
  454. return false
  455. }
  456. if ethaddressRegexUpper.MatchString(address) || ethAddressRegexLower.MatchString(address) {
  457. return true
  458. }
  459. // Checksum validation. Reference: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-55.md
  460. address = address[2:] // Skip "0x" prefix.
  461. h := sha3.NewLegacyKeccak256()
  462. // hash.Hash's io.Writer implementation says it never returns an error. https://golang.org/pkg/hash/#Hash
  463. _, _ = h.Write([]byte(strings.ToLower(address)))
  464. hash := hex.EncodeToString(h.Sum(nil))
  465. for i := 0; i < len(address); i++ {
  466. if address[i] <= '9' { // Skip 0-9 digits: they don't have upper/lower-case.
  467. continue
  468. }
  469. if hash[i] > '7' && address[i] >= 'a' || hash[i] <= '7' && address[i] <= 'F' {
  470. return false
  471. }
  472. }
  473. return true
  474. }
  475. // IsBitcoinAddress is the validation function for validating if the field's value is a valid btc address
  476. func isBitcoinAddress(fl FieldLevel) bool {
  477. address := fl.Field().String()
  478. if !btcAddressRegex.MatchString(address) {
  479. return false
  480. }
  481. alphabet := []byte("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz")
  482. decode := [25]byte{}
  483. for _, n := range []byte(address) {
  484. d := bytes.IndexByte(alphabet, n)
  485. for i := 24; i >= 0; i-- {
  486. d += 58 * int(decode[i])
  487. decode[i] = byte(d % 256)
  488. d /= 256
  489. }
  490. }
  491. h := sha256.New()
  492. _, _ = h.Write(decode[:21])
  493. d := h.Sum([]byte{})
  494. h = sha256.New()
  495. _, _ = h.Write(d)
  496. validchecksum := [4]byte{}
  497. computedchecksum := [4]byte{}
  498. copy(computedchecksum[:], h.Sum(d[:0]))
  499. copy(validchecksum[:], decode[21:])
  500. return validchecksum == computedchecksum
  501. }
  502. // IsBitcoinBech32Address is the validation function for validating if the field's value is a valid bech32 btc address
  503. func isBitcoinBech32Address(fl FieldLevel) bool {
  504. address := fl.Field().String()
  505. if !btcLowerAddressRegexBech32.MatchString(address) && !btcUpperAddressRegexBech32.MatchString(address) {
  506. return false
  507. }
  508. am := len(address) % 8
  509. if am == 0 || am == 3 || am == 5 {
  510. return false
  511. }
  512. address = strings.ToLower(address)
  513. alphabet := "qpzry9x8gf2tvdw0s3jn54khce6mua7l"
  514. hr := []int{3, 3, 0, 2, 3} // the human readable part will always be bc
  515. addr := address[3:]
  516. dp := make([]int, 0, len(addr))
  517. for _, c := range addr {
  518. dp = append(dp, strings.IndexRune(alphabet, c))
  519. }
  520. ver := dp[0]
  521. if ver < 0 || ver > 16 {
  522. return false
  523. }
  524. if ver == 0 {
  525. if len(address) != 42 && len(address) != 62 {
  526. return false
  527. }
  528. }
  529. values := append(hr, dp...)
  530. GEN := []int{0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3}
  531. p := 1
  532. for _, v := range values {
  533. b := p >> 25
  534. p = (p&0x1ffffff)<<5 ^ v
  535. for i := 0; i < 5; i++ {
  536. if (b>>uint(i))&1 == 1 {
  537. p ^= GEN[i]
  538. }
  539. }
  540. }
  541. if p != 1 {
  542. return false
  543. }
  544. b := uint(0)
  545. acc := 0
  546. mv := (1 << 5) - 1
  547. var sw []int
  548. for _, v := range dp[1 : len(dp)-6] {
  549. acc = (acc << 5) | v
  550. b += 5
  551. for b >= 8 {
  552. b -= 8
  553. sw = append(sw, (acc>>b)&mv)
  554. }
  555. }
  556. if len(sw) < 2 || len(sw) > 40 {
  557. return false
  558. }
  559. return true
  560. }
  561. // ExcludesRune is the validation function for validating that the field's value does not contain the rune specified within the param.
  562. func excludesRune(fl FieldLevel) bool {
  563. return !containsRune(fl)
  564. }
  565. // ExcludesAll is the validation function for validating that the field's value does not contain any of the characters specified within the param.
  566. func excludesAll(fl FieldLevel) bool {
  567. return !containsAny(fl)
  568. }
  569. // Excludes is the validation function for validating that the field's value does not contain the text specified within the param.
  570. func excludes(fl FieldLevel) bool {
  571. return !contains(fl)
  572. }
  573. // ContainsRune is the validation function for validating that the field's value contains the rune specified within the param.
  574. func containsRune(fl FieldLevel) bool {
  575. r, _ := utf8.DecodeRuneInString(fl.Param())
  576. return strings.ContainsRune(fl.Field().String(), r)
  577. }
  578. // ContainsAny is the validation function for validating that the field's value contains any of the characters specified within the param.
  579. func containsAny(fl FieldLevel) bool {
  580. return strings.ContainsAny(fl.Field().String(), fl.Param())
  581. }
  582. // Contains is the validation function for validating that the field's value contains the text specified within the param.
  583. func contains(fl FieldLevel) bool {
  584. return strings.Contains(fl.Field().String(), fl.Param())
  585. }
  586. // StartsWith is the validation function for validating that the field's value starts with the text specified within the param.
  587. func startsWith(fl FieldLevel) bool {
  588. return strings.HasPrefix(fl.Field().String(), fl.Param())
  589. }
  590. // EndsWith is the validation function for validating that the field's value ends with the text specified within the param.
  591. func endsWith(fl FieldLevel) bool {
  592. return strings.HasSuffix(fl.Field().String(), fl.Param())
  593. }
  594. // StartsNotWith is the validation function for validating that the field's value does not start with the text specified within the param.
  595. func startsNotWith(fl FieldLevel) bool {
  596. return !startsWith(fl)
  597. }
  598. // EndsNotWith is the validation function for validating that the field's value does not end with the text specified within the param.
  599. func endsNotWith(fl FieldLevel) bool {
  600. return !endsWith(fl)
  601. }
  602. // FieldContains is the validation function for validating if the current field's value contains the field specified by the param's value.
  603. func fieldContains(fl FieldLevel) bool {
  604. field := fl.Field()
  605. currentField, _, ok := fl.GetStructFieldOK()
  606. if !ok {
  607. return false
  608. }
  609. return strings.Contains(field.String(), currentField.String())
  610. }
  611. // FieldExcludes is the validation function for validating if the current field's value excludes the field specified by the param's value.
  612. func fieldExcludes(fl FieldLevel) bool {
  613. field := fl.Field()
  614. currentField, _, ok := fl.GetStructFieldOK()
  615. if !ok {
  616. return true
  617. }
  618. return !strings.Contains(field.String(), currentField.String())
  619. }
  620. // IsNeField is the validation function for validating if the current field's value is not equal to the field specified by the param's value.
  621. func isNeField(fl FieldLevel) bool {
  622. field := fl.Field()
  623. kind := field.Kind()
  624. currentField, currentKind, ok := fl.GetStructFieldOK()
  625. if !ok || currentKind != kind {
  626. return true
  627. }
  628. switch kind {
  629. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  630. return field.Int() != currentField.Int()
  631. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  632. return field.Uint() != currentField.Uint()
  633. case reflect.Float32, reflect.Float64:
  634. return field.Float() != currentField.Float()
  635. case reflect.Slice, reflect.Map, reflect.Array:
  636. return int64(field.Len()) != int64(currentField.Len())
  637. case reflect.Struct:
  638. fieldType := field.Type()
  639. // Not Same underlying type i.e. struct and time
  640. if fieldType != currentField.Type() {
  641. return true
  642. }
  643. if fieldType == timeType {
  644. t := currentField.Interface().(time.Time)
  645. fieldTime := field.Interface().(time.Time)
  646. return !fieldTime.Equal(t)
  647. }
  648. }
  649. // default reflect.String:
  650. return field.String() != currentField.String()
  651. }
  652. // IsNe is the validation function for validating that the field's value does not equal the provided param value.
  653. func isNe(fl FieldLevel) bool {
  654. return !isEq(fl)
  655. }
  656. // IsLteCrossStructField is the validation function for validating if the current field's value is less than or equal to the field, within a separate struct, specified by the param's value.
  657. func isLteCrossStructField(fl FieldLevel) bool {
  658. field := fl.Field()
  659. kind := field.Kind()
  660. topField, topKind, ok := fl.GetStructFieldOK()
  661. if !ok || topKind != kind {
  662. return false
  663. }
  664. switch kind {
  665. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  666. return field.Int() <= topField.Int()
  667. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  668. return field.Uint() <= topField.Uint()
  669. case reflect.Float32, reflect.Float64:
  670. return field.Float() <= topField.Float()
  671. case reflect.Slice, reflect.Map, reflect.Array:
  672. return int64(field.Len()) <= int64(topField.Len())
  673. case reflect.Struct:
  674. fieldType := field.Type()
  675. // Not Same underlying type i.e. struct and time
  676. if fieldType != topField.Type() {
  677. return false
  678. }
  679. if fieldType == timeType {
  680. fieldTime := field.Interface().(time.Time)
  681. topTime := topField.Interface().(time.Time)
  682. return fieldTime.Before(topTime) || fieldTime.Equal(topTime)
  683. }
  684. }
  685. // default reflect.String:
  686. return field.String() <= topField.String()
  687. }
  688. // IsLtCrossStructField is the validation function for validating if the current field's value is less than the field, within a separate struct, specified by the param's value.
  689. // NOTE: This is exposed for use within your own custom functions and not intended to be called directly.
  690. func isLtCrossStructField(fl FieldLevel) bool {
  691. field := fl.Field()
  692. kind := field.Kind()
  693. topField, topKind, ok := fl.GetStructFieldOK()
  694. if !ok || topKind != kind {
  695. return false
  696. }
  697. switch kind {
  698. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  699. return field.Int() < topField.Int()
  700. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  701. return field.Uint() < topField.Uint()
  702. case reflect.Float32, reflect.Float64:
  703. return field.Float() < topField.Float()
  704. case reflect.Slice, reflect.Map, reflect.Array:
  705. return int64(field.Len()) < int64(topField.Len())
  706. case reflect.Struct:
  707. fieldType := field.Type()
  708. // Not Same underlying type i.e. struct and time
  709. if fieldType != topField.Type() {
  710. return false
  711. }
  712. if fieldType == timeType {
  713. fieldTime := field.Interface().(time.Time)
  714. topTime := topField.Interface().(time.Time)
  715. return fieldTime.Before(topTime)
  716. }
  717. }
  718. // default reflect.String:
  719. return field.String() < topField.String()
  720. }
  721. // IsGteCrossStructField is the validation function for validating if the current field's value is greater than or equal to the field, within a separate struct, specified by the param's value.
  722. func isGteCrossStructField(fl FieldLevel) bool {
  723. field := fl.Field()
  724. kind := field.Kind()
  725. topField, topKind, ok := fl.GetStructFieldOK()
  726. if !ok || topKind != kind {
  727. return false
  728. }
  729. switch kind {
  730. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  731. return field.Int() >= topField.Int()
  732. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  733. return field.Uint() >= topField.Uint()
  734. case reflect.Float32, reflect.Float64:
  735. return field.Float() >= topField.Float()
  736. case reflect.Slice, reflect.Map, reflect.Array:
  737. return int64(field.Len()) >= int64(topField.Len())
  738. case reflect.Struct:
  739. fieldType := field.Type()
  740. // Not Same underlying type i.e. struct and time
  741. if fieldType != topField.Type() {
  742. return false
  743. }
  744. if fieldType == timeType {
  745. fieldTime := field.Interface().(time.Time)
  746. topTime := topField.Interface().(time.Time)
  747. return fieldTime.After(topTime) || fieldTime.Equal(topTime)
  748. }
  749. }
  750. // default reflect.String:
  751. return field.String() >= topField.String()
  752. }
  753. // IsGtCrossStructField is the validation function for validating if the current field's value is greater than the field, within a separate struct, specified by the param's value.
  754. func isGtCrossStructField(fl FieldLevel) bool {
  755. field := fl.Field()
  756. kind := field.Kind()
  757. topField, topKind, ok := fl.GetStructFieldOK()
  758. if !ok || topKind != kind {
  759. return false
  760. }
  761. switch kind {
  762. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  763. return field.Int() > topField.Int()
  764. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  765. return field.Uint() > topField.Uint()
  766. case reflect.Float32, reflect.Float64:
  767. return field.Float() > topField.Float()
  768. case reflect.Slice, reflect.Map, reflect.Array:
  769. return int64(field.Len()) > int64(topField.Len())
  770. case reflect.Struct:
  771. fieldType := field.Type()
  772. // Not Same underlying type i.e. struct and time
  773. if fieldType != topField.Type() {
  774. return false
  775. }
  776. if fieldType == timeType {
  777. fieldTime := field.Interface().(time.Time)
  778. topTime := topField.Interface().(time.Time)
  779. return fieldTime.After(topTime)
  780. }
  781. }
  782. // default reflect.String:
  783. return field.String() > topField.String()
  784. }
  785. // IsNeCrossStructField is the validation function for validating that the current field's value is not equal to the field, within a separate struct, specified by the param's value.
  786. func isNeCrossStructField(fl FieldLevel) bool {
  787. field := fl.Field()
  788. kind := field.Kind()
  789. topField, currentKind, ok := fl.GetStructFieldOK()
  790. if !ok || currentKind != kind {
  791. return true
  792. }
  793. switch kind {
  794. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  795. return topField.Int() != field.Int()
  796. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  797. return topField.Uint() != field.Uint()
  798. case reflect.Float32, reflect.Float64:
  799. return topField.Float() != field.Float()
  800. case reflect.Slice, reflect.Map, reflect.Array:
  801. return int64(topField.Len()) != int64(field.Len())
  802. case reflect.Struct:
  803. fieldType := field.Type()
  804. // Not Same underlying type i.e. struct and time
  805. if fieldType != topField.Type() {
  806. return true
  807. }
  808. if fieldType == timeType {
  809. t := field.Interface().(time.Time)
  810. fieldTime := topField.Interface().(time.Time)
  811. return !fieldTime.Equal(t)
  812. }
  813. }
  814. // default reflect.String:
  815. return topField.String() != field.String()
  816. }
  817. // IsEqCrossStructField is the validation function for validating that the current field's value is equal to the field, within a separate struct, specified by the param's value.
  818. func isEqCrossStructField(fl FieldLevel) bool {
  819. field := fl.Field()
  820. kind := field.Kind()
  821. topField, topKind, ok := fl.GetStructFieldOK()
  822. if !ok || topKind != kind {
  823. return false
  824. }
  825. switch kind {
  826. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  827. return topField.Int() == field.Int()
  828. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  829. return topField.Uint() == field.Uint()
  830. case reflect.Float32, reflect.Float64:
  831. return topField.Float() == field.Float()
  832. case reflect.Slice, reflect.Map, reflect.Array:
  833. return int64(topField.Len()) == int64(field.Len())
  834. case reflect.Struct:
  835. fieldType := field.Type()
  836. // Not Same underlying type i.e. struct and time
  837. if fieldType != topField.Type() {
  838. return false
  839. }
  840. if fieldType == timeType {
  841. t := field.Interface().(time.Time)
  842. fieldTime := topField.Interface().(time.Time)
  843. return fieldTime.Equal(t)
  844. }
  845. }
  846. // default reflect.String:
  847. return topField.String() == field.String()
  848. }
  849. // IsEqField is the validation function for validating if the current field's value is equal to the field specified by the param's value.
  850. func isEqField(fl FieldLevel) bool {
  851. field := fl.Field()
  852. kind := field.Kind()
  853. currentField, currentKind, ok := fl.GetStructFieldOK()
  854. if !ok || currentKind != kind {
  855. return false
  856. }
  857. switch kind {
  858. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  859. return field.Int() == currentField.Int()
  860. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  861. return field.Uint() == currentField.Uint()
  862. case reflect.Float32, reflect.Float64:
  863. return field.Float() == currentField.Float()
  864. case reflect.Slice, reflect.Map, reflect.Array:
  865. return int64(field.Len()) == int64(currentField.Len())
  866. case reflect.Struct:
  867. fieldType := field.Type()
  868. // Not Same underlying type i.e. struct and time
  869. if fieldType != currentField.Type() {
  870. return false
  871. }
  872. if fieldType == timeType {
  873. t := currentField.Interface().(time.Time)
  874. fieldTime := field.Interface().(time.Time)
  875. return fieldTime.Equal(t)
  876. }
  877. }
  878. // default reflect.String:
  879. return field.String() == currentField.String()
  880. }
  881. // IsEq is the validation function for validating if the current field's value is equal to the param's value.
  882. func isEq(fl FieldLevel) bool {
  883. field := fl.Field()
  884. param := fl.Param()
  885. switch field.Kind() {
  886. case reflect.String:
  887. return field.String() == param
  888. case reflect.Slice, reflect.Map, reflect.Array:
  889. p := asInt(param)
  890. return int64(field.Len()) == p
  891. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  892. p := asIntFromType(field.Type(), param)
  893. return field.Int() == p
  894. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  895. p := asUint(param)
  896. return field.Uint() == p
  897. case reflect.Float32, reflect.Float64:
  898. p := asFloat(param)
  899. return field.Float() == p
  900. case reflect.Bool:
  901. p := asBool(param)
  902. return field.Bool() == p
  903. }
  904. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  905. }
  906. // IsBase64 is the validation function for validating if the current field's value is a valid base 64.
  907. func isBase64(fl FieldLevel) bool {
  908. return base64Regex.MatchString(fl.Field().String())
  909. }
  910. // IsBase64URL is the validation function for validating if the current field's value is a valid base64 URL safe string.
  911. func isBase64URL(fl FieldLevel) bool {
  912. return base64URLRegex.MatchString(fl.Field().String())
  913. }
  914. // IsURI is the validation function for validating if the current field's value is a valid URI.
  915. func isURI(fl FieldLevel) bool {
  916. field := fl.Field()
  917. switch field.Kind() {
  918. case reflect.String:
  919. s := field.String()
  920. // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
  921. // emulate browser and strip the '#' suffix prior to validation. see issue-#237
  922. if i := strings.Index(s, "#"); i > -1 {
  923. s = s[:i]
  924. }
  925. if len(s) == 0 {
  926. return false
  927. }
  928. _, err := url.ParseRequestURI(s)
  929. return err == nil
  930. }
  931. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  932. }
  933. // IsURL is the validation function for validating if the current field's value is a valid URL.
  934. func isURL(fl FieldLevel) bool {
  935. field := fl.Field()
  936. switch field.Kind() {
  937. case reflect.String:
  938. var i int
  939. s := field.String()
  940. // checks needed as of Go 1.6 because of change https://github.com/golang/go/commit/617c93ce740c3c3cc28cdd1a0d712be183d0b328#diff-6c2d018290e298803c0c9419d8739885L195
  941. // emulate browser and strip the '#' suffix prior to validation. see issue-#237
  942. if i = strings.Index(s, "#"); i > -1 {
  943. s = s[:i]
  944. }
  945. if len(s) == 0 {
  946. return false
  947. }
  948. url, err := url.ParseRequestURI(s)
  949. if err != nil || url.Scheme == "" {
  950. return false
  951. }
  952. return true
  953. }
  954. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  955. }
  956. // isUrnRFC2141 is the validation function for validating if the current field's value is a valid URN as per RFC 2141.
  957. func isUrnRFC2141(fl FieldLevel) bool {
  958. field := fl.Field()
  959. switch field.Kind() {
  960. case reflect.String:
  961. str := field.String()
  962. _, match := urn.Parse([]byte(str))
  963. return match
  964. }
  965. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  966. }
  967. // IsFile is the validation function for validating if the current field's value is a valid file path.
  968. func isFile(fl FieldLevel) bool {
  969. field := fl.Field()
  970. switch field.Kind() {
  971. case reflect.String:
  972. fileInfo, err := os.Stat(field.String())
  973. if err != nil {
  974. return false
  975. }
  976. return !fileInfo.IsDir()
  977. }
  978. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  979. }
  980. // IsE164 is the validation function for validating if the current field's value is a valid e.164 formatted phone number.
  981. func isE164(fl FieldLevel) bool {
  982. return e164Regex.MatchString(fl.Field().String())
  983. }
  984. // IsEmail is the validation function for validating if the current field's value is a valid email address.
  985. func isEmail(fl FieldLevel) bool {
  986. return emailRegex.MatchString(fl.Field().String())
  987. }
  988. // IsHSLA is the validation function for validating if the current field's value is a valid HSLA color.
  989. func isHSLA(fl FieldLevel) bool {
  990. return hslaRegex.MatchString(fl.Field().String())
  991. }
  992. // IsHSL is the validation function for validating if the current field's value is a valid HSL color.
  993. func isHSL(fl FieldLevel) bool {
  994. return hslRegex.MatchString(fl.Field().String())
  995. }
  996. // IsRGBA is the validation function for validating if the current field's value is a valid RGBA color.
  997. func isRGBA(fl FieldLevel) bool {
  998. return rgbaRegex.MatchString(fl.Field().String())
  999. }
  1000. // IsRGB is the validation function for validating if the current field's value is a valid RGB color.
  1001. func isRGB(fl FieldLevel) bool {
  1002. return rgbRegex.MatchString(fl.Field().String())
  1003. }
  1004. // IsHEXColor is the validation function for validating if the current field's value is a valid HEX color.
  1005. func isHEXColor(fl FieldLevel) bool {
  1006. return hexcolorRegex.MatchString(fl.Field().String())
  1007. }
  1008. // IsHexadecimal is the validation function for validating if the current field's value is a valid hexadecimal.
  1009. func isHexadecimal(fl FieldLevel) bool {
  1010. return hexadecimalRegex.MatchString(fl.Field().String())
  1011. }
  1012. // IsNumber is the validation function for validating if the current field's value is a valid number.
  1013. func isNumber(fl FieldLevel) bool {
  1014. switch fl.Field().Kind() {
  1015. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
  1016. return true
  1017. default:
  1018. return numberRegex.MatchString(fl.Field().String())
  1019. }
  1020. }
  1021. // IsNumeric is the validation function for validating if the current field's value is a valid numeric value.
  1022. func isNumeric(fl FieldLevel) bool {
  1023. switch fl.Field().Kind() {
  1024. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr, reflect.Float32, reflect.Float64:
  1025. return true
  1026. default:
  1027. return numericRegex.MatchString(fl.Field().String())
  1028. }
  1029. }
  1030. // IsAlphanum is the validation function for validating if the current field's value is a valid alphanumeric value.
  1031. func isAlphanum(fl FieldLevel) bool {
  1032. return alphaNumericRegex.MatchString(fl.Field().String())
  1033. }
  1034. // IsAlpha is the validation function for validating if the current field's value is a valid alpha value.
  1035. func isAlpha(fl FieldLevel) bool {
  1036. return alphaRegex.MatchString(fl.Field().String())
  1037. }
  1038. // IsAlphanumUnicode is the validation function for validating if the current field's value is a valid alphanumeric unicode value.
  1039. func isAlphanumUnicode(fl FieldLevel) bool {
  1040. return alphaUnicodeNumericRegex.MatchString(fl.Field().String())
  1041. }
  1042. // IsAlphaUnicode is the validation function for validating if the current field's value is a valid alpha unicode value.
  1043. func isAlphaUnicode(fl FieldLevel) bool {
  1044. return alphaUnicodeRegex.MatchString(fl.Field().String())
  1045. }
  1046. // isDefault is the opposite of required aka hasValue
  1047. func isDefault(fl FieldLevel) bool {
  1048. return !hasValue(fl)
  1049. }
  1050. // HasValue is the validation function for validating if the current field's value is not the default static value.
  1051. func hasValue(fl FieldLevel) bool {
  1052. field := fl.Field()
  1053. switch field.Kind() {
  1054. case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
  1055. return !field.IsNil()
  1056. default:
  1057. if fl.(*validate).fldIsPointer && field.Interface() != nil {
  1058. return true
  1059. }
  1060. return field.IsValid() && field.Interface() != reflect.Zero(field.Type()).Interface()
  1061. }
  1062. }
  1063. // requireCheckField is a func for check field kind
  1064. func requireCheckFieldKind(fl FieldLevel, param string, defaultNotFoundValue bool) bool {
  1065. field := fl.Field()
  1066. kind := field.Kind()
  1067. var nullable, found bool
  1068. if len(param) > 0 {
  1069. field, kind, nullable, found = fl.GetStructFieldOKAdvanced2(fl.Parent(), param)
  1070. if !found {
  1071. return defaultNotFoundValue
  1072. }
  1073. }
  1074. switch kind {
  1075. case reflect.Invalid:
  1076. return defaultNotFoundValue
  1077. case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Interface, reflect.Chan, reflect.Func:
  1078. return field.IsNil()
  1079. default:
  1080. if nullable && field.Interface() != nil {
  1081. return false
  1082. }
  1083. return field.IsValid() && field.Interface() == reflect.Zero(field.Type()).Interface()
  1084. }
  1085. }
  1086. // requireCheckFieldValue is a func for check field value
  1087. func requireCheckFieldValue(fl FieldLevel, param string, value string, defaultNotFoundValue bool) bool {
  1088. field, kind, _, found := fl.GetStructFieldOKAdvanced2(fl.Parent(), param)
  1089. if !found {
  1090. return defaultNotFoundValue
  1091. }
  1092. switch kind {
  1093. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1094. return field.Int() == asInt(value)
  1095. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1096. return field.Uint() == asUint(value)
  1097. case reflect.Float32, reflect.Float64:
  1098. return field.Float() == asFloat(value)
  1099. case reflect.Slice, reflect.Map, reflect.Array:
  1100. return int64(field.Len()) == asInt(value)
  1101. }
  1102. // default reflect.String:
  1103. return field.String() == value
  1104. }
  1105. // requiredIf is the validation function
  1106. // The field under validation must be present and not empty only if all the other specified fields are equal to the value following with the specified field.
  1107. func requiredIf(fl FieldLevel) bool {
  1108. params := parseOneOfParam2(fl.Param())
  1109. if len(params)%2 != 0 {
  1110. panic(fmt.Sprintf("Bad param number for required_if %s", fl.FieldName()))
  1111. }
  1112. for i := 0; i < len(params); i += 2 {
  1113. if !requireCheckFieldValue(fl, params[i], params[i+1], false) {
  1114. return true
  1115. }
  1116. }
  1117. return hasValue(fl)
  1118. }
  1119. // requiredUnless is the validation function
  1120. // The field under validation must be present and not empty only unless all the other specified fields are equal to the value following with the specified field.
  1121. func requiredUnless(fl FieldLevel) bool {
  1122. params := parseOneOfParam2(fl.Param())
  1123. if len(params)%2 != 0 {
  1124. panic(fmt.Sprintf("Bad param number for required_unless %s", fl.FieldName()))
  1125. }
  1126. for i := 0; i < len(params); i += 2 {
  1127. if requireCheckFieldValue(fl, params[i], params[i+1], false) {
  1128. return true
  1129. }
  1130. }
  1131. return hasValue(fl)
  1132. }
  1133. // ExcludedWith is the validation function
  1134. // The field under validation must not be present or is empty if any of the other specified fields are present.
  1135. func excludedWith(fl FieldLevel) bool {
  1136. params := parseOneOfParam2(fl.Param())
  1137. for _, param := range params {
  1138. if !requireCheckFieldKind(fl, param, true) {
  1139. return !hasValue(fl)
  1140. }
  1141. }
  1142. return true
  1143. }
  1144. // RequiredWith is the validation function
  1145. // The field under validation must be present and not empty only if any of the other specified fields are present.
  1146. func requiredWith(fl FieldLevel) bool {
  1147. params := parseOneOfParam2(fl.Param())
  1148. for _, param := range params {
  1149. if !requireCheckFieldKind(fl, param, true) {
  1150. return hasValue(fl)
  1151. }
  1152. }
  1153. return true
  1154. }
  1155. // ExcludedWithAll is the validation function
  1156. // The field under validation must not be present or is empty if all of the other specified fields are present.
  1157. func excludedWithAll(fl FieldLevel) bool {
  1158. params := parseOneOfParam2(fl.Param())
  1159. for _, param := range params {
  1160. if requireCheckFieldKind(fl, param, true) {
  1161. return true
  1162. }
  1163. }
  1164. return !hasValue(fl)
  1165. }
  1166. // RequiredWithAll is the validation function
  1167. // The field under validation must be present and not empty only if all of the other specified fields are present.
  1168. func requiredWithAll(fl FieldLevel) bool {
  1169. params := parseOneOfParam2(fl.Param())
  1170. for _, param := range params {
  1171. if requireCheckFieldKind(fl, param, true) {
  1172. return true
  1173. }
  1174. }
  1175. return hasValue(fl)
  1176. }
  1177. // ExcludedWithout is the validation function
  1178. // The field under validation must not be present or is empty when any of the other specified fields are not present.
  1179. func excludedWithout(fl FieldLevel) bool {
  1180. if requireCheckFieldKind(fl, strings.TrimSpace(fl.Param()), true) {
  1181. return !hasValue(fl)
  1182. }
  1183. return true
  1184. }
  1185. // RequiredWithout is the validation function
  1186. // The field under validation must be present and not empty only when any of the other specified fields are not present.
  1187. func requiredWithout(fl FieldLevel) bool {
  1188. if requireCheckFieldKind(fl, strings.TrimSpace(fl.Param()), true) {
  1189. return hasValue(fl)
  1190. }
  1191. return true
  1192. }
  1193. // RequiredWithoutAll is the validation function
  1194. // The field under validation must not be present or is empty when all of the other specified fields are not present.
  1195. func excludedWithoutAll(fl FieldLevel) bool {
  1196. params := parseOneOfParam2(fl.Param())
  1197. for _, param := range params {
  1198. if !requireCheckFieldKind(fl, param, true) {
  1199. return true
  1200. }
  1201. }
  1202. return !hasValue(fl)
  1203. }
  1204. // RequiredWithoutAll is the validation function
  1205. // The field under validation must be present and not empty only when all of the other specified fields are not present.
  1206. func requiredWithoutAll(fl FieldLevel) bool {
  1207. params := parseOneOfParam2(fl.Param())
  1208. for _, param := range params {
  1209. if !requireCheckFieldKind(fl, param, true) {
  1210. return true
  1211. }
  1212. }
  1213. return hasValue(fl)
  1214. }
  1215. // IsGteField is the validation function for validating if the current field's value is greater than or equal to the field specified by the param's value.
  1216. func isGteField(fl FieldLevel) bool {
  1217. field := fl.Field()
  1218. kind := field.Kind()
  1219. currentField, currentKind, ok := fl.GetStructFieldOK()
  1220. if !ok || currentKind != kind {
  1221. return false
  1222. }
  1223. switch kind {
  1224. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1225. return field.Int() >= currentField.Int()
  1226. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1227. return field.Uint() >= currentField.Uint()
  1228. case reflect.Float32, reflect.Float64:
  1229. return field.Float() >= currentField.Float()
  1230. case reflect.Struct:
  1231. fieldType := field.Type()
  1232. // Not Same underlying type i.e. struct and time
  1233. if fieldType != currentField.Type() {
  1234. return false
  1235. }
  1236. if fieldType == timeType {
  1237. t := currentField.Interface().(time.Time)
  1238. fieldTime := field.Interface().(time.Time)
  1239. return fieldTime.After(t) || fieldTime.Equal(t)
  1240. }
  1241. }
  1242. // default reflect.String
  1243. return len(field.String()) >= len(currentField.String())
  1244. }
  1245. // IsGtField is the validation function for validating if the current field's value is greater than the field specified by the param's value.
  1246. func isGtField(fl FieldLevel) bool {
  1247. field := fl.Field()
  1248. kind := field.Kind()
  1249. currentField, currentKind, ok := fl.GetStructFieldOK()
  1250. if !ok || currentKind != kind {
  1251. return false
  1252. }
  1253. switch kind {
  1254. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1255. return field.Int() > currentField.Int()
  1256. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1257. return field.Uint() > currentField.Uint()
  1258. case reflect.Float32, reflect.Float64:
  1259. return field.Float() > currentField.Float()
  1260. case reflect.Struct:
  1261. fieldType := field.Type()
  1262. // Not Same underlying type i.e. struct and time
  1263. if fieldType != currentField.Type() {
  1264. return false
  1265. }
  1266. if fieldType == timeType {
  1267. t := currentField.Interface().(time.Time)
  1268. fieldTime := field.Interface().(time.Time)
  1269. return fieldTime.After(t)
  1270. }
  1271. }
  1272. // default reflect.String
  1273. return len(field.String()) > len(currentField.String())
  1274. }
  1275. // IsGte is the validation function for validating if the current field's value is greater than or equal to the param's value.
  1276. func isGte(fl FieldLevel) bool {
  1277. field := fl.Field()
  1278. param := fl.Param()
  1279. switch field.Kind() {
  1280. case reflect.String:
  1281. p := asInt(param)
  1282. return int64(utf8.RuneCountInString(field.String())) >= p
  1283. case reflect.Slice, reflect.Map, reflect.Array:
  1284. p := asInt(param)
  1285. return int64(field.Len()) >= p
  1286. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1287. p := asIntFromType(field.Type(), param)
  1288. return field.Int() >= p
  1289. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1290. p := asUint(param)
  1291. return field.Uint() >= p
  1292. case reflect.Float32, reflect.Float64:
  1293. p := asFloat(param)
  1294. return field.Float() >= p
  1295. case reflect.Struct:
  1296. if field.Type() == timeType {
  1297. now := time.Now().UTC()
  1298. t := field.Interface().(time.Time)
  1299. return t.After(now) || t.Equal(now)
  1300. }
  1301. }
  1302. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1303. }
  1304. // IsGt is the validation function for validating if the current field's value is greater than the param's value.
  1305. func isGt(fl FieldLevel) bool {
  1306. field := fl.Field()
  1307. param := fl.Param()
  1308. switch field.Kind() {
  1309. case reflect.String:
  1310. p := asInt(param)
  1311. return int64(utf8.RuneCountInString(field.String())) > p
  1312. case reflect.Slice, reflect.Map, reflect.Array:
  1313. p := asInt(param)
  1314. return int64(field.Len()) > p
  1315. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1316. p := asIntFromType(field.Type(), param)
  1317. return field.Int() > p
  1318. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1319. p := asUint(param)
  1320. return field.Uint() > p
  1321. case reflect.Float32, reflect.Float64:
  1322. p := asFloat(param)
  1323. return field.Float() > p
  1324. case reflect.Struct:
  1325. if field.Type() == timeType {
  1326. return field.Interface().(time.Time).After(time.Now().UTC())
  1327. }
  1328. }
  1329. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1330. }
  1331. // HasLengthOf is the validation function for validating if the current field's value is equal to the param's value.
  1332. func hasLengthOf(fl FieldLevel) bool {
  1333. field := fl.Field()
  1334. param := fl.Param()
  1335. switch field.Kind() {
  1336. case reflect.String:
  1337. p := asInt(param)
  1338. return int64(utf8.RuneCountInString(field.String())) == p
  1339. case reflect.Slice, reflect.Map, reflect.Array:
  1340. p := asInt(param)
  1341. return int64(field.Len()) == p
  1342. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1343. p := asIntFromType(field.Type(), param)
  1344. return field.Int() == p
  1345. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1346. p := asUint(param)
  1347. return field.Uint() == p
  1348. case reflect.Float32, reflect.Float64:
  1349. p := asFloat(param)
  1350. return field.Float() == p
  1351. }
  1352. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1353. }
  1354. // HasMinOf is the validation function for validating if the current field's value is greater than or equal to the param's value.
  1355. func hasMinOf(fl FieldLevel) bool {
  1356. return isGte(fl)
  1357. }
  1358. // IsLteField is the validation function for validating if the current field's value is less than or equal to the field specified by the param's value.
  1359. func isLteField(fl FieldLevel) bool {
  1360. field := fl.Field()
  1361. kind := field.Kind()
  1362. currentField, currentKind, ok := fl.GetStructFieldOK()
  1363. if !ok || currentKind != kind {
  1364. return false
  1365. }
  1366. switch kind {
  1367. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1368. return field.Int() <= currentField.Int()
  1369. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1370. return field.Uint() <= currentField.Uint()
  1371. case reflect.Float32, reflect.Float64:
  1372. return field.Float() <= currentField.Float()
  1373. case reflect.Struct:
  1374. fieldType := field.Type()
  1375. // Not Same underlying type i.e. struct and time
  1376. if fieldType != currentField.Type() {
  1377. return false
  1378. }
  1379. if fieldType == timeType {
  1380. t := currentField.Interface().(time.Time)
  1381. fieldTime := field.Interface().(time.Time)
  1382. return fieldTime.Before(t) || fieldTime.Equal(t)
  1383. }
  1384. }
  1385. // default reflect.String
  1386. return len(field.String()) <= len(currentField.String())
  1387. }
  1388. // IsLtField is the validation function for validating if the current field's value is less than the field specified by the param's value.
  1389. func isLtField(fl FieldLevel) bool {
  1390. field := fl.Field()
  1391. kind := field.Kind()
  1392. currentField, currentKind, ok := fl.GetStructFieldOK()
  1393. if !ok || currentKind != kind {
  1394. return false
  1395. }
  1396. switch kind {
  1397. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1398. return field.Int() < currentField.Int()
  1399. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1400. return field.Uint() < currentField.Uint()
  1401. case reflect.Float32, reflect.Float64:
  1402. return field.Float() < currentField.Float()
  1403. case reflect.Struct:
  1404. fieldType := field.Type()
  1405. // Not Same underlying type i.e. struct and time
  1406. if fieldType != currentField.Type() {
  1407. return false
  1408. }
  1409. if fieldType == timeType {
  1410. t := currentField.Interface().(time.Time)
  1411. fieldTime := field.Interface().(time.Time)
  1412. return fieldTime.Before(t)
  1413. }
  1414. }
  1415. // default reflect.String
  1416. return len(field.String()) < len(currentField.String())
  1417. }
  1418. // IsLte is the validation function for validating if the current field's value is less than or equal to the param's value.
  1419. func isLte(fl FieldLevel) bool {
  1420. field := fl.Field()
  1421. param := fl.Param()
  1422. switch field.Kind() {
  1423. case reflect.String:
  1424. p := asInt(param)
  1425. return int64(utf8.RuneCountInString(field.String())) <= p
  1426. case reflect.Slice, reflect.Map, reflect.Array:
  1427. p := asInt(param)
  1428. return int64(field.Len()) <= p
  1429. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1430. p := asIntFromType(field.Type(), param)
  1431. return field.Int() <= p
  1432. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1433. p := asUint(param)
  1434. return field.Uint() <= p
  1435. case reflect.Float32, reflect.Float64:
  1436. p := asFloat(param)
  1437. return field.Float() <= p
  1438. case reflect.Struct:
  1439. if field.Type() == timeType {
  1440. now := time.Now().UTC()
  1441. t := field.Interface().(time.Time)
  1442. return t.Before(now) || t.Equal(now)
  1443. }
  1444. }
  1445. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1446. }
  1447. // IsLt is the validation function for validating if the current field's value is less than the param's value.
  1448. func isLt(fl FieldLevel) bool {
  1449. field := fl.Field()
  1450. param := fl.Param()
  1451. switch field.Kind() {
  1452. case reflect.String:
  1453. p := asInt(param)
  1454. return int64(utf8.RuneCountInString(field.String())) < p
  1455. case reflect.Slice, reflect.Map, reflect.Array:
  1456. p := asInt(param)
  1457. return int64(field.Len()) < p
  1458. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1459. p := asIntFromType(field.Type(), param)
  1460. return field.Int() < p
  1461. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1462. p := asUint(param)
  1463. return field.Uint() < p
  1464. case reflect.Float32, reflect.Float64:
  1465. p := asFloat(param)
  1466. return field.Float() < p
  1467. case reflect.Struct:
  1468. if field.Type() == timeType {
  1469. return field.Interface().(time.Time).Before(time.Now().UTC())
  1470. }
  1471. }
  1472. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1473. }
  1474. // HasMaxOf is the validation function for validating if the current field's value is less than or equal to the param's value.
  1475. func hasMaxOf(fl FieldLevel) bool {
  1476. return isLte(fl)
  1477. }
  1478. // IsTCP4AddrResolvable is the validation function for validating if the field's value is a resolvable tcp4 address.
  1479. func isTCP4AddrResolvable(fl FieldLevel) bool {
  1480. if !isIP4Addr(fl) {
  1481. return false
  1482. }
  1483. _, err := net.ResolveTCPAddr("tcp4", fl.Field().String())
  1484. return err == nil
  1485. }
  1486. // IsTCP6AddrResolvable is the validation function for validating if the field's value is a resolvable tcp6 address.
  1487. func isTCP6AddrResolvable(fl FieldLevel) bool {
  1488. if !isIP6Addr(fl) {
  1489. return false
  1490. }
  1491. _, err := net.ResolveTCPAddr("tcp6", fl.Field().String())
  1492. return err == nil
  1493. }
  1494. // IsTCPAddrResolvable is the validation function for validating if the field's value is a resolvable tcp address.
  1495. func isTCPAddrResolvable(fl FieldLevel) bool {
  1496. if !isIP4Addr(fl) && !isIP6Addr(fl) {
  1497. return false
  1498. }
  1499. _, err := net.ResolveTCPAddr("tcp", fl.Field().String())
  1500. return err == nil
  1501. }
  1502. // IsUDP4AddrResolvable is the validation function for validating if the field's value is a resolvable udp4 address.
  1503. func isUDP4AddrResolvable(fl FieldLevel) bool {
  1504. if !isIP4Addr(fl) {
  1505. return false
  1506. }
  1507. _, err := net.ResolveUDPAddr("udp4", fl.Field().String())
  1508. return err == nil
  1509. }
  1510. // IsUDP6AddrResolvable is the validation function for validating if the field's value is a resolvable udp6 address.
  1511. func isUDP6AddrResolvable(fl FieldLevel) bool {
  1512. if !isIP6Addr(fl) {
  1513. return false
  1514. }
  1515. _, err := net.ResolveUDPAddr("udp6", fl.Field().String())
  1516. return err == nil
  1517. }
  1518. // IsUDPAddrResolvable is the validation function for validating if the field's value is a resolvable udp address.
  1519. func isUDPAddrResolvable(fl FieldLevel) bool {
  1520. if !isIP4Addr(fl) && !isIP6Addr(fl) {
  1521. return false
  1522. }
  1523. _, err := net.ResolveUDPAddr("udp", fl.Field().String())
  1524. return err == nil
  1525. }
  1526. // IsIP4AddrResolvable is the validation function for validating if the field's value is a resolvable ip4 address.
  1527. func isIP4AddrResolvable(fl FieldLevel) bool {
  1528. if !isIPv4(fl) {
  1529. return false
  1530. }
  1531. _, err := net.ResolveIPAddr("ip4", fl.Field().String())
  1532. return err == nil
  1533. }
  1534. // IsIP6AddrResolvable is the validation function for validating if the field's value is a resolvable ip6 address.
  1535. func isIP6AddrResolvable(fl FieldLevel) bool {
  1536. if !isIPv6(fl) {
  1537. return false
  1538. }
  1539. _, err := net.ResolveIPAddr("ip6", fl.Field().String())
  1540. return err == nil
  1541. }
  1542. // IsIPAddrResolvable is the validation function for validating if the field's value is a resolvable ip address.
  1543. func isIPAddrResolvable(fl FieldLevel) bool {
  1544. if !isIP(fl) {
  1545. return false
  1546. }
  1547. _, err := net.ResolveIPAddr("ip", fl.Field().String())
  1548. return err == nil
  1549. }
  1550. // IsUnixAddrResolvable is the validation function for validating if the field's value is a resolvable unix address.
  1551. func isUnixAddrResolvable(fl FieldLevel) bool {
  1552. _, err := net.ResolveUnixAddr("unix", fl.Field().String())
  1553. return err == nil
  1554. }
  1555. func isIP4Addr(fl FieldLevel) bool {
  1556. val := fl.Field().String()
  1557. if idx := strings.LastIndex(val, ":"); idx != -1 {
  1558. val = val[0:idx]
  1559. }
  1560. ip := net.ParseIP(val)
  1561. return ip != nil && ip.To4() != nil
  1562. }
  1563. func isIP6Addr(fl FieldLevel) bool {
  1564. val := fl.Field().String()
  1565. if idx := strings.LastIndex(val, ":"); idx != -1 {
  1566. if idx != 0 && val[idx-1:idx] == "]" {
  1567. val = val[1 : idx-1]
  1568. }
  1569. }
  1570. ip := net.ParseIP(val)
  1571. return ip != nil && ip.To4() == nil
  1572. }
  1573. func isHostnameRFC952(fl FieldLevel) bool {
  1574. return hostnameRegexRFC952.MatchString(fl.Field().String())
  1575. }
  1576. func isHostnameRFC1123(fl FieldLevel) bool {
  1577. return hostnameRegexRFC1123.MatchString(fl.Field().String())
  1578. }
  1579. func isFQDN(fl FieldLevel) bool {
  1580. val := fl.Field().String()
  1581. if val == "" {
  1582. return false
  1583. }
  1584. return fqdnRegexRFC1123.MatchString(val)
  1585. }
  1586. // IsDir is the validation function for validating if the current field's value is a valid directory.
  1587. func isDir(fl FieldLevel) bool {
  1588. field := fl.Field()
  1589. if field.Kind() == reflect.String {
  1590. fileInfo, err := os.Stat(field.String())
  1591. if err != nil {
  1592. return false
  1593. }
  1594. return fileInfo.IsDir()
  1595. }
  1596. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1597. }
  1598. // isJSON is the validation function for validating if the current field's value is a valid json string.
  1599. func isJSON(fl FieldLevel) bool {
  1600. field := fl.Field()
  1601. if field.Kind() == reflect.String {
  1602. val := field.String()
  1603. return json.Valid([]byte(val))
  1604. }
  1605. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1606. }
  1607. // isHostnamePort validates a <dns>:<port> combination for fields typically used for socket address.
  1608. func isHostnamePort(fl FieldLevel) bool {
  1609. val := fl.Field().String()
  1610. host, port, err := net.SplitHostPort(val)
  1611. if err != nil {
  1612. return false
  1613. }
  1614. // Port must be a iny <= 65535.
  1615. if portNum, err := strconv.ParseInt(port, 10, 32); err != nil || portNum > 65535 || portNum < 1 {
  1616. return false
  1617. }
  1618. // If host is specified, it should match a DNS name
  1619. if host != "" {
  1620. return hostnameRegexRFC1123.MatchString(host)
  1621. }
  1622. return true
  1623. }
  1624. // isLowercase is the validation function for validating if the current field's value is a lowercase string.
  1625. func isLowercase(fl FieldLevel) bool {
  1626. field := fl.Field()
  1627. if field.Kind() == reflect.String {
  1628. if field.String() == "" {
  1629. return false
  1630. }
  1631. return field.String() == strings.ToLower(field.String())
  1632. }
  1633. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1634. }
  1635. // isUppercase is the validation function for validating if the current field's value is an uppercase string.
  1636. func isUppercase(fl FieldLevel) bool {
  1637. field := fl.Field()
  1638. if field.Kind() == reflect.String {
  1639. if field.String() == "" {
  1640. return false
  1641. }
  1642. return field.String() == strings.ToUpper(field.String())
  1643. }
  1644. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1645. }
  1646. // isDatetime is the validation function for validating if the current field's value is a valid datetime string.
  1647. func isDatetime(fl FieldLevel) bool {
  1648. field := fl.Field()
  1649. param := fl.Param()
  1650. if field.Kind() == reflect.String {
  1651. _, err := time.Parse(param, field.String())
  1652. return err == nil
  1653. }
  1654. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1655. }
  1656. // isTimeZone is the validation function for validating if the current field's value is a valid time zone string.
  1657. func isTimeZone(fl FieldLevel) bool {
  1658. field := fl.Field()
  1659. if field.Kind() == reflect.String {
  1660. // empty value is converted to UTC by time.LoadLocation but disallow it as it is not a valid time zone name
  1661. if field.String() == "" {
  1662. return false
  1663. }
  1664. // Local value is converted to the current system time zone by time.LoadLocation but disallow it as it is not a valid time zone name
  1665. if strings.ToLower(field.String()) == "local" {
  1666. return false
  1667. }
  1668. _, err := time.LoadLocation(field.String())
  1669. return err == nil
  1670. }
  1671. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1672. }
  1673. // isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-2 country code.
  1674. func isIso3166Alpha2(fl FieldLevel) bool {
  1675. val := fl.Field().String()
  1676. return iso3166_1_alpha2[val]
  1677. }
  1678. // isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-3 country code.
  1679. func isIso3166Alpha3(fl FieldLevel) bool {
  1680. val := fl.Field().String()
  1681. return iso3166_1_alpha3[val]
  1682. }
  1683. // isIso3166Alpha2 is the validation function for validating if the current field's value is a valid iso3166-1 alpha-numeric country code.
  1684. func isIso3166AlphaNumeric(fl FieldLevel) bool {
  1685. field := fl.Field()
  1686. var code int
  1687. switch field.Kind() {
  1688. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1689. code = int(field.Int() % 1000)
  1690. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
  1691. code = int(field.Uint() % 1000)
  1692. default:
  1693. panic(fmt.Sprintf("Bad field type %T", field.Interface()))
  1694. }
  1695. return iso3166_1_alpha_numeric[code]
  1696. }