146 lines
3.0 KiB
Go
Executable File
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 ":"
|
|
}
|