diff options
Diffstat (limited to 'vendor/github.com/mattermost/mattermost-server/v5/model/utils.go')
-rw-r--r-- | vendor/github.com/mattermost/mattermost-server/v5/model/utils.go | 726 |
1 files changed, 0 insertions, 726 deletions
diff --git a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go b/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go deleted file mode 100644 index 0c5a272c..00000000 --- a/vendor/github.com/mattermost/mattermost-server/v5/model/utils.go +++ /dev/null @@ -1,726 +0,0 @@ -// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. -// See LICENSE.txt for license information. - -package model - -import ( - "bytes" - "crypto/rand" - "encoding/base32" - "encoding/json" - "fmt" - "io" - "io/ioutil" - "net" - "net/http" - "net/mail" - "net/url" - "regexp" - "strconv" - "strings" - "sync" - "time" - "unicode" - - "github.com/mattermost/mattermost-server/v5/shared/i18n" - "github.com/pborman/uuid" -) - -const ( - LOWERCASE_LETTERS = "abcdefghijklmnopqrstuvwxyz" - UPPERCASE_LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" - NUMBERS = "0123456789" - SYMBOLS = " !\"\\#$%&'()*+,-./:;<=>?@[]^_`|~" - MB = 1 << 20 -) - -type StringInterface map[string]interface{} -type StringArray []string - -func (sa StringArray) Remove(input string) StringArray { - for index := range sa { - if sa[index] == input { - ret := make(StringArray, 0, len(sa)-1) - ret = append(ret, sa[:index]...) - return append(ret, sa[index+1:]...) - } - } - return sa -} - -func (sa StringArray) Contains(input string) bool { - for index := range sa { - if sa[index] == input { - return true - } - } - - return false -} -func (sa StringArray) Equals(input StringArray) bool { - - if len(sa) != len(input) { - return false - } - - for index := range sa { - - if sa[index] != input[index] { - return false - } - } - - return true -} - -var translateFunc i18n.TranslateFunc -var translateFuncOnce sync.Once - -func AppErrorInit(t i18n.TranslateFunc) { - translateFuncOnce.Do(func() { - translateFunc = t - }) -} - -type AppError struct { - Id string `json:"id"` - Message string `json:"message"` // Message to be display to the end user without debugging information - DetailedError string `json:"detailed_error"` // Internal error string to help the developer - RequestId string `json:"request_id,omitempty"` // The RequestId that's also set in the header - StatusCode int `json:"status_code,omitempty"` // The http status code - Where string `json:"-"` // The function where it happened in the form of Struct.Func - IsOAuth bool `json:"is_oauth,omitempty"` // Whether the error is OAuth specific - params map[string]interface{} -} - -func (er *AppError) Error() string { - return er.Where + ": " + er.Message + ", " + er.DetailedError -} - -func (er *AppError) Translate(T i18n.TranslateFunc) { - if T == nil { - er.Message = er.Id - return - } - - if er.params == nil { - er.Message = T(er.Id) - } else { - er.Message = T(er.Id, er.params) - } -} - -func (er *AppError) SystemMessage(T i18n.TranslateFunc) string { - if er.params == nil { - return T(er.Id) - } - return T(er.Id, er.params) -} - -func (er *AppError) ToJson() string { - b, _ := json.Marshal(er) - return string(b) -} - -// AppErrorFromJson will decode the input and return an AppError -func AppErrorFromJson(data io.Reader) *AppError { - str := "" - bytes, rerr := ioutil.ReadAll(data) - if rerr != nil { - str = rerr.Error() - } else { - str = string(bytes) - } - - decoder := json.NewDecoder(strings.NewReader(str)) - var er AppError - err := decoder.Decode(&er) - if err != nil { - return NewAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, "body: "+str, http.StatusInternalServerError) - } - return &er -} - -func NewAppError(where string, id string, params map[string]interface{}, details string, status int) *AppError { - ap := &AppError{} - ap.Id = id - ap.params = params - ap.Message = id - ap.Where = where - ap.DetailedError = details - ap.StatusCode = status - ap.IsOAuth = false - ap.Translate(translateFunc) - return ap -} - -var encoding = base32.NewEncoding("ybndrfg8ejkmcpqxot1uwisza345h769") - -// NewId is a globally unique identifier. It is a [A-Z0-9] string 26 -// characters long. It is a UUID version 4 Guid that is zbased32 encoded -// with the padding stripped off. -func NewId() string { - var b bytes.Buffer - encoder := base32.NewEncoder(encoding, &b) - encoder.Write(uuid.NewRandom()) - encoder.Close() - b.Truncate(26) // removes the '==' padding - return b.String() -} - -// NewRandomTeamName is a NewId that will be a valid team name. -func NewRandomTeamName() string { - teamName := NewId() - for IsReservedTeamName(teamName) { - teamName = NewId() - } - return teamName -} - -// NewRandomString returns a random string of the given length. -// The resulting entropy will be (5 * length) bits. -func NewRandomString(length int) string { - data := make([]byte, 1+(length*5/8)) - rand.Read(data) - return encoding.EncodeToString(data)[:length] -} - -// GetMillis is a convenience method to get milliseconds since epoch. -func GetMillis() int64 { - return time.Now().UnixNano() / int64(time.Millisecond) -} - -// GetMillisForTime is a convenience method to get milliseconds since epoch for provided Time. -func GetMillisForTime(thisTime time.Time) int64 { - return thisTime.UnixNano() / int64(time.Millisecond) -} - -// GetTimeForMillis is a convenience method to get time.Time for milliseconds since epoch. -func GetTimeForMillis(millis int64) time.Time { - return time.Unix(0, millis*int64(time.Millisecond)) -} - -// PadDateStringZeros is a convenience method to pad 2 digit date parts with zeros to meet ISO 8601 format -func PadDateStringZeros(dateString string) string { - parts := strings.Split(dateString, "-") - for index, part := range parts { - if len(part) == 1 { - parts[index] = "0" + part - } - } - dateString = strings.Join(parts[:], "-") - return dateString -} - -// GetStartOfDayMillis is a convenience method to get milliseconds since epoch for provided date's start of day -func GetStartOfDayMillis(thisTime time.Time, timeZoneOffset int) int64 { - localSearchTimeZone := time.FixedZone("Local Search Time Zone", timeZoneOffset) - resultTime := time.Date(thisTime.Year(), thisTime.Month(), thisTime.Day(), 0, 0, 0, 0, localSearchTimeZone) - return GetMillisForTime(resultTime) -} - -// GetEndOfDayMillis is a convenience method to get milliseconds since epoch for provided date's end of day -func GetEndOfDayMillis(thisTime time.Time, timeZoneOffset int) int64 { - localSearchTimeZone := time.FixedZone("Local Search Time Zone", timeZoneOffset) - resultTime := time.Date(thisTime.Year(), thisTime.Month(), thisTime.Day(), 23, 59, 59, 999999999, localSearchTimeZone) - return GetMillisForTime(resultTime) -} - -func CopyStringMap(originalMap map[string]string) map[string]string { - copyMap := make(map[string]string) - for k, v := range originalMap { - copyMap[k] = v - } - return copyMap -} - -// MapToJson converts a map to a json string -func MapToJson(objmap map[string]string) string { - b, _ := json.Marshal(objmap) - return string(b) -} - -// MapBoolToJson converts a map to a json string -func MapBoolToJson(objmap map[string]bool) string { - b, _ := json.Marshal(objmap) - return string(b) -} - -// MapFromJson will decode the key/value pair map -func MapFromJson(data io.Reader) map[string]string { - decoder := json.NewDecoder(data) - - var objmap map[string]string - if err := decoder.Decode(&objmap); err != nil { - return make(map[string]string) - } - return objmap -} - -// MapFromJson will decode the key/value pair map -func MapBoolFromJson(data io.Reader) map[string]bool { - decoder := json.NewDecoder(data) - - var objmap map[string]bool - if err := decoder.Decode(&objmap); err != nil { - return make(map[string]bool) - } - return objmap -} - -func ArrayToJson(objmap []string) string { - b, _ := json.Marshal(objmap) - return string(b) -} - -func ArrayFromJson(data io.Reader) []string { - decoder := json.NewDecoder(data) - - var objmap []string - if err := decoder.Decode(&objmap); err != nil { - return make([]string, 0) - } - return objmap -} - -func ArrayFromInterface(data interface{}) []string { - stringArray := []string{} - - dataArray, ok := data.([]interface{}) - if !ok { - return stringArray - } - - for _, v := range dataArray { - if str, ok := v.(string); ok { - stringArray = append(stringArray, str) - } - } - - return stringArray -} - -func StringInterfaceToJson(objmap map[string]interface{}) string { - b, _ := json.Marshal(objmap) - return string(b) -} - -func StringInterfaceFromJson(data io.Reader) map[string]interface{} { - decoder := json.NewDecoder(data) - - var objmap map[string]interface{} - if err := decoder.Decode(&objmap); err != nil { - return make(map[string]interface{}) - } - return objmap -} - -func StringToJson(s string) string { - b, _ := json.Marshal(s) - return string(b) -} - -func StringFromJson(data io.Reader) string { - decoder := json.NewDecoder(data) - - var s string - if err := decoder.Decode(&s); err != nil { - return "" - } - return s -} - -// ToJson serializes an arbitrary data type to JSON, discarding the error. -func ToJson(v interface{}) []byte { - b, _ := json.Marshal(v) - return b -} - -func GetServerIpAddress(iface string) string { - var addrs []net.Addr - if iface == "" { - var err error - addrs, err = net.InterfaceAddrs() - if err != nil { - return "" - } - } else { - interfaces, err := net.Interfaces() - if err != nil { - return "" - } - for _, i := range interfaces { - if i.Name == iface { - addrs, err = i.Addrs() - if err != nil { - return "" - } - break - } - } - } - - for _, addr := range addrs { - - if ip, ok := addr.(*net.IPNet); ok && !ip.IP.IsLoopback() && !ip.IP.IsLinkLocalUnicast() && !ip.IP.IsLinkLocalMulticast() { - if ip.IP.To4() != nil { - return ip.IP.String() - } - } - } - - return "" -} - -func IsLower(s string) bool { - return strings.ToLower(s) == s -} - -func IsValidEmail(email string) bool { - if !IsLower(email) { - return false - } - - if addr, err := mail.ParseAddress(email); err != nil { - return false - } else if addr.Name != "" { - // mail.ParseAddress accepts input of the form "Billy Bob <billy@example.com>" which we don't allow - return false - } - - return true -} - -var reservedName = []string{ - "admin", - "api", - "channel", - "claim", - "error", - "files", - "help", - "landing", - "login", - "mfa", - "oauth", - "plug", - "plugins", - "post", - "signup", -} - -func IsValidChannelIdentifier(s string) bool { - - if !IsValidAlphaNumHyphenUnderscore(s, true) { - return false - } - - if len(s) < CHANNEL_NAME_MIN_LENGTH { - return false - } - - return true -} - -func IsValidAlphaNum(s string) bool { - validAlphaNum := regexp.MustCompile(`^[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+$`) - - return validAlphaNum.MatchString(s) -} - -func IsValidAlphaNumHyphenUnderscore(s string, withFormat bool) bool { - if withFormat { - validAlphaNumHyphenUnderscore := regexp.MustCompile(`^[a-z0-9]+([a-z\-\_0-9]+|(__)?)[a-z0-9]+$`) - return validAlphaNumHyphenUnderscore.MatchString(s) - } - - validSimpleAlphaNumHyphenUnderscore := regexp.MustCompile(`^[a-zA-Z0-9\-_]+$`) - return validSimpleAlphaNumHyphenUnderscore.MatchString(s) -} - -func IsValidAlphaNumHyphenUnderscorePlus(s string) bool { - - validSimpleAlphaNumHyphenUnderscorePlus := regexp.MustCompile(`^[a-zA-Z0-9+_-]+$`) - return validSimpleAlphaNumHyphenUnderscorePlus.MatchString(s) -} - -func Etag(parts ...interface{}) string { - - etag := CurrentVersion - - for _, part := range parts { - etag += fmt.Sprintf(".%v", part) - } - - return etag -} - -var validHashtag = regexp.MustCompile(`^(#\pL[\pL\d\-_.]*[\pL\d])$`) -var puncStart = regexp.MustCompile(`^[^\pL\d\s#]+`) -var hashtagStart = regexp.MustCompile(`^#{2,}`) -var puncEnd = regexp.MustCompile(`[^\pL\d\s]+$`) - -func ParseHashtags(text string) (string, string) { - words := strings.Fields(text) - - hashtagString := "" - plainString := "" - for _, word := range words { - // trim off surrounding punctuation - word = puncStart.ReplaceAllString(word, "") - word = puncEnd.ReplaceAllString(word, "") - - // and remove extra pound #s - word = hashtagStart.ReplaceAllString(word, "#") - - if validHashtag.MatchString(word) { - hashtagString += " " + word - } else { - plainString += " " + word - } - } - - if len(hashtagString) > 1000 { - hashtagString = hashtagString[:999] - lastSpace := strings.LastIndex(hashtagString, " ") - if lastSpace > -1 { - hashtagString = hashtagString[:lastSpace] - } else { - hashtagString = "" - } - } - - return strings.TrimSpace(hashtagString), strings.TrimSpace(plainString) -} - -func ClearMentionTags(post string) string { - post = strings.Replace(post, "<mention>", "", -1) - post = strings.Replace(post, "</mention>", "", -1) - return post -} - -func IsValidHttpUrl(rawUrl string) bool { - if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 { - return false - } - - if u, err := url.ParseRequestURI(rawUrl); err != nil || u.Scheme == "" || u.Host == "" { - return false - } - - return true -} - -func IsValidTurnOrStunServer(rawUri string) bool { - if strings.Index(rawUri, "turn:") != 0 && strings.Index(rawUri, "stun:") != 0 { - return false - } - - if _, err := url.ParseRequestURI(rawUri); err != nil { - return false - } - - return true -} - -func IsSafeLink(link *string) bool { - if link != nil { - if IsValidHttpUrl(*link) { - return true - } else if strings.HasPrefix(*link, "/") { - return true - } else { - return false - } - } - - return true -} - -func IsValidWebsocketUrl(rawUrl string) bool { - if strings.Index(rawUrl, "ws://") != 0 && strings.Index(rawUrl, "wss://") != 0 { - return false - } - - if _, err := url.ParseRequestURI(rawUrl); err != nil { - return false - } - - return true -} - -func IsValidTrueOrFalseString(value string) bool { - return value == "true" || value == "false" -} - -func IsValidNumberString(value string) bool { - if _, err := strconv.Atoi(value); err != nil { - return false - } - - return true -} - -func IsValidId(value string) bool { - if len(value) != 26 { - return false - } - - for _, r := range value { - if !unicode.IsLetter(r) && !unicode.IsNumber(r) { - return false - } - } - - return true -} - -// Copied from https://golang.org/src/net/dnsclient.go#L119 -func IsDomainName(s string) bool { - // See RFC 1035, RFC 3696. - // Presentation format has dots before every label except the first, and the - // terminal empty label is optional here because we assume fully-qualified - // (absolute) input. We must therefore reserve space for the first and last - // labels' length octets in wire format, where they are necessary and the - // maximum total length is 255. - // So our _effective_ maximum is 253, but 254 is not rejected if the last - // character is a dot. - l := len(s) - if l == 0 || l > 254 || l == 254 && s[l-1] != '.' { - return false - } - - last := byte('.') - ok := false // Ok once we've seen a letter. - partlen := 0 - for i := 0; i < len(s); i++ { - c := s[i] - switch { - default: - return false - case 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || c == '_': - ok = true - partlen++ - case '0' <= c && c <= '9': - // fine - partlen++ - case c == '-': - // Byte before dash cannot be dot. - if last == '.' { - return false - } - partlen++ - case c == '.': - // Byte before dot cannot be dot, dash. - if last == '.' || last == '-' { - return false - } - if partlen > 63 || partlen == 0 { - return false - } - partlen = 0 - } - last = c - } - if last == '-' || partlen > 63 { - return false - } - - return ok -} - -func RemoveDuplicateStrings(in []string) []string { - out := []string{} - seen := make(map[string]bool, len(in)) - - for _, item := range in { - if !seen[item] { - out = append(out, item) - - seen[item] = true - } - } - - return out -} - -func GetPreferredTimezone(timezone StringMap) string { - if timezone["useAutomaticTimezone"] == "true" { - return timezone["automaticTimezone"] - } - - return timezone["manualTimezone"] -} - -// IsSamlFile checks if filename is a SAML file. -func IsSamlFile(saml *SamlSettings, filename string) bool { - return filename == *saml.PublicCertificateFile || filename == *saml.PrivateKeyFile || filename == *saml.IdpCertificateFile -} - -func AsStringBoolMap(list []string) map[string]bool { - listMap := map[string]bool{} - for _, p := range list { - listMap[p] = true - } - return listMap -} - -// SanitizeUnicode will remove undesirable Unicode characters from a string. -func SanitizeUnicode(s string) string { - return strings.Map(filterBlocklist, s) -} - -// filterBlocklist returns `r` if it is not in the blocklist, otherwise drop (-1). -// Blocklist is taken from https://www.w3.org/TR/unicode-xml/#Charlist -func filterBlocklist(r rune) rune { - const drop = -1 - switch r { - case '\u0340', '\u0341': // clones of grave and acute; deprecated in Unicode - return drop - case '\u17A3', '\u17D3': // obsolete characters for Khmer; deprecated in Unicode - return drop - case '\u2028', '\u2029': // line and paragraph separator - return drop - case '\u202A', '\u202B', '\u202C', '\u202D', '\u202E': // BIDI embedding controls - return drop - case '\u206A', '\u206B': // activate/inhibit symmetric swapping; deprecated in Unicode - return drop - case '\u206C', '\u206D': // activate/inhibit Arabic form shaping; deprecated in Unicode - return drop - case '\u206E', '\u206F': // activate/inhibit national digit shapes; deprecated in Unicode - return drop - case '\uFFF9', '\uFFFA', '\uFFFB': // interlinear annotation characters - return drop - case '\uFEFF': // byte order mark - return drop - case '\uFFFC': // object replacement character - return drop - } - - // Scoping for musical notation - if r >= 0x0001D173 && r <= 0x0001D17A { - return drop - } - - // Language tag code points - if r >= 0x000E0000 && r <= 0x000E007F { - return drop - } - - return r -} - -// UniqueStrings returns a unique subset of the string slice provided. -func UniqueStrings(input []string) []string { - u := make([]string, 0, len(input)) - m := make(map[string]bool) - - for _, val := range input { - if _, ok := m[val]; !ok { - m[val] = true - u = append(u, val) - } - } - - return u -} |