mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-23 18:42:26 +00:00
Refs: https://codeberg.org/forgejo/forgejo/pulls/676 Author: Panagiotis "Ivory" Vasilopoulos <git@n0toose.net> Date: Mon Jun 12 13:57:01 2023 +0200 Co-authored-by: Gusted <postmaster@gusted.xyz> (cherry picked from commitfabdda5c6e) (cherry picked from commitd2c7f45621) (cherry picked from commitdfdbaba3d6) (cherry picked from commita3cda092b8) (cherry picked from commitf0fdb5905c) (cherry picked from commit9697e48c1f) (cherry picked from commit46e31009a8) (cherry picked from commit5bb2c54b6f) (cherry picked from commit682f9d24e1) (cherry picked from commit1863481005) (cherry picked from commit4f1b7c4ddb) (cherry picked from commit6afe70bbf1) (cherry picked from commit5cec1d9c2d) Conflicts: templates/admin/config.tmpl https://codeberg.org/forgejo/forgejo/pulls/1512 (cherry picked from commitde2d172473) (cherry picked from commit37a3172dd9) (cherry picked from commit92dfca0c5a) (cherry picked from commita713d59b0c) (cherry picked from commite7bd71a618) (cherry picked from commit69f3e952c4) (cherry picked from commit83fbb7b566) (cherry picked from commit3196605fa9) (cherry picked from commite37eb8de9c) (cherry picked from commit8c99f59e48) (cherry picked from commit74aa1ac66f) (cherry picked from commit622440b3bd) (cherry picked from commit2c1ec90984) (cherry picked from commit24d57152e0) (cherry picked from commit071e9013f3)
136 lines
3.3 KiB
Go
136 lines
3.3 KiB
Go
// Copyright 2018 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package validation
|
|
|
|
import (
|
|
"net"
|
|
"net/url"
|
|
"regexp"
|
|
"strings"
|
|
|
|
"code.gitea.io/gitea/modules/setting"
|
|
|
|
"github.com/gobwas/glob"
|
|
)
|
|
|
|
var externalTrackerRegex = regexp.MustCompile(`({?)(?:user|repo|index)+?(}?)`)
|
|
|
|
func isLoopbackIP(ip string) bool {
|
|
return net.ParseIP(ip).IsLoopback()
|
|
}
|
|
|
|
// IsValidURL checks if URL is valid
|
|
func IsValidURL(uri string) bool {
|
|
if u, err := url.ParseRequestURI(uri); err != nil ||
|
|
(u.Scheme != "http" && u.Scheme != "https") ||
|
|
!validPort(portOnly(u.Host)) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
// IsValidSiteURL checks if URL is valid
|
|
func IsValidSiteURL(uri string) bool {
|
|
u, err := url.ParseRequestURI(uri)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
if !validPort(portOnly(u.Host)) {
|
|
return false
|
|
}
|
|
|
|
for _, scheme := range setting.Service.ValidSiteURLSchemes {
|
|
if scheme == u.Scheme {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
// IsEmailDomainListed checks whether the domain of an email address
|
|
// matches a list of domains
|
|
func IsEmailDomainListed(globs []glob.Glob, email string) bool {
|
|
if len(globs) == 0 {
|
|
return false
|
|
}
|
|
|
|
n := strings.LastIndex(email, "@")
|
|
if n <= 0 {
|
|
return false
|
|
}
|
|
|
|
domain := strings.ToLower(email[n+1:])
|
|
|
|
for _, g := range globs {
|
|
if g.Match(domain) {
|
|
return true
|
|
}
|
|
}
|
|
|
|
return false
|
|
}
|
|
|
|
// IsAPIURL checks if URL is current Gitea instance API URL
|
|
func IsAPIURL(uri string) bool {
|
|
return strings.HasPrefix(strings.ToLower(uri), strings.ToLower(setting.AppURL+"api"))
|
|
}
|
|
|
|
// IsValidExternalURL checks if URL is valid external URL
|
|
func IsValidExternalURL(uri string) bool {
|
|
if !IsValidURL(uri) || IsAPIURL(uri) {
|
|
return false
|
|
}
|
|
|
|
u, err := url.ParseRequestURI(uri)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
// Currently check only if not loopback IP is provided to keep compatibility
|
|
if isLoopbackIP(u.Hostname()) || strings.ToLower(u.Hostname()) == "localhost" {
|
|
return false
|
|
}
|
|
|
|
// TODO: Later it should be added to allow local network IP addresses
|
|
// only if allowed by special setting
|
|
|
|
return true
|
|
}
|
|
|
|
// IsValidExternalTrackerURLFormat checks if URL matches required syntax for external trackers
|
|
func IsValidExternalTrackerURLFormat(uri string) bool {
|
|
if !IsValidExternalURL(uri) {
|
|
return false
|
|
}
|
|
|
|
// check for typoed variables like /{index/ or /[repo}
|
|
for _, match := range externalTrackerRegex.FindAllStringSubmatch(uri, -1) {
|
|
if (match[1] == "{" || match[2] == "}") && (match[1] != "{" || match[2] != "}") {
|
|
return false
|
|
}
|
|
}
|
|
|
|
return true
|
|
}
|
|
|
|
var (
|
|
validUsernamePatternWithDots = regexp.MustCompile(`^[\da-zA-Z][-.\w]*$`)
|
|
validUsernamePatternWithoutDots = regexp.MustCompile(`^[\da-zA-Z][-\w]*$`)
|
|
|
|
// No consecutive or trailing non-alphanumeric chars, catches both cases
|
|
invalidUsernamePattern = regexp.MustCompile(`[-._]{2,}|[-._]$`)
|
|
)
|
|
|
|
// IsValidUsername checks if username is valid
|
|
func IsValidUsername(name string) bool {
|
|
// It is difficult to find a single pattern that is both readable and effective,
|
|
// but it's easier to use positive and negative checks.
|
|
if setting.Service.AllowDotsInUsernames {
|
|
return validUsernamePatternWithDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
|
}
|
|
|
|
return validUsernamePatternWithoutDots.MatchString(name) && !invalidUsernamePattern.MatchString(name)
|
|
}
|