form.go 4.1 KB

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