form.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. // Copyright 2015 The Gogs Authors. All rights reserved.
  2. // Copyright 2018 Gitote. All rights reserved.
  3. //
  4. // This source code is licensed under the MIT license found in the
  5. // LICENSE file in the root directory of this source tree.
  6. package form
  7. import (
  8. "fmt"
  9. "reflect"
  10. "regexp"
  11. "strings"
  12. "github.com/go-macaron/binding"
  13. "gitlab.com/gitote/com"
  14. "gopkg.in/macaron.v1"
  15. )
  16. const ERR_ALPHA_DASH_DOT_SLASH = "AlphaDashDotSlashError"
  17. var AlphaDashDotSlashPattern = regexp.MustCompile("[^\\d\\w-_\\./]")
  18. func init() {
  19. binding.SetNameMapper(com.ToSnakeCase)
  20. binding.AddRule(&binding.Rule{
  21. IsMatch: func(rule string) bool {
  22. return rule == "AlphaDashDotSlash"
  23. },
  24. IsValid: func(errs binding.Errors, name string, v interface{}) (bool, binding.Errors) {
  25. if AlphaDashDotSlashPattern.MatchString(fmt.Sprintf("%v", v)) {
  26. errs.Add([]string{name}, ERR_ALPHA_DASH_DOT_SLASH, "AlphaDashDotSlash")
  27. return false, errs
  28. }
  29. return true, errs
  30. },
  31. })
  32. }
  33. type Form interface {
  34. binding.Validator
  35. }
  36. // Assign assign form values back to the template data.
  37. func Assign(form interface{}, data map[string]interface{}) {
  38. typ := reflect.TypeOf(form)
  39. val := reflect.ValueOf(form)
  40. if typ.Kind() == reflect.Ptr {
  41. typ = typ.Elem()
  42. val = val.Elem()
  43. }
  44. for i := 0; i < typ.NumField(); i++ {
  45. field := typ.Field(i)
  46. fieldName := field.Tag.Get("form")
  47. // Allow ignored fields in the struct
  48. if fieldName == "-" {
  49. continue
  50. } else if len(fieldName) == 0 {
  51. fieldName = com.ToSnakeCase(field.Name)
  52. }
  53. data[fieldName] = val.Field(i).Interface()
  54. }
  55. }
  56. func getRuleBody(field reflect.StructField, prefix string) string {
  57. for _, rule := range strings.Split(field.Tag.Get("binding"), ";") {
  58. if strings.HasPrefix(rule, prefix) {
  59. return rule[len(prefix) : len(rule)-1]
  60. }
  61. }
  62. return ""
  63. }
  64. func getSize(field reflect.StructField) string {
  65. return getRuleBody(field, "Size(")
  66. }
  67. func getMinSize(field reflect.StructField) string {
  68. return getRuleBody(field, "MinSize(")
  69. }
  70. func getMaxSize(field reflect.StructField) string {
  71. return getRuleBody(field, "MaxSize(")
  72. }
  73. func getInclude(field reflect.StructField) string {
  74. return getRuleBody(field, "Include(")
  75. }
  76. func validate(errs binding.Errors, data map[string]interface{}, f Form, l macaron.Locale) binding.Errors {
  77. if errs.Len() == 0 {
  78. return errs
  79. }
  80. data["HasError"] = true
  81. Assign(f, data)
  82. typ := reflect.TypeOf(f)
  83. val := reflect.ValueOf(f)
  84. if typ.Kind() == reflect.Ptr {
  85. typ = typ.Elem()
  86. val = val.Elem()
  87. }
  88. for i := 0; i < typ.NumField(); i++ {
  89. field := typ.Field(i)
  90. fieldName := field.Tag.Get("form")
  91. // Allow ignored fields in the struct
  92. if fieldName == "-" {
  93. continue
  94. }
  95. if errs[0].FieldNames[0] == field.Name {
  96. data["Err_"+field.Name] = true
  97. trName := field.Tag.Get("locale")
  98. if len(trName) == 0 {
  99. trName = l.Tr("form." + field.Name)
  100. } else {
  101. trName = l.Tr(trName)
  102. }
  103. switch errs[0].Classification {
  104. case binding.ERR_REQUIRED:
  105. data["ErrorMsg"] = trName + l.Tr("form.require_error")
  106. case binding.ERR_ALPHA_DASH:
  107. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_error")
  108. case binding.ERR_ALPHA_DASH_DOT:
  109. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_error")
  110. case ERR_ALPHA_DASH_DOT_SLASH:
  111. data["ErrorMsg"] = trName + l.Tr("form.alpha_dash_dot_slash_error")
  112. case binding.ERR_SIZE:
  113. data["ErrorMsg"] = trName + l.Tr("form.size_error", getSize(field))
  114. case binding.ERR_MIN_SIZE:
  115. data["ErrorMsg"] = trName + l.Tr("form.min_size_error", getMinSize(field))
  116. case binding.ERR_MAX_SIZE:
  117. data["ErrorMsg"] = trName + l.Tr("form.max_size_error", getMaxSize(field))
  118. case binding.ERR_EMAIL:
  119. data["ErrorMsg"] = trName + l.Tr("form.email_error")
  120. case binding.ERR_URL:
  121. data["ErrorMsg"] = trName + l.Tr("form.url_error")
  122. case binding.ERR_INCLUDE:
  123. data["ErrorMsg"] = trName + l.Tr("form.include_error", getInclude(field))
  124. default:
  125. data["ErrorMsg"] = l.Tr("form.unknown_error") + " " + errs[0].Classification
  126. }
  127. return errs
  128. }
  129. }
  130. return errs
  131. }