PageRenderTime 100ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/model/utils.go

https://gitlab.com/Realtyka/platform
Go | 368 lines | 292 code | 65 blank | 11 comment | 63 complexity | e7248c47df9eaf25cc480d2c7a0ece1a MD5 | raw file
  1. // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
  2. // See License.txt for license information.
  3. package model
  4. import (
  5. "bytes"
  6. "crypto/rand"
  7. "encoding/base32"
  8. "encoding/json"
  9. "fmt"
  10. "io"
  11. "net/mail"
  12. "net/url"
  13. "regexp"
  14. "strings"
  15. "time"
  16. goi18n "github.com/nicksnyder/go-i18n/i18n"
  17. "github.com/pborman/uuid"
  18. )
  19. type StringInterface map[string]interface{}
  20. type StringMap map[string]string
  21. type StringArray []string
  22. type EncryptStringMap map[string]string
  23. type AppError struct {
  24. Id string `json:"id"`
  25. Message string `json:"message"` // Message to be display to the end user without debugging information
  26. DetailedError string `json:"detailed_error"` // Internal error string to help the developer
  27. RequestId string `json:"request_id"` // The RequestId that's also set in the header
  28. StatusCode int `json:"status_code"` // The http status code
  29. Where string `json:"-"` // The function where it happened in the form of Struct.Func
  30. IsOAuth bool `json:"is_oauth"` // Whether the error is OAuth specific
  31. params map[string]interface{} `json:"-"`
  32. }
  33. func (er *AppError) Error() string {
  34. return er.Where + ": " + er.Message + ", " + er.DetailedError
  35. }
  36. func (er *AppError) Translate(T goi18n.TranslateFunc) {
  37. if len(er.Message) == 0 {
  38. if er.params == nil {
  39. er.Message = T(er.Id)
  40. } else {
  41. er.Message = T(er.Id, er.params)
  42. }
  43. }
  44. }
  45. func (er *AppError) ToJson() string {
  46. b, err := json.Marshal(er)
  47. if err != nil {
  48. return ""
  49. } else {
  50. return string(b)
  51. }
  52. }
  53. // AppErrorFromJson will decode the input and return an AppError
  54. func AppErrorFromJson(data io.Reader) *AppError {
  55. decoder := json.NewDecoder(data)
  56. var er AppError
  57. err := decoder.Decode(&er)
  58. if err == nil {
  59. return &er
  60. } else {
  61. return NewLocAppError("AppErrorFromJson", "model.utils.decode_json.app_error", nil, err.Error())
  62. }
  63. }
  64. func NewLocAppError(where string, id string, params map[string]interface{}, details string) *AppError {
  65. ap := &AppError{}
  66. ap.Id = id
  67. ap.params = params
  68. ap.Where = where
  69. ap.DetailedError = details
  70. ap.StatusCode = 500
  71. ap.IsOAuth = false
  72. return ap
  73. }
  74. var encoding = base32.NewEncoding("ybndrfg8ejkmcpqxot1uwisza345h769")
  75. // NewId is a globally unique identifier. It is a [A-Z0-9] string 26
  76. // characters long. It is a UUID version 4 Guid that is zbased32 encoded
  77. // with the padding stripped off.
  78. func NewId() string {
  79. var b bytes.Buffer
  80. encoder := base32.NewEncoder(encoding, &b)
  81. encoder.Write(uuid.NewRandom())
  82. encoder.Close()
  83. b.Truncate(26) // removes the '==' padding
  84. return b.String()
  85. }
  86. func NewRandomString(length int) string {
  87. var b bytes.Buffer
  88. str := make([]byte, length+8)
  89. rand.Read(str)
  90. encoder := base32.NewEncoder(encoding, &b)
  91. encoder.Write(str)
  92. encoder.Close()
  93. b.Truncate(length) // removes the '==' padding
  94. return b.String()
  95. }
  96. // GetMillis is a convience method to get milliseconds since epoch.
  97. func GetMillis() int64 {
  98. return time.Now().UnixNano() / int64(time.Millisecond)
  99. }
  100. // MapToJson converts a map to a json string
  101. func MapToJson(objmap map[string]string) string {
  102. if b, err := json.Marshal(objmap); err != nil {
  103. return ""
  104. } else {
  105. return string(b)
  106. }
  107. }
  108. // MapFromJson will decode the key/value pair map
  109. func MapFromJson(data io.Reader) map[string]string {
  110. decoder := json.NewDecoder(data)
  111. var objmap map[string]string
  112. if err := decoder.Decode(&objmap); err != nil {
  113. return make(map[string]string)
  114. } else {
  115. return objmap
  116. }
  117. }
  118. func ArrayToJson(objmap []string) string {
  119. if b, err := json.Marshal(objmap); err != nil {
  120. return ""
  121. } else {
  122. return string(b)
  123. }
  124. }
  125. func ArrayFromJson(data io.Reader) []string {
  126. decoder := json.NewDecoder(data)
  127. var objmap []string
  128. if err := decoder.Decode(&objmap); err != nil {
  129. return make([]string, 0)
  130. } else {
  131. return objmap
  132. }
  133. }
  134. func StringInterfaceToJson(objmap map[string]interface{}) string {
  135. if b, err := json.Marshal(objmap); err != nil {
  136. return ""
  137. } else {
  138. return string(b)
  139. }
  140. }
  141. func StringInterfaceFromJson(data io.Reader) map[string]interface{} {
  142. decoder := json.NewDecoder(data)
  143. var objmap map[string]interface{}
  144. if err := decoder.Decode(&objmap); err != nil {
  145. return make(map[string]interface{})
  146. } else {
  147. return objmap
  148. }
  149. }
  150. func IsLower(s string) bool {
  151. if strings.ToLower(s) == s {
  152. return true
  153. }
  154. return false
  155. }
  156. func IsValidEmail(email string) bool {
  157. if !IsLower(email) {
  158. return false
  159. }
  160. if _, err := mail.ParseAddress(email); err == nil {
  161. return true
  162. }
  163. return false
  164. }
  165. var reservedName = []string{
  166. "www",
  167. "web",
  168. "admin",
  169. "support",
  170. "notify",
  171. "test",
  172. "demo",
  173. "mail",
  174. "team",
  175. "channel",
  176. "internal",
  177. "localhost",
  178. "dockerhost",
  179. "stag",
  180. "post",
  181. "cluster",
  182. "api",
  183. "oauth",
  184. }
  185. var wwwStart = regexp.MustCompile(`^www`)
  186. var betaStart = regexp.MustCompile(`^beta`)
  187. var ciStart = regexp.MustCompile(`^ci`)
  188. func GetSubDomain(s string) (string, string) {
  189. s = strings.Replace(s, "http://", "", 1)
  190. s = strings.Replace(s, "https://", "", 1)
  191. match := wwwStart.MatchString(s)
  192. if match {
  193. return "", ""
  194. }
  195. match = betaStart.MatchString(s)
  196. if match {
  197. return "", ""
  198. }
  199. match = ciStart.MatchString(s)
  200. if match {
  201. return "", ""
  202. }
  203. parts := strings.Split(s, ".")
  204. if len(parts) != 3 {
  205. return "", ""
  206. }
  207. return parts[0], parts[1]
  208. }
  209. func IsValidChannelIdentifier(s string) bool {
  210. if !IsValidAlphaNum(s, true) {
  211. return false
  212. }
  213. if len(s) < 2 {
  214. return false
  215. }
  216. return true
  217. }
  218. var validAlphaNumUnderscore = regexp.MustCompile(`^[a-z0-9]+([a-z\-\_0-9]+|(__)?)[a-z0-9]+$`)
  219. var validAlphaNum = regexp.MustCompile(`^[a-z0-9]+([a-z\-0-9]+|(__)?)[a-z0-9]+$`)
  220. func IsValidAlphaNum(s string, allowUnderscores bool) bool {
  221. var match bool
  222. if allowUnderscores {
  223. match = validAlphaNumUnderscore.MatchString(s)
  224. } else {
  225. match = validAlphaNum.MatchString(s)
  226. }
  227. if !match {
  228. return false
  229. }
  230. return true
  231. }
  232. func Etag(parts ...interface{}) string {
  233. etag := CurrentVersion
  234. for _, part := range parts {
  235. etag += fmt.Sprintf(".%v", part)
  236. }
  237. return etag
  238. }
  239. var validHashtag = regexp.MustCompile(`^(#[A-Za-zäöüÄÖÜß]+[A-Za-z0-9äöüÄÖÜß_\-]*[A-Za-z0-9äöüÄÖÜß])$`)
  240. var puncStart = regexp.MustCompile(`^[.,()&$!\?\[\]{}':;\\<>\-+=%^*|]+`)
  241. var hashtagStart = regexp.MustCompile(`^#{2,}`)
  242. var puncEnd = regexp.MustCompile(`[.,()&$#!\?\[\]{}':;\\<>\-+=%^*|]+$`)
  243. func ParseHashtags(text string) (string, string) {
  244. words := strings.Fields(text)
  245. hashtagString := ""
  246. plainString := ""
  247. for _, word := range words {
  248. // trim off surrounding punctuation
  249. word = puncStart.ReplaceAllString(word, "")
  250. word = puncEnd.ReplaceAllString(word, "")
  251. // and remove extra pound #s
  252. word = hashtagStart.ReplaceAllString(word, "#")
  253. if validHashtag.MatchString(word) {
  254. hashtagString += " " + word
  255. } else {
  256. plainString += " " + word
  257. }
  258. }
  259. if len(hashtagString) > 1000 {
  260. hashtagString = hashtagString[:999]
  261. lastSpace := strings.LastIndex(hashtagString, " ")
  262. if lastSpace > -1 {
  263. hashtagString = hashtagString[:lastSpace]
  264. } else {
  265. hashtagString = ""
  266. }
  267. }
  268. return strings.TrimSpace(hashtagString), strings.TrimSpace(plainString)
  269. }
  270. func IsFileExtImage(ext string) bool {
  271. ext = strings.ToLower(ext)
  272. for _, imgExt := range IMAGE_EXTENSIONS {
  273. if ext == imgExt {
  274. return true
  275. }
  276. }
  277. return false
  278. }
  279. func GetImageMimeType(ext string) string {
  280. ext = strings.ToLower(ext)
  281. if len(IMAGE_MIME_TYPES[ext]) == 0 {
  282. return "image"
  283. } else {
  284. return IMAGE_MIME_TYPES[ext]
  285. }
  286. }
  287. func ClearMentionTags(post string) string {
  288. post = strings.Replace(post, "<mention>", "", -1)
  289. post = strings.Replace(post, "</mention>", "", -1)
  290. return post
  291. }
  292. var UrlRegex = regexp.MustCompile(`^((?:[a-z]+:\/\/)?(?:(?:[a-z0-9\-]+\.)+(?:[a-z]{2}|aero|arpa|biz|com|coop|edu|gov|info|int|jobs|mil|museum|name|nato|net|org|pro|travel|local|internal))(:[0-9]{1,5})?(?:\/[a-z0-9_\-\.~]+)*(\/([a-z0-9_\-\.]*)(?:\?[a-z0-9+_~\-\.%=&amp;]*)?)?(?:#[a-zA-Z0-9!$&'()*+.=-_~:@/?]*)?)(?:\s+|$)$`)
  293. var PartialUrlRegex = regexp.MustCompile(`/([A-Za-z0-9]{26})/([A-Za-z0-9]{26})/((?:[A-Za-z0-9]{26})?.+(?:\.[A-Za-z0-9]{3,})?)`)
  294. var SplitRunes = map[rune]bool{',': true, ' ': true, '.': true, '!': true, '?': true, ':': true, ';': true, '\n': true, '<': true, '>': true, '(': true, ')': true, '{': true, '}': true, '[': true, ']': true, '+': true, '/': true, '\\': true}
  295. func IsValidHttpUrl(rawUrl string) bool {
  296. if strings.Index(rawUrl, "http://") != 0 && strings.Index(rawUrl, "https://") != 0 {
  297. return false
  298. }
  299. if _, err := url.ParseRequestURI(rawUrl); err != nil {
  300. return false
  301. }
  302. return true
  303. }