mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-10-24 02:52:37 +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)
111 lines
2.8 KiB
Go
111 lines
2.8 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"
|
|
)
|
|
|
|
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
|
|
}
|
|
|
|
// 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)
|
|
}
|