validator.go 44 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622
  1. // Package govalidator is package of validators and sanitizers for strings, structs and collections.
  2. package govalidator
  3. import (
  4. "bytes"
  5. "crypto/rsa"
  6. "crypto/x509"
  7. "encoding/base64"
  8. "encoding/json"
  9. "encoding/pem"
  10. "fmt"
  11. "io/ioutil"
  12. "net"
  13. "net/url"
  14. "reflect"
  15. "regexp"
  16. "sort"
  17. "strconv"
  18. "strings"
  19. "time"
  20. "unicode"
  21. "unicode/utf8"
  22. )
  23. var (
  24. fieldsRequiredByDefault bool
  25. nilPtrAllowedByRequired = false
  26. notNumberRegexp = regexp.MustCompile("[^0-9]+")
  27. whiteSpacesAndMinus = regexp.MustCompile(`[\s-]+`)
  28. paramsRegexp = regexp.MustCompile(`\(.*\)$`)
  29. )
  30. const maxURLRuneCount = 2083
  31. const minURLRuneCount = 3
  32. const rfc3339WithoutZone = "2006-01-02T15:04:05"
  33. // SetFieldsRequiredByDefault causes validation to fail when struct fields
  34. // do not include validations or are not explicitly marked as exempt (using `valid:"-"` or `valid:"email,optional"`).
  35. // This struct definition will fail govalidator.ValidateStruct() (and the field values do not matter):
  36. // type exampleStruct struct {
  37. // Name string ``
  38. // Email string `valid:"email"`
  39. // This, however, will only fail when Email is empty or an invalid email address:
  40. // type exampleStruct2 struct {
  41. // Name string `valid:"-"`
  42. // Email string `valid:"email"`
  43. // Lastly, this will only fail when Email is an invalid email address but not when it's empty:
  44. // type exampleStruct2 struct {
  45. // Name string `valid:"-"`
  46. // Email string `valid:"email,optional"`
  47. func SetFieldsRequiredByDefault(value bool) {
  48. fieldsRequiredByDefault = value
  49. }
  50. // SetNilPtrAllowedByRequired causes validation to pass for nil ptrs when a field is set to required.
  51. // The validation will still reject ptr fields in their zero value state. Example with this enabled:
  52. // type exampleStruct struct {
  53. // Name *string `valid:"required"`
  54. // With `Name` set to "", this will be considered invalid input and will cause a validation error.
  55. // With `Name` set to nil, this will be considered valid by validation.
  56. // By default this is disabled.
  57. func SetNilPtrAllowedByRequired(value bool) {
  58. nilPtrAllowedByRequired = value
  59. }
  60. // IsEmail checks if the string is an email.
  61. func IsEmail(str string) bool {
  62. // TODO uppercase letters are not supported
  63. return rxEmail.MatchString(str)
  64. }
  65. // IsExistingEmail checks if the string is an email of existing domain
  66. func IsExistingEmail(email string) bool {
  67. if len(email) < 6 || len(email) > 254 {
  68. return false
  69. }
  70. at := strings.LastIndex(email, "@")
  71. if at <= 0 || at > len(email)-3 {
  72. return false
  73. }
  74. user := email[:at]
  75. host := email[at+1:]
  76. if len(user) > 64 {
  77. return false
  78. }
  79. switch host {
  80. case "localhost", "example.com":
  81. return true
  82. }
  83. if userDotRegexp.MatchString(user) || !userRegexp.MatchString(user) || !hostRegexp.MatchString(host) {
  84. return false
  85. }
  86. if _, err := net.LookupMX(host); err != nil {
  87. if _, err := net.LookupIP(host); err != nil {
  88. return false
  89. }
  90. }
  91. return true
  92. }
  93. // IsURL checks if the string is an URL.
  94. func IsURL(str string) bool {
  95. if str == "" || utf8.RuneCountInString(str) >= maxURLRuneCount || len(str) <= minURLRuneCount || strings.HasPrefix(str, ".") {
  96. return false
  97. }
  98. strTemp := str
  99. if strings.Contains(str, ":") && !strings.Contains(str, "://") {
  100. // support no indicated urlscheme but with colon for port number
  101. // http:// is appended so url.Parse will succeed, strTemp used so it does not impact rxURL.MatchString
  102. strTemp = "http://" + str
  103. }
  104. u, err := url.Parse(strTemp)
  105. if err != nil {
  106. return false
  107. }
  108. if strings.HasPrefix(u.Host, ".") {
  109. return false
  110. }
  111. if u.Host == "" && (u.Path != "" && !strings.Contains(u.Path, ".")) {
  112. return false
  113. }
  114. return rxURL.MatchString(str)
  115. }
  116. // IsRequestURL checks if the string rawurl, assuming
  117. // it was received in an HTTP request, is a valid
  118. // URL confirm to RFC 3986
  119. func IsRequestURL(rawurl string) bool {
  120. url, err := url.ParseRequestURI(rawurl)
  121. if err != nil {
  122. return false //Couldn't even parse the rawurl
  123. }
  124. if len(url.Scheme) == 0 {
  125. return false //No Scheme found
  126. }
  127. return true
  128. }
  129. // IsRequestURI checks if the string rawurl, assuming
  130. // it was received in an HTTP request, is an
  131. // absolute URI or an absolute path.
  132. func IsRequestURI(rawurl string) bool {
  133. _, err := url.ParseRequestURI(rawurl)
  134. return err == nil
  135. }
  136. // IsAlpha checks if the string contains only letters (a-zA-Z). Empty string is valid.
  137. func IsAlpha(str string) bool {
  138. if IsNull(str) {
  139. return true
  140. }
  141. return rxAlpha.MatchString(str)
  142. }
  143. //IsUTFLetter checks if the string contains only unicode letter characters.
  144. //Similar to IsAlpha but for all languages. Empty string is valid.
  145. func IsUTFLetter(str string) bool {
  146. if IsNull(str) {
  147. return true
  148. }
  149. for _, c := range str {
  150. if !unicode.IsLetter(c) {
  151. return false
  152. }
  153. }
  154. return true
  155. }
  156. // IsAlphanumeric checks if the string contains only letters and numbers. Empty string is valid.
  157. func IsAlphanumeric(str string) bool {
  158. if IsNull(str) {
  159. return true
  160. }
  161. return rxAlphanumeric.MatchString(str)
  162. }
  163. // IsUTFLetterNumeric checks if the string contains only unicode letters and numbers. Empty string is valid.
  164. func IsUTFLetterNumeric(str string) bool {
  165. if IsNull(str) {
  166. return true
  167. }
  168. for _, c := range str {
  169. if !unicode.IsLetter(c) && !unicode.IsNumber(c) { //letters && numbers are ok
  170. return false
  171. }
  172. }
  173. return true
  174. }
  175. // IsNumeric checks if the string contains only numbers. Empty string is valid.
  176. func IsNumeric(str string) bool {
  177. if IsNull(str) {
  178. return true
  179. }
  180. return rxNumeric.MatchString(str)
  181. }
  182. // IsUTFNumeric checks if the string contains only unicode numbers of any kind.
  183. // Numbers can be 0-9 but also Fractions ¾,Roman Ⅸ and Hangzhou 〩. Empty string is valid.
  184. func IsUTFNumeric(str string) bool {
  185. if IsNull(str) {
  186. return true
  187. }
  188. if strings.IndexAny(str, "+-") > 0 {
  189. return false
  190. }
  191. if len(str) > 1 {
  192. str = strings.TrimPrefix(str, "-")
  193. str = strings.TrimPrefix(str, "+")
  194. }
  195. for _, c := range str {
  196. if !unicode.IsNumber(c) { //numbers && minus sign are ok
  197. return false
  198. }
  199. }
  200. return true
  201. }
  202. // IsUTFDigit checks if the string contains only unicode radix-10 decimal digits. Empty string is valid.
  203. func IsUTFDigit(str string) bool {
  204. if IsNull(str) {
  205. return true
  206. }
  207. if strings.IndexAny(str, "+-") > 0 {
  208. return false
  209. }
  210. if len(str) > 1 {
  211. str = strings.TrimPrefix(str, "-")
  212. str = strings.TrimPrefix(str, "+")
  213. }
  214. for _, c := range str {
  215. if !unicode.IsDigit(c) { //digits && minus sign are ok
  216. return false
  217. }
  218. }
  219. return true
  220. }
  221. // IsHexadecimal checks if the string is a hexadecimal number.
  222. func IsHexadecimal(str string) bool {
  223. return rxHexadecimal.MatchString(str)
  224. }
  225. // IsHexcolor checks if the string is a hexadecimal color.
  226. func IsHexcolor(str string) bool {
  227. return rxHexcolor.MatchString(str)
  228. }
  229. // IsRGBcolor checks if the string is a valid RGB color in form rgb(RRR, GGG, BBB).
  230. func IsRGBcolor(str string) bool {
  231. return rxRGBcolor.MatchString(str)
  232. }
  233. // IsLowerCase checks if the string is lowercase. Empty string is valid.
  234. func IsLowerCase(str string) bool {
  235. if IsNull(str) {
  236. return true
  237. }
  238. return str == strings.ToLower(str)
  239. }
  240. // IsUpperCase checks if the string is uppercase. Empty string is valid.
  241. func IsUpperCase(str string) bool {
  242. if IsNull(str) {
  243. return true
  244. }
  245. return str == strings.ToUpper(str)
  246. }
  247. // HasLowerCase checks if the string contains at least 1 lowercase. Empty string is valid.
  248. func HasLowerCase(str string) bool {
  249. if IsNull(str) {
  250. return true
  251. }
  252. return rxHasLowerCase.MatchString(str)
  253. }
  254. // HasUpperCase checks if the string contains as least 1 uppercase. Empty string is valid.
  255. func HasUpperCase(str string) bool {
  256. if IsNull(str) {
  257. return true
  258. }
  259. return rxHasUpperCase.MatchString(str)
  260. }
  261. // IsInt checks if the string is an integer. Empty string is valid.
  262. func IsInt(str string) bool {
  263. if IsNull(str) {
  264. return true
  265. }
  266. return rxInt.MatchString(str)
  267. }
  268. // IsFloat checks if the string is a float.
  269. func IsFloat(str string) bool {
  270. return str != "" && rxFloat.MatchString(str)
  271. }
  272. // IsDivisibleBy checks if the string is a number that's divisible by another.
  273. // If second argument is not valid integer or zero, it's return false.
  274. // Otherwise, if first argument is not valid integer or zero, it's return true (Invalid string converts to zero).
  275. func IsDivisibleBy(str, num string) bool {
  276. f, _ := ToFloat(str)
  277. p := int64(f)
  278. q, _ := ToInt(num)
  279. if q == 0 {
  280. return false
  281. }
  282. return (p == 0) || (p%q == 0)
  283. }
  284. // IsNull checks if the string is null.
  285. func IsNull(str string) bool {
  286. return len(str) == 0
  287. }
  288. // IsNotNull checks if the string is not null.
  289. func IsNotNull(str string) bool {
  290. return !IsNull(str)
  291. }
  292. // HasWhitespaceOnly checks the string only contains whitespace
  293. func HasWhitespaceOnly(str string) bool {
  294. return len(str) > 0 && rxHasWhitespaceOnly.MatchString(str)
  295. }
  296. // HasWhitespace checks if the string contains any whitespace
  297. func HasWhitespace(str string) bool {
  298. return len(str) > 0 && rxHasWhitespace.MatchString(str)
  299. }
  300. // IsByteLength checks if the string's length (in bytes) falls in a range.
  301. func IsByteLength(str string, min, max int) bool {
  302. return len(str) >= min && len(str) <= max
  303. }
  304. // IsUUIDv3 checks if the string is a UUID version 3.
  305. func IsUUIDv3(str string) bool {
  306. return rxUUID3.MatchString(str)
  307. }
  308. // IsUUIDv4 checks if the string is a UUID version 4.
  309. func IsUUIDv4(str string) bool {
  310. return rxUUID4.MatchString(str)
  311. }
  312. // IsUUIDv5 checks if the string is a UUID version 5.
  313. func IsUUIDv5(str string) bool {
  314. return rxUUID5.MatchString(str)
  315. }
  316. // IsUUID checks if the string is a UUID (version 3, 4 or 5).
  317. func IsUUID(str string) bool {
  318. return rxUUID.MatchString(str)
  319. }
  320. // IsCreditCard checks if the string is a credit card.
  321. func IsCreditCard(str string) bool {
  322. sanitized := notNumberRegexp.ReplaceAllString(str, "")
  323. if !rxCreditCard.MatchString(sanitized) {
  324. return false
  325. }
  326. var sum int64
  327. var digit string
  328. var tmpNum int64
  329. var shouldDouble bool
  330. for i := len(sanitized) - 1; i >= 0; i-- {
  331. digit = sanitized[i:(i + 1)]
  332. tmpNum, _ = ToInt(digit)
  333. if shouldDouble {
  334. tmpNum *= 2
  335. if tmpNum >= 10 {
  336. sum += (tmpNum % 10) + 1
  337. } else {
  338. sum += tmpNum
  339. }
  340. } else {
  341. sum += tmpNum
  342. }
  343. shouldDouble = !shouldDouble
  344. }
  345. return sum%10 == 0
  346. }
  347. // IsISBN10 checks if the string is an ISBN version 10.
  348. func IsISBN10(str string) bool {
  349. return IsISBN(str, 10)
  350. }
  351. // IsISBN13 checks if the string is an ISBN version 13.
  352. func IsISBN13(str string) bool {
  353. return IsISBN(str, 13)
  354. }
  355. // IsISBN checks if the string is an ISBN (version 10 or 13).
  356. // If version value is not equal to 10 or 13, it will be checks both variants.
  357. func IsISBN(str string, version int) bool {
  358. sanitized := whiteSpacesAndMinus.ReplaceAllString(str, "")
  359. var checksum int32
  360. var i int32
  361. if version == 10 {
  362. if !rxISBN10.MatchString(sanitized) {
  363. return false
  364. }
  365. for i = 0; i < 9; i++ {
  366. checksum += (i + 1) * int32(sanitized[i]-'0')
  367. }
  368. if sanitized[9] == 'X' {
  369. checksum += 10 * 10
  370. } else {
  371. checksum += 10 * int32(sanitized[9]-'0')
  372. }
  373. if checksum%11 == 0 {
  374. return true
  375. }
  376. return false
  377. } else if version == 13 {
  378. if !rxISBN13.MatchString(sanitized) {
  379. return false
  380. }
  381. factor := []int32{1, 3}
  382. for i = 0; i < 12; i++ {
  383. checksum += factor[i%2] * int32(sanitized[i]-'0')
  384. }
  385. return (int32(sanitized[12]-'0'))-((10-(checksum%10))%10) == 0
  386. }
  387. return IsISBN(str, 10) || IsISBN(str, 13)
  388. }
  389. // IsJSON checks if the string is valid JSON (note: uses json.Unmarshal).
  390. func IsJSON(str string) bool {
  391. var js json.RawMessage
  392. return json.Unmarshal([]byte(str), &js) == nil
  393. }
  394. // IsMultibyte checks if the string contains one or more multibyte chars. Empty string is valid.
  395. func IsMultibyte(str string) bool {
  396. if IsNull(str) {
  397. return true
  398. }
  399. return rxMultibyte.MatchString(str)
  400. }
  401. // IsASCII checks if the string contains ASCII chars only. Empty string is valid.
  402. func IsASCII(str string) bool {
  403. if IsNull(str) {
  404. return true
  405. }
  406. return rxASCII.MatchString(str)
  407. }
  408. // IsPrintableASCII checks if the string contains printable ASCII chars only. Empty string is valid.
  409. func IsPrintableASCII(str string) bool {
  410. if IsNull(str) {
  411. return true
  412. }
  413. return rxPrintableASCII.MatchString(str)
  414. }
  415. // IsFullWidth checks if the string contains any full-width chars. Empty string is valid.
  416. func IsFullWidth(str string) bool {
  417. if IsNull(str) {
  418. return true
  419. }
  420. return rxFullWidth.MatchString(str)
  421. }
  422. // IsHalfWidth checks if the string contains any half-width chars. Empty string is valid.
  423. func IsHalfWidth(str string) bool {
  424. if IsNull(str) {
  425. return true
  426. }
  427. return rxHalfWidth.MatchString(str)
  428. }
  429. // IsVariableWidth checks if the string contains a mixture of full and half-width chars. Empty string is valid.
  430. func IsVariableWidth(str string) bool {
  431. if IsNull(str) {
  432. return true
  433. }
  434. return rxHalfWidth.MatchString(str) && rxFullWidth.MatchString(str)
  435. }
  436. // IsBase64 checks if a string is base64 encoded.
  437. func IsBase64(str string) bool {
  438. return rxBase64.MatchString(str)
  439. }
  440. // IsFilePath checks is a string is Win or Unix file path and returns it's type.
  441. func IsFilePath(str string) (bool, int) {
  442. if rxWinPath.MatchString(str) {
  443. //check windows path limit see:
  444. // http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath
  445. if len(str[3:]) > 32767 {
  446. return false, Win
  447. }
  448. return true, Win
  449. } else if rxUnixPath.MatchString(str) {
  450. return true, Unix
  451. }
  452. return false, Unknown
  453. }
  454. // IsDataURI checks if a string is base64 encoded data URI such as an image
  455. func IsDataURI(str string) bool {
  456. dataURI := strings.Split(str, ",")
  457. if !rxDataURI.MatchString(dataURI[0]) {
  458. return false
  459. }
  460. return IsBase64(dataURI[1])
  461. }
  462. // IsMagnetURI checks if a string is valid magnet URI
  463. func IsMagnetURI(str string) bool {
  464. return rxMagnetURI.MatchString(str)
  465. }
  466. // IsISO3166Alpha2 checks if a string is valid two-letter country code
  467. func IsISO3166Alpha2(str string) bool {
  468. for _, entry := range ISO3166List {
  469. if str == entry.Alpha2Code {
  470. return true
  471. }
  472. }
  473. return false
  474. }
  475. // IsISO3166Alpha3 checks if a string is valid three-letter country code
  476. func IsISO3166Alpha3(str string) bool {
  477. for _, entry := range ISO3166List {
  478. if str == entry.Alpha3Code {
  479. return true
  480. }
  481. }
  482. return false
  483. }
  484. // IsISO693Alpha2 checks if a string is valid two-letter language code
  485. func IsISO693Alpha2(str string) bool {
  486. for _, entry := range ISO693List {
  487. if str == entry.Alpha2Code {
  488. return true
  489. }
  490. }
  491. return false
  492. }
  493. // IsISO693Alpha3b checks if a string is valid three-letter language code
  494. func IsISO693Alpha3b(str string) bool {
  495. for _, entry := range ISO693List {
  496. if str == entry.Alpha3bCode {
  497. return true
  498. }
  499. }
  500. return false
  501. }
  502. // IsDNSName will validate the given string as a DNS name
  503. func IsDNSName(str string) bool {
  504. if str == "" || len(strings.Replace(str, ".", "", -1)) > 255 {
  505. // constraints already violated
  506. return false
  507. }
  508. return !IsIP(str) && rxDNSName.MatchString(str)
  509. }
  510. // IsHash checks if a string is a hash of type algorithm.
  511. // Algorithm is one of ['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']
  512. func IsHash(str string, algorithm string) bool {
  513. var len string
  514. algo := strings.ToLower(algorithm)
  515. if algo == "crc32" || algo == "crc32b" {
  516. len = "8"
  517. } else if algo == "md5" || algo == "md4" || algo == "ripemd128" || algo == "tiger128" {
  518. len = "32"
  519. } else if algo == "sha1" || algo == "ripemd160" || algo == "tiger160" {
  520. len = "40"
  521. } else if algo == "tiger192" {
  522. len = "48"
  523. } else if algo == "sha256" {
  524. len = "64"
  525. } else if algo == "sha384" {
  526. len = "96"
  527. } else if algo == "sha512" {
  528. len = "128"
  529. } else {
  530. return false
  531. }
  532. return Matches(str, "^[a-f0-9]{"+len+"}$")
  533. }
  534. // IsSHA512 checks is a string is a SHA512 hash. Alias for `IsHash(str, "sha512")`
  535. func IsSHA512(str string) bool {
  536. return IsHash(str, "sha512")
  537. }
  538. // IsSHA384 checks is a string is a SHA384 hash. Alias for `IsHash(str, "sha384")`
  539. func IsSHA384(str string) bool {
  540. return IsHash(str, "sha384")
  541. }
  542. // IsSHA256 checks is a string is a SHA256 hash. Alias for `IsHash(str, "sha256")`
  543. func IsSHA256(str string) bool {
  544. return IsHash(str, "sha256")
  545. }
  546. // IsTiger192 checks is a string is a Tiger192 hash. Alias for `IsHash(str, "tiger192")`
  547. func IsTiger192(str string) bool {
  548. return IsHash(str, "tiger192")
  549. }
  550. // IsTiger160 checks is a string is a Tiger160 hash. Alias for `IsHash(str, "tiger160")`
  551. func IsTiger160(str string) bool {
  552. return IsHash(str, "tiger160")
  553. }
  554. // IsRipeMD160 checks is a string is a RipeMD160 hash. Alias for `IsHash(str, "ripemd160")`
  555. func IsRipeMD160(str string) bool {
  556. return IsHash(str, "ripemd160")
  557. }
  558. // IsSHA1 checks is a string is a SHA-1 hash. Alias for `IsHash(str, "sha1")`
  559. func IsSHA1(str string) bool {
  560. return IsHash(str, "sha1")
  561. }
  562. // IsTiger128 checks is a string is a Tiger128 hash. Alias for `IsHash(str, "tiger128")`
  563. func IsTiger128(str string) bool {
  564. return IsHash(str, "tiger128")
  565. }
  566. // IsRipeMD128 checks is a string is a RipeMD128 hash. Alias for `IsHash(str, "ripemd128")`
  567. func IsRipeMD128(str string) bool {
  568. return IsHash(str, "ripemd128")
  569. }
  570. // IsCRC32 checks is a string is a CRC32 hash. Alias for `IsHash(str, "crc32")`
  571. func IsCRC32(str string) bool {
  572. return IsHash(str, "crc32")
  573. }
  574. // IsCRC32b checks is a string is a CRC32b hash. Alias for `IsHash(str, "crc32b")`
  575. func IsCRC32b(str string) bool {
  576. return IsHash(str, "crc32b")
  577. }
  578. // IsMD5 checks is a string is a MD5 hash. Alias for `IsHash(str, "md5")`
  579. func IsMD5(str string) bool {
  580. return IsHash(str, "md5")
  581. }
  582. // IsMD4 checks is a string is a MD4 hash. Alias for `IsHash(str, "md4")`
  583. func IsMD4(str string) bool {
  584. return IsHash(str, "md4")
  585. }
  586. // IsDialString validates the given string for usage with the various Dial() functions
  587. func IsDialString(str string) bool {
  588. if h, p, err := net.SplitHostPort(str); err == nil && h != "" && p != "" && (IsDNSName(h) || IsIP(h)) && IsPort(p) {
  589. return true
  590. }
  591. return false
  592. }
  593. // IsIP checks if a string is either IP version 4 or 6. Alias for `net.ParseIP`
  594. func IsIP(str string) bool {
  595. return net.ParseIP(str) != nil
  596. }
  597. // IsPort checks if a string represents a valid port
  598. func IsPort(str string) bool {
  599. if i, err := strconv.Atoi(str); err == nil && i > 0 && i < 65536 {
  600. return true
  601. }
  602. return false
  603. }
  604. // IsIPv4 checks if the string is an IP version 4.
  605. func IsIPv4(str string) bool {
  606. ip := net.ParseIP(str)
  607. return ip != nil && strings.Contains(str, ".")
  608. }
  609. // IsIPv6 checks if the string is an IP version 6.
  610. func IsIPv6(str string) bool {
  611. ip := net.ParseIP(str)
  612. return ip != nil && strings.Contains(str, ":")
  613. }
  614. // IsCIDR checks if the string is an valid CIDR notiation (IPV4 & IPV6)
  615. func IsCIDR(str string) bool {
  616. _, _, err := net.ParseCIDR(str)
  617. return err == nil
  618. }
  619. // IsMAC checks if a string is valid MAC address.
  620. // Possible MAC formats:
  621. // 01:23:45:67:89:ab
  622. // 01:23:45:67:89:ab:cd:ef
  623. // 01-23-45-67-89-ab
  624. // 01-23-45-67-89-ab-cd-ef
  625. // 0123.4567.89ab
  626. // 0123.4567.89ab.cdef
  627. func IsMAC(str string) bool {
  628. _, err := net.ParseMAC(str)
  629. return err == nil
  630. }
  631. // IsHost checks if the string is a valid IP (both v4 and v6) or a valid DNS name
  632. func IsHost(str string) bool {
  633. return IsIP(str) || IsDNSName(str)
  634. }
  635. // IsMongoID checks if the string is a valid hex-encoded representation of a MongoDB ObjectId.
  636. func IsMongoID(str string) bool {
  637. return rxHexadecimal.MatchString(str) && (len(str) == 24)
  638. }
  639. // IsLatitude checks if a string is valid latitude.
  640. func IsLatitude(str string) bool {
  641. return rxLatitude.MatchString(str)
  642. }
  643. // IsLongitude checks if a string is valid longitude.
  644. func IsLongitude(str string) bool {
  645. return rxLongitude.MatchString(str)
  646. }
  647. // IsIMEI checks if a string is valid IMEI
  648. func IsIMEI(str string) bool {
  649. return rxIMEI.MatchString(str)
  650. }
  651. // IsIMSI checks if a string is valid IMSI
  652. func IsIMSI(str string) bool {
  653. if !rxIMSI.MatchString(str) {
  654. return false
  655. }
  656. mcc, err := strconv.ParseInt(str[0:3], 10, 32)
  657. if err != nil {
  658. return false
  659. }
  660. switch mcc {
  661. case 202, 204, 206, 208, 212, 213, 214, 216, 218, 219:
  662. case 220, 221, 222, 226, 228, 230, 231, 232, 234, 235:
  663. case 238, 240, 242, 244, 246, 247, 248, 250, 255, 257:
  664. case 259, 260, 262, 266, 268, 270, 272, 274, 276, 278:
  665. case 280, 282, 283, 284, 286, 288, 289, 290, 292, 293:
  666. case 294, 295, 297, 302, 308, 310, 311, 312, 313, 314:
  667. case 315, 316, 330, 332, 334, 338, 340, 342, 344, 346:
  668. case 348, 350, 352, 354, 356, 358, 360, 362, 363, 364:
  669. case 365, 366, 368, 370, 372, 374, 376, 400, 401, 402:
  670. case 404, 405, 406, 410, 412, 413, 414, 415, 416, 417:
  671. case 418, 419, 420, 421, 422, 424, 425, 426, 427, 428:
  672. case 429, 430, 431, 432, 434, 436, 437, 438, 440, 441:
  673. case 450, 452, 454, 455, 456, 457, 460, 461, 466, 467:
  674. case 470, 472, 502, 505, 510, 514, 515, 520, 525, 528:
  675. case 530, 536, 537, 539, 540, 541, 542, 543, 544, 545:
  676. case 546, 547, 548, 549, 550, 551, 552, 553, 554, 555:
  677. case 602, 603, 604, 605, 606, 607, 608, 609, 610, 611:
  678. case 612, 613, 614, 615, 616, 617, 618, 619, 620, 621:
  679. case 622, 623, 624, 625, 626, 627, 628, 629, 630, 631:
  680. case 632, 633, 634, 635, 636, 637, 638, 639, 640, 641:
  681. case 642, 643, 645, 646, 647, 648, 649, 650, 651, 652:
  682. case 653, 654, 655, 657, 658, 659, 702, 704, 706, 708:
  683. case 710, 712, 714, 716, 722, 724, 730, 732, 734, 736:
  684. case 738, 740, 742, 744, 746, 748, 750, 995:
  685. return true
  686. default:
  687. return false
  688. }
  689. return true
  690. }
  691. // IsRsaPublicKey checks if a string is valid public key with provided length
  692. func IsRsaPublicKey(str string, keylen int) bool {
  693. bb := bytes.NewBufferString(str)
  694. pemBytes, err := ioutil.ReadAll(bb)
  695. if err != nil {
  696. return false
  697. }
  698. block, _ := pem.Decode(pemBytes)
  699. if block != nil && block.Type != "PUBLIC KEY" {
  700. return false
  701. }
  702. var der []byte
  703. if block != nil {
  704. der = block.Bytes
  705. } else {
  706. der, err = base64.StdEncoding.DecodeString(str)
  707. if err != nil {
  708. return false
  709. }
  710. }
  711. key, err := x509.ParsePKIXPublicKey(der)
  712. if err != nil {
  713. return false
  714. }
  715. pubkey, ok := key.(*rsa.PublicKey)
  716. if !ok {
  717. return false
  718. }
  719. bitlen := len(pubkey.N.Bytes()) * 8
  720. return bitlen == int(keylen)
  721. }
  722. func toJSONName(tag string) string {
  723. if tag == "" {
  724. return ""
  725. }
  726. // JSON name always comes first. If there's no options then split[0] is
  727. // JSON name, if JSON name is not set, then split[0] is an empty string.
  728. split := strings.SplitN(tag, ",", 2)
  729. name := split[0]
  730. // However it is possible that the field is skipped when
  731. // (de-)serializing from/to JSON, in which case assume that there is no
  732. // tag name to use
  733. if name == "-" {
  734. return ""
  735. }
  736. return name
  737. }
  738. func prependPathToErrors(err error, path string) error {
  739. switch err2 := err.(type) {
  740. case Error:
  741. err2.Path = append([]string{path}, err2.Path...)
  742. return err2
  743. case Errors:
  744. errors := err2.Errors()
  745. for i, err3 := range errors {
  746. errors[i] = prependPathToErrors(err3, path)
  747. }
  748. return err2
  749. }
  750. return err
  751. }
  752. // ValidateMap use validation map for fields.
  753. // result will be equal to `false` if there are any errors.
  754. // s is the map containing the data to be validated.
  755. // m is the validation map in the form:
  756. // map[string]interface{}{"name":"required,alpha","address":map[string]interface{}{"line1":"required,alphanum"}}
  757. func ValidateMap(s map[string]interface{}, m map[string]interface{}) (bool, error) {
  758. if s == nil {
  759. return true, nil
  760. }
  761. result := true
  762. var err error
  763. var errs Errors
  764. var index int
  765. val := reflect.ValueOf(s)
  766. for key, value := range s {
  767. presentResult := true
  768. validator, ok := m[key]
  769. if !ok {
  770. presentResult = false
  771. var err error
  772. err = fmt.Errorf("all map keys has to be present in the validation map; got %s", key)
  773. err = prependPathToErrors(err, key)
  774. errs = append(errs, err)
  775. }
  776. valueField := reflect.ValueOf(value)
  777. mapResult := true
  778. typeResult := true
  779. structResult := true
  780. resultField := true
  781. switch subValidator := validator.(type) {
  782. case map[string]interface{}:
  783. var err error
  784. if v, ok := value.(map[string]interface{}); !ok {
  785. mapResult = false
  786. err = fmt.Errorf("map validator has to be for the map type only; got %s", valueField.Type().String())
  787. err = prependPathToErrors(err, key)
  788. errs = append(errs, err)
  789. } else {
  790. mapResult, err = ValidateMap(v, subValidator)
  791. if err != nil {
  792. mapResult = false
  793. err = prependPathToErrors(err, key)
  794. errs = append(errs, err)
  795. }
  796. }
  797. case string:
  798. if (valueField.Kind() == reflect.Struct ||
  799. (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
  800. subValidator != "-" {
  801. var err error
  802. structResult, err = ValidateStruct(valueField.Interface())
  803. if err != nil {
  804. err = prependPathToErrors(err, key)
  805. errs = append(errs, err)
  806. }
  807. }
  808. resultField, err = typeCheck(valueField, reflect.StructField{
  809. Name: key,
  810. PkgPath: "",
  811. Type: val.Type(),
  812. Tag: reflect.StructTag(fmt.Sprintf("%s:%q", tagName, subValidator)),
  813. Offset: 0,
  814. Index: []int{index},
  815. Anonymous: false,
  816. }, val, nil)
  817. if err != nil {
  818. errs = append(errs, err)
  819. }
  820. case nil:
  821. // already handlerd when checked before
  822. default:
  823. typeResult = false
  824. err = fmt.Errorf("map validator has to be either map[string]interface{} or string; got %s", valueField.Type().String())
  825. err = prependPathToErrors(err, key)
  826. errs = append(errs, err)
  827. }
  828. result = result && presentResult && typeResult && resultField && structResult && mapResult
  829. index++
  830. }
  831. // checks required keys
  832. requiredResult := true
  833. for key, value := range m {
  834. if schema, ok := value.(string); ok {
  835. tags := parseTagIntoMap(schema)
  836. if required, ok := tags["required"]; ok {
  837. if _, ok := s[key]; !ok {
  838. requiredResult = false
  839. if required.customErrorMessage != "" {
  840. err = Error{key, fmt.Errorf(required.customErrorMessage), true, "required", []string{}}
  841. } else {
  842. err = Error{key, fmt.Errorf("required field missing"), false, "required", []string{}}
  843. }
  844. errs = append(errs, err)
  845. }
  846. }
  847. }
  848. }
  849. if len(errs) > 0 {
  850. err = errs
  851. }
  852. return result && requiredResult, err
  853. }
  854. // ValidateStruct use tags for fields.
  855. // result will be equal to `false` if there are any errors.
  856. // todo currently there is no guarantee that errors will be returned in predictable order (tests may to fail)
  857. func ValidateStruct(s interface{}) (bool, error) {
  858. if s == nil {
  859. return true, nil
  860. }
  861. result := true
  862. var err error
  863. val := reflect.ValueOf(s)
  864. if val.Kind() == reflect.Interface || val.Kind() == reflect.Ptr {
  865. val = val.Elem()
  866. }
  867. // we only accept structs
  868. if val.Kind() != reflect.Struct {
  869. return false, fmt.Errorf("function only accepts structs; got %s", val.Kind())
  870. }
  871. var errs Errors
  872. for i := 0; i < val.NumField(); i++ {
  873. valueField := val.Field(i)
  874. typeField := val.Type().Field(i)
  875. if typeField.PkgPath != "" {
  876. continue // Private field
  877. }
  878. structResult := true
  879. if valueField.Kind() == reflect.Interface {
  880. valueField = valueField.Elem()
  881. }
  882. if (valueField.Kind() == reflect.Struct ||
  883. (valueField.Kind() == reflect.Ptr && valueField.Elem().Kind() == reflect.Struct)) &&
  884. typeField.Tag.Get(tagName) != "-" {
  885. var err error
  886. structResult, err = ValidateStruct(valueField.Interface())
  887. if err != nil {
  888. err = prependPathToErrors(err, typeField.Name)
  889. errs = append(errs, err)
  890. }
  891. }
  892. resultField, err2 := typeCheck(valueField, typeField, val, nil)
  893. if err2 != nil {
  894. // Replace structure name with JSON name if there is a tag on the variable
  895. jsonTag := toJSONName(typeField.Tag.Get("json"))
  896. if jsonTag != "" {
  897. switch jsonError := err2.(type) {
  898. case Error:
  899. jsonError.Name = jsonTag
  900. err2 = jsonError
  901. case Errors:
  902. for i2, err3 := range jsonError {
  903. switch customErr := err3.(type) {
  904. case Error:
  905. customErr.Name = jsonTag
  906. jsonError[i2] = customErr
  907. }
  908. }
  909. err2 = jsonError
  910. }
  911. }
  912. errs = append(errs, err2)
  913. }
  914. result = result && resultField && structResult
  915. }
  916. if len(errs) > 0 {
  917. err = errs
  918. }
  919. return result, err
  920. }
  921. // ValidateStructAsync performs async validation of the struct and returns results through the channels
  922. func ValidateStructAsync(s interface{}) (<-chan bool, <-chan error) {
  923. res := make(chan bool)
  924. errors := make(chan error)
  925. go func() {
  926. defer close(res)
  927. defer close(errors)
  928. isValid, isFailed := ValidateStruct(s)
  929. res <- isValid
  930. errors <- isFailed
  931. }()
  932. return res, errors
  933. }
  934. // ValidateMapAsync performs async validation of the map and returns results through the channels
  935. func ValidateMapAsync(s map[string]interface{}, m map[string]interface{}) (<-chan bool, <-chan error) {
  936. res := make(chan bool)
  937. errors := make(chan error)
  938. go func() {
  939. defer close(res)
  940. defer close(errors)
  941. isValid, isFailed := ValidateMap(s, m)
  942. res <- isValid
  943. errors <- isFailed
  944. }()
  945. return res, errors
  946. }
  947. // parseTagIntoMap parses a struct tag `valid:required~Some error message,length(2|3)` into map[string]string{"required": "Some error message", "length(2|3)": ""}
  948. func parseTagIntoMap(tag string) tagOptionsMap {
  949. optionsMap := make(tagOptionsMap)
  950. options := strings.Split(tag, ",")
  951. for i, option := range options {
  952. option = strings.TrimSpace(option)
  953. validationOptions := strings.Split(option, "~")
  954. if !isValidTag(validationOptions[0]) {
  955. continue
  956. }
  957. if len(validationOptions) == 2 {
  958. optionsMap[validationOptions[0]] = tagOption{validationOptions[0], validationOptions[1], i}
  959. } else {
  960. optionsMap[validationOptions[0]] = tagOption{validationOptions[0], "", i}
  961. }
  962. }
  963. return optionsMap
  964. }
  965. func isValidTag(s string) bool {
  966. if s == "" {
  967. return false
  968. }
  969. for _, c := range s {
  970. switch {
  971. case strings.ContainsRune("\\'\"!#$%&()*+-./:<=>?@[]^_{|}~ ", c):
  972. // Backslash and quote chars are reserved, but
  973. // otherwise any punctuation chars are allowed
  974. // in a tag name.
  975. default:
  976. if !unicode.IsLetter(c) && !unicode.IsDigit(c) {
  977. return false
  978. }
  979. }
  980. }
  981. return true
  982. }
  983. // IsSSN will validate the given string as a U.S. Social Security Number
  984. func IsSSN(str string) bool {
  985. if str == "" || len(str) != 11 {
  986. return false
  987. }
  988. return rxSSN.MatchString(str)
  989. }
  990. // IsSemver checks if string is valid semantic version
  991. func IsSemver(str string) bool {
  992. return rxSemver.MatchString(str)
  993. }
  994. // IsType checks if interface is of some type
  995. func IsType(v interface{}, params ...string) bool {
  996. if len(params) == 1 {
  997. typ := params[0]
  998. return strings.Replace(reflect.TypeOf(v).String(), " ", "", -1) == strings.Replace(typ, " ", "", -1)
  999. }
  1000. return false
  1001. }
  1002. // IsTime checks if string is valid according to given format
  1003. func IsTime(str string, format string) bool {
  1004. _, err := time.Parse(format, str)
  1005. return err == nil
  1006. }
  1007. // IsUnixTime checks if string is valid unix timestamp value
  1008. func IsUnixTime(str string) bool {
  1009. if _, err := strconv.Atoi(str); err == nil {
  1010. return true
  1011. }
  1012. return false
  1013. }
  1014. // IsRFC3339 checks if string is valid timestamp value according to RFC3339
  1015. func IsRFC3339(str string) bool {
  1016. return IsTime(str, time.RFC3339)
  1017. }
  1018. // IsRFC3339WithoutZone checks if string is valid timestamp value according to RFC3339 which excludes the timezone.
  1019. func IsRFC3339WithoutZone(str string) bool {
  1020. return IsTime(str, rfc3339WithoutZone)
  1021. }
  1022. // IsISO4217 checks if string is valid ISO currency code
  1023. func IsISO4217(str string) bool {
  1024. for _, currency := range ISO4217List {
  1025. if str == currency {
  1026. return true
  1027. }
  1028. }
  1029. return false
  1030. }
  1031. // ByteLength checks string's length
  1032. func ByteLength(str string, params ...string) bool {
  1033. if len(params) == 2 {
  1034. min, _ := ToInt(params[0])
  1035. max, _ := ToInt(params[1])
  1036. return len(str) >= int(min) && len(str) <= int(max)
  1037. }
  1038. return false
  1039. }
  1040. // RuneLength checks string's length
  1041. // Alias for StringLength
  1042. func RuneLength(str string, params ...string) bool {
  1043. return StringLength(str, params...)
  1044. }
  1045. // IsRsaPub checks whether string is valid RSA key
  1046. // Alias for IsRsaPublicKey
  1047. func IsRsaPub(str string, params ...string) bool {
  1048. if len(params) == 1 {
  1049. len, _ := ToInt(params[0])
  1050. return IsRsaPublicKey(str, int(len))
  1051. }
  1052. return false
  1053. }
  1054. // StringMatches checks if a string matches a given pattern.
  1055. func StringMatches(s string, params ...string) bool {
  1056. if len(params) == 1 {
  1057. pattern := params[0]
  1058. return Matches(s, pattern)
  1059. }
  1060. return false
  1061. }
  1062. // StringLength checks string's length (including multi byte strings)
  1063. func StringLength(str string, params ...string) bool {
  1064. if len(params) == 2 {
  1065. strLength := utf8.RuneCountInString(str)
  1066. min, _ := ToInt(params[0])
  1067. max, _ := ToInt(params[1])
  1068. return strLength >= int(min) && strLength <= int(max)
  1069. }
  1070. return false
  1071. }
  1072. // MinStringLength checks string's minimum length (including multi byte strings)
  1073. func MinStringLength(str string, params ...string) bool {
  1074. if len(params) == 1 {
  1075. strLength := utf8.RuneCountInString(str)
  1076. min, _ := ToInt(params[0])
  1077. return strLength >= int(min)
  1078. }
  1079. return false
  1080. }
  1081. // MaxStringLength checks string's maximum length (including multi byte strings)
  1082. func MaxStringLength(str string, params ...string) bool {
  1083. if len(params) == 1 {
  1084. strLength := utf8.RuneCountInString(str)
  1085. max, _ := ToInt(params[0])
  1086. return strLength <= int(max)
  1087. }
  1088. return false
  1089. }
  1090. // Range checks string's length
  1091. func Range(str string, params ...string) bool {
  1092. if len(params) == 2 {
  1093. value, _ := ToFloat(str)
  1094. min, _ := ToFloat(params[0])
  1095. max, _ := ToFloat(params[1])
  1096. return InRange(value, min, max)
  1097. }
  1098. return false
  1099. }
  1100. // IsInRaw checks if string is in list of allowed values
  1101. func IsInRaw(str string, params ...string) bool {
  1102. if len(params) == 1 {
  1103. rawParams := params[0]
  1104. parsedParams := strings.Split(rawParams, "|")
  1105. return IsIn(str, parsedParams...)
  1106. }
  1107. return false
  1108. }
  1109. // IsIn checks if string str is a member of the set of strings params
  1110. func IsIn(str string, params ...string) bool {
  1111. for _, param := range params {
  1112. if str == param {
  1113. return true
  1114. }
  1115. }
  1116. return false
  1117. }
  1118. func checkRequired(v reflect.Value, t reflect.StructField, options tagOptionsMap) (bool, error) {
  1119. if nilPtrAllowedByRequired {
  1120. k := v.Kind()
  1121. if (k == reflect.Ptr || k == reflect.Interface) && v.IsNil() {
  1122. return true, nil
  1123. }
  1124. }
  1125. if requiredOption, isRequired := options["required"]; isRequired {
  1126. if len(requiredOption.customErrorMessage) > 0 {
  1127. return false, Error{t.Name, fmt.Errorf(requiredOption.customErrorMessage), true, "required", []string{}}
  1128. }
  1129. return false, Error{t.Name, fmt.Errorf("non zero value required"), false, "required", []string{}}
  1130. } else if _, isOptional := options["optional"]; fieldsRequiredByDefault && !isOptional {
  1131. return false, Error{t.Name, fmt.Errorf("Missing required field"), false, "required", []string{}}
  1132. }
  1133. // not required and empty is valid
  1134. return true, nil
  1135. }
  1136. func typeCheck(v reflect.Value, t reflect.StructField, o reflect.Value, options tagOptionsMap) (isValid bool, resultErr error) {
  1137. if !v.IsValid() {
  1138. return false, nil
  1139. }
  1140. tag := t.Tag.Get(tagName)
  1141. // checks if the field should be ignored
  1142. switch tag {
  1143. case "":
  1144. if v.Kind() != reflect.Slice && v.Kind() != reflect.Map {
  1145. if !fieldsRequiredByDefault {
  1146. return true, nil
  1147. }
  1148. return false, Error{t.Name, fmt.Errorf("All fields are required to at least have one validation defined"), false, "required", []string{}}
  1149. }
  1150. case "-":
  1151. return true, nil
  1152. }
  1153. isRootType := false
  1154. if options == nil {
  1155. isRootType = true
  1156. options = parseTagIntoMap(tag)
  1157. }
  1158. if isEmptyValue(v) {
  1159. // an empty value is not validated, checks only required
  1160. isValid, resultErr = checkRequired(v, t, options)
  1161. for key := range options {
  1162. delete(options, key)
  1163. }
  1164. return isValid, resultErr
  1165. }
  1166. var customTypeErrors Errors
  1167. optionsOrder := options.orderedKeys()
  1168. for _, validatorName := range optionsOrder {
  1169. validatorStruct := options[validatorName]
  1170. if validatefunc, ok := CustomTypeTagMap.Get(validatorName); ok {
  1171. delete(options, validatorName)
  1172. if result := validatefunc(v.Interface(), o.Interface()); !result {
  1173. if len(validatorStruct.customErrorMessage) > 0 {
  1174. customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: TruncatingErrorf(validatorStruct.customErrorMessage, fmt.Sprint(v), validatorName), CustomErrorMessageExists: true, Validator: stripParams(validatorName)})
  1175. continue
  1176. }
  1177. customTypeErrors = append(customTypeErrors, Error{Name: t.Name, Err: fmt.Errorf("%s does not validate as %s", fmt.Sprint(v), validatorName), CustomErrorMessageExists: false, Validator: stripParams(validatorName)})
  1178. }
  1179. }
  1180. }
  1181. if len(customTypeErrors.Errors()) > 0 {
  1182. return false, customTypeErrors
  1183. }
  1184. if isRootType {
  1185. // Ensure that we've checked the value by all specified validators before report that the value is valid
  1186. defer func() {
  1187. delete(options, "optional")
  1188. delete(options, "required")
  1189. if isValid && resultErr == nil && len(options) != 0 {
  1190. optionsOrder := options.orderedKeys()
  1191. for _, validator := range optionsOrder {
  1192. isValid = false
  1193. resultErr = Error{t.Name, fmt.Errorf(
  1194. "The following validator is invalid or can't be applied to the field: %q", validator), false, stripParams(validator), []string{}}
  1195. return
  1196. }
  1197. }
  1198. }()
  1199. }
  1200. for _, validatorSpec := range optionsOrder {
  1201. validatorStruct := options[validatorSpec]
  1202. var negate bool
  1203. validator := validatorSpec
  1204. customMsgExists := len(validatorStruct.customErrorMessage) > 0
  1205. // checks whether the tag looks like '!something' or 'something'
  1206. if validator[0] == '!' {
  1207. validator = validator[1:]
  1208. negate = true
  1209. }
  1210. // checks for interface param validators
  1211. for key, value := range InterfaceParamTagRegexMap {
  1212. ps := value.FindStringSubmatch(validator)
  1213. if len(ps) == 0 {
  1214. continue
  1215. }
  1216. validatefunc, ok := InterfaceParamTagMap[key]
  1217. if !ok {
  1218. continue
  1219. }
  1220. delete(options, validatorSpec)
  1221. field := fmt.Sprint(v)
  1222. if result := validatefunc(v.Interface(), ps[1:]...); (!result && !negate) || (result && negate) {
  1223. if customMsgExists {
  1224. return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1225. }
  1226. if negate {
  1227. return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1228. }
  1229. return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1230. }
  1231. }
  1232. }
  1233. switch v.Kind() {
  1234. case reflect.Bool,
  1235. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  1236. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
  1237. reflect.Float32, reflect.Float64,
  1238. reflect.String:
  1239. // for each tag option checks the map of validator functions
  1240. for _, validatorSpec := range optionsOrder {
  1241. validatorStruct := options[validatorSpec]
  1242. var negate bool
  1243. validator := validatorSpec
  1244. customMsgExists := len(validatorStruct.customErrorMessage) > 0
  1245. // checks whether the tag looks like '!something' or 'something'
  1246. if validator[0] == '!' {
  1247. validator = validator[1:]
  1248. negate = true
  1249. }
  1250. // checks for param validators
  1251. for key, value := range ParamTagRegexMap {
  1252. ps := value.FindStringSubmatch(validator)
  1253. if len(ps) == 0 {
  1254. continue
  1255. }
  1256. validatefunc, ok := ParamTagMap[key]
  1257. if !ok {
  1258. continue
  1259. }
  1260. delete(options, validatorSpec)
  1261. switch v.Kind() {
  1262. case reflect.String,
  1263. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  1264. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  1265. reflect.Float32, reflect.Float64:
  1266. field := fmt.Sprint(v) // make value into string, then validate with regex
  1267. if result := validatefunc(field, ps[1:]...); (!result && !negate) || (result && negate) {
  1268. if customMsgExists {
  1269. return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1270. }
  1271. if negate {
  1272. return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1273. }
  1274. return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1275. }
  1276. default:
  1277. // type not yet supported, fail
  1278. return false, Error{t.Name, fmt.Errorf("Validator %s doesn't support kind %s", validator, v.Kind()), false, stripParams(validatorSpec), []string{}}
  1279. }
  1280. }
  1281. if validatefunc, ok := TagMap[validator]; ok {
  1282. delete(options, validatorSpec)
  1283. switch v.Kind() {
  1284. case reflect.String,
  1285. reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
  1286. reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
  1287. reflect.Float32, reflect.Float64:
  1288. field := fmt.Sprint(v) // make value into string, then validate with regex
  1289. if result := validatefunc(field); !result && !negate || result && negate {
  1290. if customMsgExists {
  1291. return false, Error{t.Name, TruncatingErrorf(validatorStruct.customErrorMessage, field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1292. }
  1293. if negate {
  1294. return false, Error{t.Name, fmt.Errorf("%s does validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1295. }
  1296. return false, Error{t.Name, fmt.Errorf("%s does not validate as %s", field, validator), customMsgExists, stripParams(validatorSpec), []string{}}
  1297. }
  1298. default:
  1299. //Not Yet Supported Types (Fail here!)
  1300. err := fmt.Errorf("Validator %s doesn't support kind %s for value %v", validator, v.Kind(), v)
  1301. return false, Error{t.Name, err, false, stripParams(validatorSpec), []string{}}
  1302. }
  1303. }
  1304. }
  1305. return true, nil
  1306. case reflect.Map:
  1307. if v.Type().Key().Kind() != reflect.String {
  1308. return false, &UnsupportedTypeError{v.Type()}
  1309. }
  1310. var sv stringValues
  1311. sv = v.MapKeys()
  1312. sort.Sort(sv)
  1313. result := true
  1314. for i, k := range sv {
  1315. var resultItem bool
  1316. var err error
  1317. if v.MapIndex(k).Kind() != reflect.Struct {
  1318. resultItem, err = typeCheck(v.MapIndex(k), t, o, options)
  1319. if err != nil {
  1320. return false, err
  1321. }
  1322. } else {
  1323. resultItem, err = ValidateStruct(v.MapIndex(k).Interface())
  1324. if err != nil {
  1325. err = prependPathToErrors(err, t.Name+"."+sv[i].Interface().(string))
  1326. return false, err
  1327. }
  1328. }
  1329. result = result && resultItem
  1330. }
  1331. return result, nil
  1332. case reflect.Slice, reflect.Array:
  1333. result := true
  1334. for i := 0; i < v.Len(); i++ {
  1335. var resultItem bool
  1336. var err error
  1337. if v.Index(i).Kind() != reflect.Struct {
  1338. resultItem, err = typeCheck(v.Index(i), t, o, options)
  1339. if err != nil {
  1340. return false, err
  1341. }
  1342. } else {
  1343. resultItem, err = ValidateStruct(v.Index(i).Interface())
  1344. if err != nil {
  1345. err = prependPathToErrors(err, t.Name+"."+strconv.Itoa(i))
  1346. return false, err
  1347. }
  1348. }
  1349. result = result && resultItem
  1350. }
  1351. return result, nil
  1352. case reflect.Interface:
  1353. // If the value is an interface then encode its element
  1354. if v.IsNil() {
  1355. return true, nil
  1356. }
  1357. return ValidateStruct(v.Interface())
  1358. case reflect.Ptr:
  1359. // If the value is a pointer then checks its element
  1360. if v.IsNil() {
  1361. return true, nil
  1362. }
  1363. return typeCheck(v.Elem(), t, o, options)
  1364. case reflect.Struct:
  1365. return true, nil
  1366. default:
  1367. return false, &UnsupportedTypeError{v.Type()}
  1368. }
  1369. }
  1370. func stripParams(validatorString string) string {
  1371. return paramsRegexp.ReplaceAllString(validatorString, "")
  1372. }
  1373. // isEmptyValue checks whether value empty or not
  1374. func isEmptyValue(v reflect.Value) bool {
  1375. switch v.Kind() {
  1376. case reflect.String, reflect.Array:
  1377. return v.Len() == 0
  1378. case reflect.Map, reflect.Slice:
  1379. return v.Len() == 0 || v.IsNil()
  1380. case reflect.Bool:
  1381. return !v.Bool()
  1382. case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  1383. return v.Int() == 0
  1384. case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  1385. return v.Uint() == 0
  1386. case reflect.Float32, reflect.Float64:
  1387. return v.Float() == 0
  1388. case reflect.Interface, reflect.Ptr:
  1389. return v.IsNil()
  1390. }
  1391. return reflect.DeepEqual(v.Interface(), reflect.Zero(v.Type()).Interface())
  1392. }
  1393. // ErrorByField returns error for specified field of the struct
  1394. // validated by ValidateStruct or empty string if there are no errors
  1395. // or this field doesn't exists or doesn't have any errors.
  1396. func ErrorByField(e error, field string) string {
  1397. if e == nil {
  1398. return ""
  1399. }
  1400. return ErrorsByField(e)[field]
  1401. }
  1402. // ErrorsByField returns map of errors of the struct validated
  1403. // by ValidateStruct or empty map if there are no errors.
  1404. func ErrorsByField(e error) map[string]string {
  1405. m := make(map[string]string)
  1406. if e == nil {
  1407. return m
  1408. }
  1409. // prototype for ValidateStruct
  1410. switch e := e.(type) {
  1411. case Error:
  1412. m[e.Name] = e.Err.Error()
  1413. case Errors:
  1414. for _, item := range e.Errors() {
  1415. n := ErrorsByField(item)
  1416. for k, v := range n {
  1417. m[k] = v
  1418. }
  1419. }
  1420. }
  1421. return m
  1422. }
  1423. // Error returns string equivalent for reflect.Type
  1424. func (e *UnsupportedTypeError) Error() string {
  1425. return "validator: unsupported type: " + e.Type.String()
  1426. }
  1427. func (sv stringValues) Len() int { return len(sv) }
  1428. func (sv stringValues) Swap(i, j int) { sv[i], sv[j] = sv[j], sv[i] }
  1429. func (sv stringValues) Less(i, j int) bool { return sv.get(i) < sv.get(j) }
  1430. func (sv stringValues) get(i int) string { return sv[i].String() }