You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

tool.go 7.7KB

9 years ago
10 years ago
10 years ago
10 years ago
8 years ago
10 years ago
9 years ago
9 years ago
9 years ago
9 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
Add Octicon SVG spritemap (#10107) * Add octicon SVG sprite Signed-off-by: jolheiser <john.olheiser@gmail.com> * Static prefix Signed-off-by: jolheiser <john.olheiser@gmail.com> * SVG for all repo icons Signed-off-by: jolheiser <john.olheiser@gmail.com> * make vendor Signed-off-by: jolheiser <john.olheiser@gmail.com> * Swap out octicons Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move octicons to top of less imports Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix JS Signed-off-by: jolheiser <john.olheiser@gmail.com> * Definitely not a search/replace Signed-off-by: jolheiser <john.olheiser@gmail.com> * Missed regex Signed-off-by: jolheiser <john.olheiser@gmail.com> * Move to more generic calls and webpack Signed-off-by: jolheiser <john.olheiser@gmail.com> * make svg -> make webpack Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove svg-sprite Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Missed a test Signed-off-by: jolheiser <john.olheiser@gmail.com> * Remove svg from makefile Signed-off-by: jolheiser <john.olheiser@gmail.com> * Suggestions Signed-off-by: jolheiser <john.olheiser@gmail.com> * Attempt to fix test Signed-off-by: jolheiser <john.olheiser@gmail.com> * Update tests Signed-off-by: jolheiser <john.olheiser@gmail.com> * Revert timetracking test Signed-off-by: jolheiser <john.olheiser@gmail.com> * Swap .octicon for .svg in less Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add aria-hidden Signed-off-by: jolheiser <john.olheiser@gmail.com> * Replace mega-octicon Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix webpack globbing on Windows Signed-off-by: jolheiser <john.olheiser@gmail.com> * Revert Co-Authored-By: silverwind <me@silverwind.io> * Fix octions from upstream Signed-off-by: jolheiser <john.olheiser@gmail.com> * Fix Vue and missed JS function Signed-off-by: jolheiser <john.olheiser@gmail.com> * Add JS helper and PWA Signed-off-by: jolheiser <john.olheiser@gmail.com> * Preload SVG Signed-off-by: jolheiser <john.olheiser@gmail.com> Co-authored-by: silverwind <me@silverwind.io> Co-authored-by: techknowlogick <matti@mdranta.net>
4 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. // Copyright 2014 The Gogs Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package base
  4. import (
  5. "crypto/md5"
  6. "crypto/sha1"
  7. "crypto/sha256"
  8. "encoding/base64"
  9. "encoding/hex"
  10. "errors"
  11. "fmt"
  12. "os"
  13. "path/filepath"
  14. "runtime"
  15. "strconv"
  16. "strings"
  17. "time"
  18. "unicode"
  19. "unicode/utf8"
  20. "code.gitea.io/gitea/modules/git"
  21. "code.gitea.io/gitea/modules/log"
  22. "code.gitea.io/gitea/modules/setting"
  23. "code.gitea.io/gitea/modules/util"
  24. "github.com/dustin/go-humanize"
  25. )
  26. // EncodeMD5 encodes string to md5 hex value.
  27. func EncodeMD5(str string) string {
  28. m := md5.New()
  29. _, _ = m.Write([]byte(str))
  30. return hex.EncodeToString(m.Sum(nil))
  31. }
  32. // EncodeSha1 string to sha1 hex value.
  33. func EncodeSha1(str string) string {
  34. h := sha1.New()
  35. _, _ = h.Write([]byte(str))
  36. return hex.EncodeToString(h.Sum(nil))
  37. }
  38. // EncodeSha256 string to sha256 hex value.
  39. func EncodeSha256(str string) string {
  40. h := sha256.New()
  41. _, _ = h.Write([]byte(str))
  42. return hex.EncodeToString(h.Sum(nil))
  43. }
  44. // ShortSha is basically just truncating.
  45. // It is DEPRECATED and will be removed in the future.
  46. func ShortSha(sha1 string) string {
  47. return TruncateString(sha1, 10)
  48. }
  49. // BasicAuthDecode decode basic auth string
  50. func BasicAuthDecode(encoded string) (string, string, error) {
  51. s, err := base64.StdEncoding.DecodeString(encoded)
  52. if err != nil {
  53. return "", "", err
  54. }
  55. auth := strings.SplitN(string(s), ":", 2)
  56. if len(auth) != 2 {
  57. return "", "", errors.New("invalid basic authentication")
  58. }
  59. return auth[0], auth[1], nil
  60. }
  61. // BasicAuthEncode encode basic auth string
  62. func BasicAuthEncode(username, password string) string {
  63. return base64.StdEncoding.EncodeToString([]byte(username + ":" + password))
  64. }
  65. // VerifyTimeLimitCode verify time limit code
  66. func VerifyTimeLimitCode(data string, minutes int, code string) bool {
  67. if len(code) <= 18 {
  68. return false
  69. }
  70. // split code
  71. start := code[:12]
  72. lives := code[12:18]
  73. if d, err := strconv.ParseInt(lives, 10, 0); err == nil {
  74. minutes = int(d)
  75. }
  76. // right active code
  77. retCode := CreateTimeLimitCode(data, minutes, start)
  78. if retCode == code && minutes > 0 {
  79. // check time is expired or not
  80. before, _ := time.ParseInLocation("200601021504", start, time.Local)
  81. now := time.Now()
  82. if before.Add(time.Minute*time.Duration(minutes)).Unix() > now.Unix() {
  83. return true
  84. }
  85. }
  86. return false
  87. }
  88. // TimeLimitCodeLength default value for time limit code
  89. const TimeLimitCodeLength = 12 + 6 + 40
  90. // CreateTimeLimitCode create a time limit code
  91. // code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
  92. func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string {
  93. format := "200601021504"
  94. var start, end time.Time
  95. var startStr, endStr string
  96. if startInf == nil {
  97. // Use now time create code
  98. start = time.Now()
  99. startStr = start.Format(format)
  100. } else {
  101. // use start string create code
  102. startStr = startInf.(string)
  103. start, _ = time.ParseInLocation(format, startStr, time.Local)
  104. startStr = start.Format(format)
  105. }
  106. end = start.Add(time.Minute * time.Duration(minutes))
  107. endStr = end.Format(format)
  108. // create sha1 encode string
  109. sh := sha1.New()
  110. _, _ = sh.Write([]byte(fmt.Sprintf("%s%s%s%s%d", data, setting.SecretKey, startStr, endStr, minutes)))
  111. encoded := hex.EncodeToString(sh.Sum(nil))
  112. code := fmt.Sprintf("%s%06d%s", startStr, minutes, encoded)
  113. return code
  114. }
  115. // FileSize calculates the file size and generate user-friendly string.
  116. func FileSize(s int64) string {
  117. return humanize.IBytes(uint64(s))
  118. }
  119. // PrettyNumber produces a string form of the given number in base 10 with
  120. // commas after every three orders of magnitude
  121. func PrettyNumber(i interface{}) string {
  122. return humanize.Comma(util.NumberIntoInt64(i))
  123. }
  124. // Subtract deals with subtraction of all types of number.
  125. func Subtract(left, right interface{}) interface{} {
  126. var rleft, rright int64
  127. var fleft, fright float64
  128. isInt := true
  129. switch v := left.(type) {
  130. case int:
  131. rleft = int64(v)
  132. case int8:
  133. rleft = int64(v)
  134. case int16:
  135. rleft = int64(v)
  136. case int32:
  137. rleft = int64(v)
  138. case int64:
  139. rleft = v
  140. case float32:
  141. fleft = float64(v)
  142. isInt = false
  143. case float64:
  144. fleft = v
  145. isInt = false
  146. }
  147. switch v := right.(type) {
  148. case int:
  149. rright = int64(v)
  150. case int8:
  151. rright = int64(v)
  152. case int16:
  153. rright = int64(v)
  154. case int32:
  155. rright = int64(v)
  156. case int64:
  157. rright = v
  158. case float32:
  159. fright = float64(v)
  160. isInt = false
  161. case float64:
  162. fright = v
  163. isInt = false
  164. }
  165. if isInt {
  166. return rleft - rright
  167. }
  168. return fleft + float64(rleft) - (fright + float64(rright))
  169. }
  170. // EllipsisString returns a truncated short string,
  171. // it appends '...' in the end of the length of string is too large.
  172. func EllipsisString(str string, length int) string {
  173. if length <= 3 {
  174. return "..."
  175. }
  176. if utf8.RuneCountInString(str) <= length {
  177. return str
  178. }
  179. return string([]rune(str)[:length-3]) + "..."
  180. }
  181. // TruncateString returns a truncated string with given limit,
  182. // it returns input string if length is not reached limit.
  183. func TruncateString(str string, limit int) string {
  184. if utf8.RuneCountInString(str) < limit {
  185. return str
  186. }
  187. return string([]rune(str)[:limit])
  188. }
  189. // StringsToInt64s converts a slice of string to a slice of int64.
  190. func StringsToInt64s(strs []string) ([]int64, error) {
  191. ints := make([]int64, len(strs))
  192. for i := range strs {
  193. n, err := strconv.ParseInt(strs[i], 10, 64)
  194. if err != nil {
  195. return ints, err
  196. }
  197. ints[i] = n
  198. }
  199. return ints, nil
  200. }
  201. // Int64sToStrings converts a slice of int64 to a slice of string.
  202. func Int64sToStrings(ints []int64) []string {
  203. strs := make([]string, len(ints))
  204. for i := range ints {
  205. strs[i] = strconv.FormatInt(ints[i], 10)
  206. }
  207. return strs
  208. }
  209. // Int64sContains returns if a int64 in a slice of int64
  210. func Int64sContains(intsSlice []int64, a int64) bool {
  211. for _, c := range intsSlice {
  212. if c == a {
  213. return true
  214. }
  215. }
  216. return false
  217. }
  218. // IsLetter reports whether the rune is a letter (category L).
  219. // https://github.com/golang/go/blob/c3b4918/src/go/scanner/scanner.go#L342
  220. func IsLetter(ch rune) bool {
  221. return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_' || ch >= 0x80 && unicode.IsLetter(ch)
  222. }
  223. // EntryIcon returns the octicon class for displaying files/directories
  224. func EntryIcon(entry *git.TreeEntry) string {
  225. switch {
  226. case entry.IsLink():
  227. te, err := entry.FollowLink()
  228. if err != nil {
  229. log.Debug(err.Error())
  230. return "file-symlink-file"
  231. }
  232. if te.IsDir() {
  233. return "file-submodule"
  234. }
  235. return "file-symlink-file"
  236. case entry.IsDir():
  237. return "file-directory-fill"
  238. case entry.IsSubModule():
  239. return "file-submodule"
  240. }
  241. return "file"
  242. }
  243. // SetupGiteaRoot Sets GITEA_ROOT if it is not already set and returns the value
  244. func SetupGiteaRoot() string {
  245. giteaRoot := os.Getenv("GITEA_ROOT")
  246. if giteaRoot == "" {
  247. _, filename, _, _ := runtime.Caller(0)
  248. giteaRoot = strings.TrimSuffix(filename, "modules/base/tool.go")
  249. wd, err := os.Getwd()
  250. if err != nil {
  251. rel, err := filepath.Rel(giteaRoot, wd)
  252. if err != nil && strings.HasPrefix(filepath.ToSlash(rel), "../") {
  253. giteaRoot = wd
  254. }
  255. }
  256. if _, err := os.Stat(filepath.Join(giteaRoot, "gitea")); os.IsNotExist(err) {
  257. giteaRoot = ""
  258. } else if err := os.Setenv("GITEA_ROOT", giteaRoot); err != nil {
  259. giteaRoot = ""
  260. }
  261. }
  262. return giteaRoot
  263. }
  264. // FormatNumberSI format a number
  265. func FormatNumberSI(data interface{}) string {
  266. var num int64
  267. if num1, ok := data.(int64); ok {
  268. num = num1
  269. } else if num1, ok := data.(int); ok {
  270. num = int64(num1)
  271. } else {
  272. return ""
  273. }
  274. if num < 1000 {
  275. return fmt.Sprintf("%d", num)
  276. } else if num < 1000000 {
  277. num2 := float32(num) / float32(1000.0)
  278. return fmt.Sprintf("%.1fk", num2)
  279. } else if num < 1000000000 {
  280. num2 := float32(num) / float32(1000000.0)
  281. return fmt.Sprintf("%.1fM", num2)
  282. }
  283. num2 := float32(num) / float32(1000000000.0)
  284. return fmt.Sprintf("%.1fG", num2)
  285. }