2014-02-19 02:31:16 +04:00
// Copyright 2014 The Gogs Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2014-02-19 02:31:16 +04:00
2014-03-08 02:22:15 +04:00
package base
2014-02-19 02:31:16 +04:00
import (
2014-03-19 15:21:23 +04:00
"crypto/sha1"
2024-02-25 16:32:13 +03:00
"crypto/sha256"
2014-11-07 22:46:13 +03:00
"encoding/base64"
2014-02-19 02:31:16 +04:00
"encoding/hex"
2020-12-18 04:51:28 +03:00
"errors"
2014-03-14 10:32:11 +04:00
"fmt"
2019-04-17 19:06:35 +03:00
"os"
"path/filepath"
"runtime"
2016-11-07 23:49:50 +03:00
"strconv"
2014-03-15 11:28:06 +04:00
"strings"
2014-03-14 10:32:11 +04:00
"time"
2021-05-13 10:50:57 +03:00
"unicode/utf8"
2014-05-26 04:11:25 +04:00
2019-03-27 12:33:00 +03:00
"code.gitea.io/gitea/modules/git"
2016-11-10 19:24:48 +03:00
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
2019-03-27 12:33:00 +03:00
2020-02-03 22:50:37 +03:00
"github.com/dustin/go-humanize"
2014-02-19 02:31:16 +04:00
)
2016-11-24 10:17:44 +03:00
// EncodeSha1 string to sha1 hex value.
2014-11-12 14:48:50 +03:00
func EncodeSha1 ( str string ) string {
h := sha1 . New ( )
2019-06-12 22:41:28 +03:00
_ , _ = h . Write ( [ ] byte ( str ) )
2014-11-12 14:48:50 +03:00
return hex . EncodeToString ( h . Sum ( nil ) )
}
2022-11-26 19:21:54 +03:00
// EncodeSha256 string to sha256 hex value.
2019-05-04 18:45:34 +03:00
func EncodeSha256 ( str string ) string {
h := sha256 . New ( )
2019-06-12 22:41:28 +03:00
_ , _ = h . Write ( [ ] byte ( str ) )
2019-05-04 18:45:34 +03:00
return hex . EncodeToString ( h . Sum ( nil ) )
}
2016-11-08 01:14:50 +03:00
// ShortSha is basically just truncating.
// It is DEPRECATED and will be removed in the future.
2015-11-14 01:10:25 +03:00
func ShortSha ( sha1 string ) string {
2016-11-07 23:36:01 +03:00
return TruncateString ( sha1 , 10 )
2015-11-14 01:10:25 +03:00
}
2016-11-24 10:17:44 +03:00
// BasicAuthDecode decode basic auth string
2014-12-10 13:10:26 +03:00
func BasicAuthDecode ( encoded string ) ( string , string , error ) {
s , err := base64 . StdEncoding . DecodeString ( encoded )
2014-11-07 22:46:13 +03:00
if err != nil {
2014-12-10 13:10:26 +03:00
return "" , "" , err
2014-11-07 22:46:13 +03:00
}
2014-12-10 13:01:17 +03:00
auth := strings . SplitN ( string ( s ) , ":" , 2 )
2020-12-18 04:51:28 +03:00
if len ( auth ) != 2 {
return "" , "" , errors . New ( "invalid basic authentication" )
}
2014-12-10 13:10:26 +03:00
return auth [ 0 ] , auth [ 1 ] , nil
2014-11-07 22:46:13 +03:00
}
2016-11-24 10:17:44 +03:00
// VerifyTimeLimitCode verify time limit code
2014-03-19 20:50:44 +04:00
func VerifyTimeLimitCode ( data string , minutes int , code string ) bool {
if len ( code ) <= 18 {
return false
}
// split code
start := code [ : 12 ]
lives := code [ 12 : 18 ]
2020-12-25 12:59:32 +03:00
if d , err := strconv . ParseInt ( lives , 10 , 0 ) ; err == nil {
minutes = int ( d )
2014-03-19 20:50:44 +04:00
}
// right active code
retCode := CreateTimeLimitCode ( data , minutes , start )
if retCode == code && minutes > 0 {
// check time is expired or not
2015-02-16 15:44:27 +03:00
before , _ := time . ParseInLocation ( "200601021504" , start , time . Local )
2014-03-19 20:50:44 +04:00
now := time . Now ( )
if before . Add ( time . Minute * time . Duration ( minutes ) ) . Unix ( ) > now . Unix ( ) {
return true
}
}
return false
}
2016-11-24 10:17:44 +03:00
// TimeLimitCodeLength default value for time limit code
2014-03-19 20:50:44 +04:00
const TimeLimitCodeLength = 12 + 6 + 40
2016-11-24 10:17:44 +03:00
// CreateTimeLimitCode create a time limit code
2014-03-19 15:21:23 +04:00
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
2023-07-04 21:36:08 +03:00
func CreateTimeLimitCode ( data string , minutes int , startInf any ) string {
2015-02-16 15:44:27 +03:00
format := "200601021504"
2014-03-19 15:21:23 +04:00
var start , end time . Time
var startStr , endStr string
if startInf == nil {
// Use now time create code
start = time . Now ( )
2015-02-16 15:44:27 +03:00
startStr = start . Format ( format )
2014-03-19 15:21:23 +04:00
} else {
// use start string create code
startStr = startInf . ( string )
2015-02-16 15:44:27 +03:00
start , _ = time . ParseInLocation ( format , startStr , time . Local )
startStr = start . Format ( format )
2014-03-19 15:21:23 +04:00
}
end = start . Add ( time . Minute * time . Duration ( minutes ) )
2015-02-16 15:44:27 +03:00
endStr = end . Format ( format )
2014-03-19 15:21:23 +04:00
// create sha1 encode string
sh := sha1 . New ( )
2024-02-18 20:39:04 +03:00
_ , _ = sh . Write ( [ ] byte ( fmt . Sprintf ( "%s%s%s%s%d" , data , hex . EncodeToString ( setting . GetGeneralTokenSigningSecret ( ) ) , startStr , endStr , minutes ) ) )
2014-03-19 15:21:23 +04:00
encoded := hex . EncodeToString ( sh . Sum ( nil ) )
code := fmt . Sprintf ( "%s%06d%s" , startStr , minutes , encoded )
return code
}
2014-03-15 20:29:49 +04:00
// FileSize calculates the file size and generate user-friendly string.
2014-03-15 20:31:12 +04:00
func FileSize ( s int64 ) string {
2020-02-03 22:50:37 +03:00
return humanize . IBytes ( uint64 ( s ) )
}
2016-01-11 15:41:43 +03:00
// EllipsisString returns a truncated short string,
// it appends '...' in the end of the length of string is too large.
func EllipsisString ( str string , length int ) string {
2016-11-07 23:27:14 +03:00
if length <= 3 {
return "..."
}
2021-05-13 10:50:57 +03:00
if utf8 . RuneCountInString ( str ) <= length {
2016-01-11 15:41:43 +03:00
return str
}
2021-05-13 10:50:57 +03:00
return string ( [ ] rune ( str ) [ : length - 3 ] ) + "..."
2016-01-11 15:41:43 +03:00
}
2016-03-05 08:51:51 +03:00
// TruncateString returns a truncated string with given limit,
// it returns input string if length is not reached limit.
func TruncateString ( str string , limit int ) string {
2021-05-13 10:50:57 +03:00
if utf8 . RuneCountInString ( str ) < limit {
2016-03-05 08:51:51 +03:00
return str
}
2021-05-13 10:50:57 +03:00
return string ( [ ] rune ( str ) [ : limit ] )
2016-03-05 08:51:51 +03:00
}
2015-08-10 11:52:08 +03:00
// StringsToInt64s converts a slice of string to a slice of int64.
2016-12-22 11:58:04 +03:00
func StringsToInt64s ( strs [ ] string ) ( [ ] int64 , error ) {
2024-03-21 18:07:35 +03:00
if strs == nil {
return nil , nil
}
ints := make ( [ ] int64 , 0 , len ( strs ) )
for _ , s := range strs {
n , err := strconv . ParseInt ( s , 10 , 64 )
2016-12-22 11:58:04 +03:00
if err != nil {
2024-03-21 18:07:35 +03:00
return nil , err
2016-12-22 11:58:04 +03:00
}
2024-03-21 18:07:35 +03:00
ints = append ( ints , n )
2015-08-10 11:52:08 +03:00
}
2016-12-22 11:58:04 +03:00
return ints , nil
2015-08-10 11:52:08 +03:00
}
2015-08-25 18:22:05 +03:00
// Int64sToStrings converts a slice of int64 to a slice of string.
func Int64sToStrings ( ints [ ] int64 ) [ ] string {
strs := make ( [ ] string , len ( ints ) )
for i := range ints {
2016-11-07 23:49:50 +03:00
strs [ i ] = strconv . FormatInt ( ints [ i ] , 10 )
2015-08-25 18:22:05 +03:00
}
return strs
}
2018-05-01 10:04:36 +03:00
// EntryIcon returns the octicon class for displaying files/directories
func EntryIcon ( entry * git . TreeEntry ) string {
switch {
case entry . IsLink ( ) :
te , err := entry . FollowLink ( )
if err != nil {
log . Debug ( err . Error ( ) )
return "file-symlink-file"
}
if te . IsDir ( ) {
2023-06-23 01:05:52 +03:00
return "file-directory-symlink"
2018-05-01 10:04:36 +03:00
}
return "file-symlink-file"
case entry . IsDir ( ) :
2022-04-01 03:15:46 +03:00
return "file-directory-fill"
2018-05-01 10:04:36 +03:00
case entry . IsSubModule ( ) :
return "file-submodule"
}
2020-02-11 20:02:41 +03:00
return "file"
2018-05-01 10:04:36 +03:00
}
2019-04-17 19:06:35 +03:00
// SetupGiteaRoot Sets GITEA_ROOT if it is not already set and returns the value
func SetupGiteaRoot ( ) string {
giteaRoot := os . Getenv ( "GITEA_ROOT" )
if giteaRoot == "" {
_ , filename , _ , _ := runtime . Caller ( 0 )
giteaRoot = strings . TrimSuffix ( filename , "modules/base/tool.go" )
wd , err := os . Getwd ( )
if err != nil {
rel , err := filepath . Rel ( giteaRoot , wd )
if err != nil && strings . HasPrefix ( filepath . ToSlash ( rel ) , "../" ) {
giteaRoot = wd
}
}
if _ , err := os . Stat ( filepath . Join ( giteaRoot , "gitea" ) ) ; os . IsNotExist ( err ) {
giteaRoot = ""
} else if err := os . Setenv ( "GITEA_ROOT" , giteaRoot ) ; err != nil {
giteaRoot = ""
}
}
return giteaRoot
}
2020-09-16 07:07:18 +03:00
// FormatNumberSI format a number
2023-07-04 21:36:08 +03:00
func FormatNumberSI ( data any ) string {
2020-09-16 07:07:18 +03:00
var num int64
if num1 , ok := data . ( int64 ) ; ok {
num = num1
} else if num1 , ok := data . ( int ) ; ok {
num = int64 ( num1 )
} else {
return ""
}
if num < 1000 {
return fmt . Sprintf ( "%d" , num )
} else if num < 1000000 {
num2 := float32 ( num ) / float32 ( 1000.0 )
return fmt . Sprintf ( "%.1fk" , num2 )
} else if num < 1000000000 {
num2 := float32 ( num ) / float32 ( 1000000.0 )
return fmt . Sprintf ( "%.1fM" , num2 )
}
num2 := float32 ( num ) / float32 ( 1000000000.0 )
return fmt . Sprintf ( "%.1fG" , num2 )
}