You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright 2017 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package validation
  5. import (
  6. "fmt"
  7. "regexp"
  8. "strings"
  9. "gitea.com/macaron/binding"
  10. "github.com/gobwas/glob"
  11. )
  12. const (
  13. // ErrGitRefName is git reference name error
  14. ErrGitRefName = "GitRefNameError"
  15. // ErrGlobPattern is returned when glob pattern is invalid
  16. ErrGlobPattern = "GlobPattern"
  17. )
  18. var (
  19. // GitRefNamePattern is regular expression with unallowed characters in git reference name
  20. // They cannot have ASCII control characters (i.e. bytes whose values are lower than \040, or \177 DEL), space, tilde ~, caret ^, or colon : anywhere.
  21. // They cannot have question-mark ?, asterisk *, or open bracket [ anywhere
  22. GitRefNamePattern = regexp.MustCompile(`[\000-\037\177 \\~^:?*[]+`)
  23. )
  24. // AddBindingRules adds additional binding rules
  25. func AddBindingRules() {
  26. addGitRefNameBindingRule()
  27. addValidURLBindingRule()
  28. addGlobPatternRule()
  29. }
  30. func addGitRefNameBindingRule() {
  31. // Git refname validation rule
  32. binding.AddRule(&binding.Rule{
  33. IsMatch: func(rule string) bool {
  34. return strings.HasPrefix(rule, "GitRefName")
  35. },
  36. IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
  37. str := fmt.Sprintf("%v", val)
  38. if GitRefNamePattern.MatchString(str) {
  39. errs.Add([]string{name}, ErrGitRefName, "GitRefName")
  40. return false, errs
  41. }
  42. // Additional rules as described at https://www.kernel.org/pub/software/scm/git/docs/git-check-ref-format.html
  43. if strings.HasPrefix(str, "/") || strings.HasSuffix(str, "/") ||
  44. strings.HasSuffix(str, ".") || strings.Contains(str, "..") ||
  45. strings.Contains(str, "//") || strings.Contains(str, "@{") ||
  46. str == "@" {
  47. errs.Add([]string{name}, ErrGitRefName, "GitRefName")
  48. return false, errs
  49. }
  50. parts := strings.Split(str, "/")
  51. for _, part := range parts {
  52. if strings.HasSuffix(part, ".lock") || strings.HasPrefix(part, ".") {
  53. errs.Add([]string{name}, ErrGitRefName, "GitRefName")
  54. return false, errs
  55. }
  56. }
  57. return true, errs
  58. },
  59. })
  60. }
  61. func addValidURLBindingRule() {
  62. // URL validation rule
  63. binding.AddRule(&binding.Rule{
  64. IsMatch: func(rule string) bool {
  65. return strings.HasPrefix(rule, "ValidUrl")
  66. },
  67. IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
  68. str := fmt.Sprintf("%v", val)
  69. if len(str) != 0 && !IsValidURL(str) {
  70. errs.Add([]string{name}, binding.ERR_URL, "Url")
  71. return false, errs
  72. }
  73. return true, errs
  74. },
  75. })
  76. }
  77. func addGlobPatternRule() {
  78. binding.AddRule(&binding.Rule{
  79. IsMatch: func(rule string) bool {
  80. return rule == "GlobPattern"
  81. },
  82. IsValid: func(errs binding.Errors, name string, val interface{}) (bool, binding.Errors) {
  83. str := fmt.Sprintf("%v", val)
  84. if len(str) != 0 {
  85. if _, err := glob.Compile(str); err != nil {
  86. errs.Add([]string{name}, ErrGlobPattern, err.Error())
  87. return false, errs
  88. }
  89. }
  90. return true, errs
  91. },
  92. })
  93. }
  94. func portOnly(hostport string) string {
  95. colon := strings.IndexByte(hostport, ':')
  96. if colon == -1 {
  97. return ""
  98. }
  99. if i := strings.Index(hostport, "]:"); i != -1 {
  100. return hostport[i+len("]:"):]
  101. }
  102. if strings.Contains(hostport, "]") {
  103. return ""
  104. }
  105. return hostport[colon+len(":"):]
  106. }
  107. func validPort(p string) bool {
  108. for _, r := range []byte(p) {
  109. if r < '0' || r > '9' {
  110. return false
  111. }
  112. }
  113. return true
  114. }