mccl/pkg/util/util.go

146 lines
3.0 KiB
Go
Executable File

package util
import (
"crypto/md5"
"crypto/sha1"
"encoding/base64"
"encoding/hex"
"fmt"
"hash"
"io"
"net/http"
"os"
"path"
"runtime"
"strings"
)
type File struct {
Id string `json:"id"`
Sha1 string `json:"sha1"`
Size int64 `json:"size"`
Url string `json:"url"`
Path string `json:"path"`
}
func (f File) Retrieve() ([]byte, error) {
return GetFromUrl(f.Url, f.Sha1, "sha1", f.Size)
}
func (f *File) GetName() string {
if f.Id == "" {
return f.Path
}
return f.Id
}
func GetFromUrl(url string, hash, hashType string, fSize int64) ([]byte, error) {
resp, err := http.Get(url)
if err != nil {
return nil, err
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("status code returned is %d", resp.StatusCode)
}
if fSize != -1 && resp.ContentLength != -1 && resp.ContentLength != fSize {
return nil, fmt.Errorf("response size mismatch. %d != %d", resp.ContentLength, fSize)
}
data, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
if fSize != -1 && len(data) != int(fSize) {
return nil, fmt.Errorf("body size mismatch. %d != %d", len(data), fSize)
}
if hash != "" {
if err := CheckHash(data, hash, hashType); err != nil {
return nil, err
}
}
return data, nil
}
func IsFileExist(path string) bool {
_, err := os.Stat(path)
return err == nil
}
func WriteFile(fPath string, data []byte) error {
if err := os.MkdirAll(path.Dir(fPath), 0777); err != nil {
return err
}
if err := os.WriteFile(fPath, data, 0666); err != nil {
return err
}
return nil
}
func ReadFile(fPath string) ([]byte, error) {
if !IsFileExist(fPath) {
return nil, fmt.Errorf("File %s not found", fPath)
}
data, err := os.ReadFile(fPath)
if err != nil {
return nil, err
}
return data, nil
}
// LoadOrDownloadFile will check if file exists and correct, will download it otherwise.
func LoadOrDownloadFile(fPath, url string, hash, hashType string, fSize int64) ([]byte, error) {
if IsFileExist(fPath) {
data, err := os.ReadFile(fPath)
if err != nil {
return nil, err
}
if hash != "" {
if err := CheckHash(data, hash, hashType); err != nil {
return nil, err
}
}
return data, nil
}
return GetFromUrl(url, hash, hashType, fSize)
}
func CheckHash(data []byte, fHash, hashType string) error {
var hasher hash.Hash
switch hashType {
case "sha1":
hasher = sha1.New()
case "md5":
hasher = md5.New()
default:
return fmt.Errorf("unsupported hash type %s", hashType)
}
if _, err := hasher.Write(data); err != nil {
return err
}
resultedHash := hasher.Sum(nil)
if (strings.Contains(fHash, "=") && base64.StdEncoding.EncodeToString(resultedHash) == fHash) ||
hex.EncodeToString(resultedHash) == fHash {
return nil
}
return fmt.Errorf("hash mismatch: %s != %s", hex.EncodeToString(resultedHash), fHash)
}
func PathSeparator() string {
if runtime.GOOS == "windows" {
return ";"
}
return ":"
}