code.gitea.io/gitea@v1.19.3/modules/validation/helpers.go (about) 1 // Copyright 2018 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package validation 5 6 import ( 7 "net" 8 "net/url" 9 "regexp" 10 "strings" 11 12 "code.gitea.io/gitea/modules/setting" 13 ) 14 15 var externalTrackerRegex = regexp.MustCompile(`({?)(?:user|repo|index)+?(}?)`) 16 17 func isLoopbackIP(ip string) bool { 18 return net.ParseIP(ip).IsLoopback() 19 } 20 21 // IsValidURL checks if URL is valid 22 func IsValidURL(uri string) bool { 23 if u, err := url.ParseRequestURI(uri); err != nil || 24 (u.Scheme != "http" && u.Scheme != "https") || 25 !validPort(portOnly(u.Host)) { 26 return false 27 } 28 29 return true 30 } 31 32 // IsValidSiteURL checks if URL is valid 33 func IsValidSiteURL(uri string) bool { 34 u, err := url.ParseRequestURI(uri) 35 if err != nil { 36 return false 37 } 38 39 if !validPort(portOnly(u.Host)) { 40 return false 41 } 42 43 for _, scheme := range setting.Service.ValidSiteURLSchemes { 44 if scheme == u.Scheme { 45 return true 46 } 47 } 48 return false 49 } 50 51 // IsAPIURL checks if URL is current Gitea instance API URL 52 func IsAPIURL(uri string) bool { 53 return strings.HasPrefix(strings.ToLower(uri), strings.ToLower(setting.AppURL+"api")) 54 } 55 56 // IsValidExternalURL checks if URL is valid external URL 57 func IsValidExternalURL(uri string) bool { 58 if !IsValidURL(uri) || IsAPIURL(uri) { 59 return false 60 } 61 62 u, err := url.ParseRequestURI(uri) 63 if err != nil { 64 return false 65 } 66 67 // Currently check only if not loopback IP is provided to keep compatibility 68 if isLoopbackIP(u.Hostname()) || strings.ToLower(u.Hostname()) == "localhost" { 69 return false 70 } 71 72 // TODO: Later it should be added to allow local network IP addresses 73 // only if allowed by special setting 74 75 return true 76 } 77 78 // IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers 79 func IsValidExternalTrackerURLFormat(uri string) bool { 80 if !IsValidExternalURL(uri) { 81 return false 82 } 83 84 // check for typoed variables like /{index/ or /[repo} 85 for _, match := range externalTrackerRegex.FindAllStringSubmatch(uri, -1) { 86 if (match[1] == "{" || match[2] == "}") && (match[1] != "{" || match[2] != "}") { 87 return false 88 } 89 } 90 91 return true 92 } 93 94 var ( 95 validUsernamePattern = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`) 96 invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`) // No consecutive or trailing non-alphanumeric chars 97 ) 98 99 // IsValidUsername checks if username is valid 100 func IsValidUsername(name string) bool { 101 // It is difficult to find a single pattern that is both readable and effective, 102 // but it's easier to use positive and negative checks. 103 return validUsernamePattern.MatchString(name) && !invalidUsernamePattern.MatchString(name) 104 }