PageRenderTime 750ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/vendor/github.com/xeipuuv/gojsonschema/format_checkers.go

https://bitbucket.org/RusAlex/cryptocoins
Go | 250 lines | 151 code | 55 blank | 44 comment | 36 complexity | 9c265883ae8e866288f152bd8b48b23a MD5 | raw file
Possible License(s): 0BSD, MIT, MPL-2.0-no-copyleft-exception, BSD-3-Clause, Apache-2.0
  1. package gojsonschema
  2. import (
  3. "net"
  4. "net/url"
  5. "regexp"
  6. "strings"
  7. "time"
  8. )
  9. type (
  10. // FormatChecker is the interface all formatters added to FormatCheckerChain must implement
  11. FormatChecker interface {
  12. IsFormat(input interface{}) bool
  13. }
  14. // FormatCheckerChain holds the formatters
  15. FormatCheckerChain struct {
  16. formatters map[string]FormatChecker
  17. }
  18. // EmailFormatter verifies email address formats
  19. EmailFormatChecker struct{}
  20. // IPV4FormatChecker verifies IP addresses in the ipv4 format
  21. IPV4FormatChecker struct{}
  22. // IPV6FormatChecker verifies IP addresses in the ipv6 format
  23. IPV6FormatChecker struct{}
  24. // DateTimeFormatChecker verifies date/time formats per RFC3339 5.6
  25. //
  26. // Valid formats:
  27. // Partial Time: HH:MM:SS
  28. // Full Date: YYYY-MM-DD
  29. // Full Time: HH:MM:SSZ-07:00
  30. // Date Time: YYYY-MM-DDTHH:MM:SSZ-0700
  31. //
  32. // Where
  33. // YYYY = 4DIGIT year
  34. // MM = 2DIGIT month ; 01-12
  35. // DD = 2DIGIT day-month ; 01-28, 01-29, 01-30, 01-31 based on month/year
  36. // HH = 2DIGIT hour ; 00-23
  37. // MM = 2DIGIT ; 00-59
  38. // SS = 2DIGIT ; 00-58, 00-60 based on leap second rules
  39. // T = Literal
  40. // Z = Literal
  41. //
  42. // Note: Nanoseconds are also suported in all formats
  43. //
  44. // http://tools.ietf.org/html/rfc3339#section-5.6
  45. DateTimeFormatChecker struct{}
  46. // URIFormatChecker validates a URI with a valid Scheme per RFC3986
  47. URIFormatChecker struct{}
  48. // URIReferenceFormatChecker validates a URI or relative-reference per RFC3986
  49. URIReferenceFormatChecker struct{}
  50. // HostnameFormatChecker validates a hostname is in the correct format
  51. HostnameFormatChecker struct{}
  52. // UUIDFormatChecker validates a UUID is in the correct format
  53. UUIDFormatChecker struct{}
  54. // RegexFormatChecker validates a regex is in the correct format
  55. RegexFormatChecker struct{}
  56. )
  57. var (
  58. // Formatters holds the valid formatters, and is a public variable
  59. // so library users can add custom formatters
  60. FormatCheckers = FormatCheckerChain{
  61. formatters: map[string]FormatChecker{
  62. "date-time": DateTimeFormatChecker{},
  63. "hostname": HostnameFormatChecker{},
  64. "email": EmailFormatChecker{},
  65. "ipv4": IPV4FormatChecker{},
  66. "ipv6": IPV6FormatChecker{},
  67. "uri": URIFormatChecker{},
  68. "uri-reference": URIReferenceFormatChecker{},
  69. "uuid": UUIDFormatChecker{},
  70. "regex": RegexFormatChecker{},
  71. },
  72. }
  73. // Regex credit: https://github.com/asaskevich/govalidator
  74. rxEmail = regexp.MustCompile("^(((([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+(\\.([a-zA-Z]|\\d|[!#\\$%&'\\*\\+\\-\\/=\\?\\^_`{\\|}~]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])+)*)|((\\x22)((((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(([\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x7f]|\\x21|[\\x23-\\x5b]|[\\x5d-\\x7e]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(\\([\\x01-\\x09\\x0b\\x0c\\x0d-\\x7f]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}]))))*(((\\x20|\\x09)*(\\x0d\\x0a))?(\\x20|\\x09)+)?(\\x22)))@((([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|\\d|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.)+(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])|(([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])([a-zA-Z]|\\d|-|\\.|_|~|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])*([a-zA-Z]|[\\x{00A0}-\\x{D7FF}\\x{F900}-\\x{FDCF}\\x{FDF0}-\\x{FFEF}])))\\.?$")
  75. // Regex credit: https://www.socketloop.com/tutorials/golang-validate-hostname
  76. rxHostname = regexp.MustCompile(`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`)
  77. rxUUID = regexp.MustCompile("^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$")
  78. )
  79. // Add adds a FormatChecker to the FormatCheckerChain
  80. // The name used will be the value used for the format key in your json schema
  81. func (c *FormatCheckerChain) Add(name string, f FormatChecker) *FormatCheckerChain {
  82. c.formatters[name] = f
  83. return c
  84. }
  85. // Remove deletes a FormatChecker from the FormatCheckerChain (if it exists)
  86. func (c *FormatCheckerChain) Remove(name string) *FormatCheckerChain {
  87. delete(c.formatters, name)
  88. return c
  89. }
  90. // Has checks to see if the FormatCheckerChain holds a FormatChecker with the given name
  91. func (c *FormatCheckerChain) Has(name string) bool {
  92. _, ok := c.formatters[name]
  93. return ok
  94. }
  95. // IsFormat will check an input against a FormatChecker with the given name
  96. // to see if it is the correct format
  97. func (c *FormatCheckerChain) IsFormat(name string, input interface{}) bool {
  98. f, ok := c.formatters[name]
  99. if !ok {
  100. return false
  101. }
  102. return f.IsFormat(input)
  103. }
  104. func (f EmailFormatChecker) IsFormat(input interface{}) bool {
  105. asString, ok := input.(string)
  106. if ok == false {
  107. return false
  108. }
  109. return rxEmail.MatchString(asString)
  110. }
  111. // Credit: https://github.com/asaskevich/govalidator
  112. func (f IPV4FormatChecker) IsFormat(input interface{}) bool {
  113. asString, ok := input.(string)
  114. if ok == false {
  115. return false
  116. }
  117. ip := net.ParseIP(asString)
  118. return ip != nil && strings.Contains(asString, ".")
  119. }
  120. // Credit: https://github.com/asaskevich/govalidator
  121. func (f IPV6FormatChecker) IsFormat(input interface{}) bool {
  122. asString, ok := input.(string)
  123. if ok == false {
  124. return false
  125. }
  126. ip := net.ParseIP(asString)
  127. return ip != nil && strings.Contains(asString, ":")
  128. }
  129. func (f DateTimeFormatChecker) IsFormat(input interface{}) bool {
  130. asString, ok := input.(string)
  131. if ok == false {
  132. return false
  133. }
  134. formats := []string{
  135. "15:04:05",
  136. "15:04:05Z07:00",
  137. "2006-01-02",
  138. time.RFC3339,
  139. time.RFC3339Nano,
  140. }
  141. for _, format := range formats {
  142. if _, err := time.Parse(format, asString); err == nil {
  143. return true
  144. }
  145. }
  146. return false
  147. }
  148. func (f URIFormatChecker) IsFormat(input interface{}) bool {
  149. asString, ok := input.(string)
  150. if ok == false {
  151. return false
  152. }
  153. u, err := url.Parse(asString)
  154. if err != nil || u.Scheme == "" {
  155. return false
  156. }
  157. return true
  158. }
  159. func (f URIReferenceFormatChecker) IsFormat(input interface{}) bool {
  160. asString, ok := input.(string)
  161. if ok == false {
  162. return false
  163. }
  164. _, err := url.Parse(asString)
  165. return err == nil
  166. }
  167. func (f HostnameFormatChecker) IsFormat(input interface{}) bool {
  168. asString, ok := input.(string)
  169. if ok == false {
  170. return false
  171. }
  172. return rxHostname.MatchString(asString) && len(asString) < 256
  173. }
  174. func (f UUIDFormatChecker) IsFormat(input interface{}) bool {
  175. asString, ok := input.(string)
  176. if ok == false {
  177. return false
  178. }
  179. return rxUUID.MatchString(asString)
  180. }
  181. // IsFormat implements FormatChecker interface.
  182. func (f RegexFormatChecker) IsFormat(input interface{}) bool {
  183. asString, ok := input.(string)
  184. if ok == false {
  185. return false
  186. }
  187. if asString == "" {
  188. return true
  189. }
  190. _, err := regexp.Compile(asString)
  191. if err != nil {
  192. return false
  193. }
  194. return true
  195. }