mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-03-09 17:09:29 +00:00
Several packages are only used while running the e2e suite. These packages are less important to update, as the they can not influence the final executable that is part of the Ceph-CSI container-image. By moving these dependencies out of the main Ceph-CSI go.mod, it is easier to identify if a reported CVE affects Ceph-CSI, or only the testing (like most of the Kubernetes CVEs). Signed-off-by: Niels de Vos <ndevos@ibm.com>
271 lines
7.8 KiB
Go
271 lines
7.8 KiB
Go
package govalidator
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"html"
|
|
"math"
|
|
"path"
|
|
"regexp"
|
|
"strings"
|
|
"unicode"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
// Contains check if the string contains the substring.
|
|
func Contains(str, substring string) bool {
|
|
return strings.Contains(str, substring)
|
|
}
|
|
|
|
// Matches check if string matches the pattern (pattern is regular expression)
|
|
// In case of error return false
|
|
func Matches(str, pattern string) bool {
|
|
match, _ := regexp.MatchString(pattern, str)
|
|
return match
|
|
}
|
|
|
|
// LeftTrim trim characters from the left-side of the input.
|
|
// If second argument is empty, it's will be remove leading spaces.
|
|
func LeftTrim(str, chars string) string {
|
|
if chars == "" {
|
|
return strings.TrimLeftFunc(str, unicode.IsSpace)
|
|
}
|
|
r, _ := regexp.Compile("^[" + chars + "]+")
|
|
return r.ReplaceAllString(str, "")
|
|
}
|
|
|
|
// RightTrim trim characters from the right-side of the input.
|
|
// If second argument is empty, it's will be remove spaces.
|
|
func RightTrim(str, chars string) string {
|
|
if chars == "" {
|
|
return strings.TrimRightFunc(str, unicode.IsSpace)
|
|
}
|
|
r, _ := regexp.Compile("[" + chars + "]+$")
|
|
return r.ReplaceAllString(str, "")
|
|
}
|
|
|
|
// Trim trim characters from both sides of the input.
|
|
// If second argument is empty, it's will be remove spaces.
|
|
func Trim(str, chars string) string {
|
|
return LeftTrim(RightTrim(str, chars), chars)
|
|
}
|
|
|
|
// WhiteList remove characters that do not appear in the whitelist.
|
|
func WhiteList(str, chars string) string {
|
|
pattern := "[^" + chars + "]+"
|
|
r, _ := regexp.Compile(pattern)
|
|
return r.ReplaceAllString(str, "")
|
|
}
|
|
|
|
// BlackList remove characters that appear in the blacklist.
|
|
func BlackList(str, chars string) string {
|
|
pattern := "[" + chars + "]+"
|
|
r, _ := regexp.Compile(pattern)
|
|
return r.ReplaceAllString(str, "")
|
|
}
|
|
|
|
// StripLow remove characters with a numerical value < 32 and 127, mostly control characters.
|
|
// If keep_new_lines is true, newline characters are preserved (\n and \r, hex 0xA and 0xD).
|
|
func StripLow(str string, keepNewLines bool) string {
|
|
chars := ""
|
|
if keepNewLines {
|
|
chars = "\x00-\x09\x0B\x0C\x0E-\x1F\x7F"
|
|
} else {
|
|
chars = "\x00-\x1F\x7F"
|
|
}
|
|
return BlackList(str, chars)
|
|
}
|
|
|
|
// ReplacePattern replace regular expression pattern in string
|
|
func ReplacePattern(str, pattern, replace string) string {
|
|
r, _ := regexp.Compile(pattern)
|
|
return r.ReplaceAllString(str, replace)
|
|
}
|
|
|
|
// Escape replace <, >, & and " with HTML entities.
|
|
var Escape = html.EscapeString
|
|
|
|
func addSegment(inrune, segment []rune) []rune {
|
|
if len(segment) == 0 {
|
|
return inrune
|
|
}
|
|
if len(inrune) != 0 {
|
|
inrune = append(inrune, '_')
|
|
}
|
|
inrune = append(inrune, segment...)
|
|
return inrune
|
|
}
|
|
|
|
// UnderscoreToCamelCase converts from underscore separated form to camel case form.
|
|
// Ex.: my_func => MyFunc
|
|
func UnderscoreToCamelCase(s string) string {
|
|
return strings.Replace(strings.Title(strings.Replace(strings.ToLower(s), "_", " ", -1)), " ", "", -1)
|
|
}
|
|
|
|
// CamelCaseToUnderscore converts from camel case form to underscore separated form.
|
|
// Ex.: MyFunc => my_func
|
|
func CamelCaseToUnderscore(str string) string {
|
|
var output []rune
|
|
var segment []rune
|
|
for _, r := range str {
|
|
|
|
// not treat number as separate segment
|
|
if !unicode.IsLower(r) && string(r) != "_" && !unicode.IsNumber(r) {
|
|
output = addSegment(output, segment)
|
|
segment = nil
|
|
}
|
|
segment = append(segment, unicode.ToLower(r))
|
|
}
|
|
output = addSegment(output, segment)
|
|
return string(output)
|
|
}
|
|
|
|
// Reverse return reversed string
|
|
func Reverse(s string) string {
|
|
r := []rune(s)
|
|
for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
|
|
r[i], r[j] = r[j], r[i]
|
|
}
|
|
return string(r)
|
|
}
|
|
|
|
// GetLines split string by "\n" and return array of lines
|
|
func GetLines(s string) []string {
|
|
return strings.Split(s, "\n")
|
|
}
|
|
|
|
// GetLine return specified line of multiline string
|
|
func GetLine(s string, index int) (string, error) {
|
|
lines := GetLines(s)
|
|
if index < 0 || index >= len(lines) {
|
|
return "", errors.New("line index out of bounds")
|
|
}
|
|
return lines[index], nil
|
|
}
|
|
|
|
// RemoveTags remove all tags from HTML string
|
|
func RemoveTags(s string) string {
|
|
return ReplacePattern(s, "<[^>]*>", "")
|
|
}
|
|
|
|
// SafeFileName return safe string that can be used in file names
|
|
func SafeFileName(str string) string {
|
|
name := strings.ToLower(str)
|
|
name = path.Clean(path.Base(name))
|
|
name = strings.Trim(name, " ")
|
|
separators, err := regexp.Compile(`[ &_=+:]`)
|
|
if err == nil {
|
|
name = separators.ReplaceAllString(name, "-")
|
|
}
|
|
legal, err := regexp.Compile(`[^[:alnum:]-.]`)
|
|
if err == nil {
|
|
name = legal.ReplaceAllString(name, "")
|
|
}
|
|
for strings.Contains(name, "--") {
|
|
name = strings.Replace(name, "--", "-", -1)
|
|
}
|
|
return name
|
|
}
|
|
|
|
// NormalizeEmail canonicalize an email address.
|
|
// The local part of the email address is lowercased for all domains; the hostname is always lowercased and
|
|
// the local part of the email address is always lowercased for hosts that are known to be case-insensitive (currently only GMail).
|
|
// Normalization follows special rules for known providers: currently, GMail addresses have dots removed in the local part and
|
|
// are stripped of tags (e.g. some.one+tag@gmail.com becomes someone@gmail.com) and all @googlemail.com addresses are
|
|
// normalized to @gmail.com.
|
|
func NormalizeEmail(str string) (string, error) {
|
|
if !IsEmail(str) {
|
|
return "", fmt.Errorf("%s is not an email", str)
|
|
}
|
|
parts := strings.Split(str, "@")
|
|
parts[0] = strings.ToLower(parts[0])
|
|
parts[1] = strings.ToLower(parts[1])
|
|
if parts[1] == "gmail.com" || parts[1] == "googlemail.com" {
|
|
parts[1] = "gmail.com"
|
|
parts[0] = strings.Split(ReplacePattern(parts[0], `\.`, ""), "+")[0]
|
|
}
|
|
return strings.Join(parts, "@"), nil
|
|
}
|
|
|
|
// Truncate a string to the closest length without breaking words.
|
|
func Truncate(str string, length int, ending string) string {
|
|
var aftstr, befstr string
|
|
if len(str) > length {
|
|
words := strings.Fields(str)
|
|
before, present := 0, 0
|
|
for i := range words {
|
|
befstr = aftstr
|
|
before = present
|
|
aftstr = aftstr + words[i] + " "
|
|
present = len(aftstr)
|
|
if present > length && i != 0 {
|
|
if (length - before) < (present - length) {
|
|
return Trim(befstr, " /\\.,\"'#!?&@+-") + ending
|
|
}
|
|
return Trim(aftstr, " /\\.,\"'#!?&@+-") + ending
|
|
}
|
|
}
|
|
}
|
|
|
|
return str
|
|
}
|
|
|
|
// PadLeft pad left side of string if size of string is less then indicated pad length
|
|
func PadLeft(str string, padStr string, padLen int) string {
|
|
return buildPadStr(str, padStr, padLen, true, false)
|
|
}
|
|
|
|
// PadRight pad right side of string if size of string is less then indicated pad length
|
|
func PadRight(str string, padStr string, padLen int) string {
|
|
return buildPadStr(str, padStr, padLen, false, true)
|
|
}
|
|
|
|
// PadBoth pad sides of string if size of string is less then indicated pad length
|
|
func PadBoth(str string, padStr string, padLen int) string {
|
|
return buildPadStr(str, padStr, padLen, true, true)
|
|
}
|
|
|
|
// PadString either left, right or both sides, not the padding string can be unicode and more then one
|
|
// character
|
|
func buildPadStr(str string, padStr string, padLen int, padLeft bool, padRight bool) string {
|
|
|
|
// When padded length is less then the current string size
|
|
if padLen < utf8.RuneCountInString(str) {
|
|
return str
|
|
}
|
|
|
|
padLen -= utf8.RuneCountInString(str)
|
|
|
|
targetLen := padLen
|
|
|
|
targetLenLeft := targetLen
|
|
targetLenRight := targetLen
|
|
if padLeft && padRight {
|
|
targetLenLeft = padLen / 2
|
|
targetLenRight = padLen - targetLenLeft
|
|
}
|
|
|
|
strToRepeatLen := utf8.RuneCountInString(padStr)
|
|
|
|
repeatTimes := int(math.Ceil(float64(targetLen) / float64(strToRepeatLen)))
|
|
repeatedString := strings.Repeat(padStr, repeatTimes)
|
|
|
|
leftSide := ""
|
|
if padLeft {
|
|
leftSide = repeatedString[0:targetLenLeft]
|
|
}
|
|
|
|
rightSide := ""
|
|
if padRight {
|
|
rightSide = repeatedString[0:targetLenRight]
|
|
}
|
|
|
|
return leftSide + str + rightSide
|
|
}
|
|
|
|
// TruncatingErrorf removes extra args from fmt.Errorf if not formatted in the str object
|
|
func TruncatingErrorf(str string, args ...interface{}) error {
|
|
n := strings.Count(str, "%s")
|
|
return fmt.Errorf(str, args[:n]...)
|
|
}
|