2017-04-19 06:02:20 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2017-04-19 06:02:20 +03:00
package validation
import (
"fmt"
"regexp"
"strings"
2023-02-08 09:44:42 +03:00
"code.gitea.io/gitea/modules/auth"
2022-09-04 13:47:56 +03:00
"code.gitea.io/gitea/modules/git"
2024-11-28 05:50:27 +03:00
"code.gitea.io/gitea/modules/util"
2022-09-04 13:47:56 +03:00
2021-01-26 18:36:53 +03:00
"gitea.com/go-chi/binding"
2019-09-09 08:48:21 +03:00
"github.com/gobwas/glob"
2017-04-19 06:02:20 +03:00
)
const (
// ErrGitRefName is git reference name error
ErrGitRefName = "GitRefNameError"
2019-09-09 08:48:21 +03:00
// ErrGlobPattern is returned when glob pattern is invalid
ErrGlobPattern = "GlobPattern"
2021-06-25 17:28:55 +03:00
// ErrRegexPattern is returned when a regex pattern is invalid
ErrRegexPattern = "RegexPattern"
2022-11-04 12:04:08 +03:00
// ErrUsername is username error
ErrUsername = "UsernameError"
2023-02-08 09:44:42 +03:00
// ErrInvalidGroupTeamMap is returned when a group team mapping is invalid
ErrInvalidGroupTeamMap = "InvalidGroupTeamMap"
2017-04-19 06:02:20 +03:00
)
// AddBindingRules adds additional binding rules
func AddBindingRules ( ) {
addGitRefNameBindingRule ( )
2024-11-28 05:50:27 +03:00
addValidURLListBindingRule ( )
2017-04-19 06:02:20 +03:00
addValidURLBindingRule ( )
2021-06-26 01:38:27 +03:00
addValidSiteURLBindingRule ( )
2019-09-09 08:48:21 +03:00
addGlobPatternRule ( )
2021-06-25 17:28:55 +03:00
addRegexPatternRule ( )
addGlobOrRegexPatternRule ( )
2022-11-04 12:04:08 +03:00
addUsernamePatternRule ( )
2023-02-08 09:44:42 +03:00
addValidGroupTeamMapRule ( )
2017-04-19 06:02:20 +03:00
}
func addGitRefNameBindingRule ( ) {
// Git refname validation rule
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
2024-11-28 05:50:27 +03:00
return rule == "GitRefName"
2017-04-19 06:02:20 +03:00
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2017-04-19 06:02:20 +03:00
str := fmt . Sprintf ( "%v" , val )
2022-09-04 13:47:56 +03:00
if ! git . IsValidRefPattern ( str ) {
2017-04-19 06:02:20 +03:00
errs . Add ( [ ] string { name } , ErrGitRefName , "GitRefName" )
return false , errs
}
return true , errs
} ,
} )
}
2024-11-28 05:50:27 +03:00
func addValidURLListBindingRule ( ) {
// URL validation rule
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
return rule == "ValidUrlList"
} ,
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
str := fmt . Sprintf ( "%v" , val )
if len ( str ) == 0 {
errs . Add ( [ ] string { name } , binding . ERR_URL , "Url" )
return false , errs
}
ok := true
urls := util . SplitTrimSpace ( str , "\n" )
for _ , u := range urls {
if ! IsValidURL ( u ) {
ok = false
errs . Add ( [ ] string { name } , binding . ERR_URL , u )
}
}
return ok , errs
} ,
} )
}
2017-04-19 06:02:20 +03:00
func addValidURLBindingRule ( ) {
// URL validation rule
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
2024-11-28 05:50:27 +03:00
return rule == "ValidUrl"
2017-04-19 06:02:20 +03:00
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2017-04-19 06:02:20 +03:00
str := fmt . Sprintf ( "%v" , val )
2018-08-15 09:29:37 +03:00
if len ( str ) != 0 && ! IsValidURL ( str ) {
errs . Add ( [ ] string { name } , binding . ERR_URL , "Url" )
return false , errs
2017-04-19 06:02:20 +03:00
}
return true , errs
} ,
} )
}
2021-06-26 01:38:27 +03:00
func addValidSiteURLBindingRule ( ) {
// URL validation rule
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
2024-11-28 05:50:27 +03:00
return rule == "ValidSiteUrl"
2021-06-26 01:38:27 +03:00
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2021-06-26 01:38:27 +03:00
str := fmt . Sprintf ( "%v" , val )
if len ( str ) != 0 && ! IsValidSiteURL ( str ) {
errs . Add ( [ ] string { name } , binding . ERR_URL , "Url" )
return false , errs
}
return true , errs
} ,
} )
}
2019-09-09 08:48:21 +03:00
func addGlobPatternRule ( ) {
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
return rule == "GlobPattern"
} ,
2021-06-25 17:28:55 +03:00
IsValid : globPatternValidator ,
} )
}
2023-07-04 21:36:08 +03:00
func globPatternValidator ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2021-06-25 17:28:55 +03:00
str := fmt . Sprintf ( "%v" , val )
if len ( str ) != 0 {
if _ , err := glob . Compile ( str ) ; err != nil {
errs . Add ( [ ] string { name } , ErrGlobPattern , err . Error ( ) )
return false , errs
}
}
return true , errs
}
func addRegexPatternRule ( ) {
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
return rule == "RegexPattern"
} ,
IsValid : regexPatternValidator ,
} )
}
2023-07-04 21:36:08 +03:00
func regexPatternValidator ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2021-06-25 17:28:55 +03:00
str := fmt . Sprintf ( "%v" , val )
if _ , err := regexp . Compile ( str ) ; err != nil {
errs . Add ( [ ] string { name } , ErrRegexPattern , err . Error ( ) )
return false , errs
}
return true , errs
}
func addGlobOrRegexPatternRule ( ) {
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
return rule == "GlobOrRegexPattern"
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2021-06-25 17:28:55 +03:00
str := strings . TrimSpace ( fmt . Sprintf ( "%v" , val ) )
2019-09-09 08:48:21 +03:00
2021-06-25 17:28:55 +03:00
if len ( str ) >= 2 && strings . HasPrefix ( str , "/" ) && strings . HasSuffix ( str , "/" ) {
return regexPatternValidator ( errs , name , str [ 1 : len ( str ) - 1 ] )
2019-09-09 08:48:21 +03:00
}
2021-06-25 17:28:55 +03:00
return globPatternValidator ( errs , name , val )
2019-09-09 08:48:21 +03:00
} ,
} )
}
2022-11-04 12:04:08 +03:00
func addUsernamePatternRule ( ) {
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
return rule == "Username"
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2022-11-04 12:04:08 +03:00
str := fmt . Sprintf ( "%v" , val )
if ! IsValidUsername ( str ) {
errs . Add ( [ ] string { name } , ErrUsername , "invalid username" )
return false , errs
}
return true , errs
} ,
} )
}
2023-02-08 09:44:42 +03:00
func addValidGroupTeamMapRule ( ) {
binding . AddRule ( & binding . Rule {
IsMatch : func ( rule string ) bool {
2024-11-28 05:50:27 +03:00
return rule == "ValidGroupTeamMap"
2023-02-08 09:44:42 +03:00
} ,
2023-07-04 21:36:08 +03:00
IsValid : func ( errs binding . Errors , name string , val any ) ( bool , binding . Errors ) {
2023-02-08 09:44:42 +03:00
_ , err := auth . UnmarshalGroupTeamMapping ( fmt . Sprintf ( "%v" , val ) )
if err != nil {
errs . Add ( [ ] string { name } , ErrInvalidGroupTeamMap , err . Error ( ) )
return false , errs
}
return true , errs
} ,
} )
}
2017-04-19 06:02:20 +03:00
func portOnly ( hostport string ) string {
colon := strings . IndexByte ( hostport , ':' )
if colon == - 1 {
return ""
}
if i := strings . Index ( hostport , "]:" ) ; i != - 1 {
return hostport [ i + len ( "]:" ) : ]
}
if strings . Contains ( hostport , "]" ) {
return ""
}
return hostport [ colon + len ( ":" ) : ]
}
func validPort ( p string ) bool {
for _ , r := range [ ] byte ( p ) {
if r < '0' || r > '9' {
return false
}
}
return true
}