Implement pack importing/exporting for downloaded Curseforge packs

Abstract out hash implementations
Implement file saving/downloading
This commit is contained in:
comp500
2019-11-12 22:11:40 +00:00
parent 73f6184b3d
commit 5dfe23e51d
12 changed files with 749 additions and 297 deletions

23
core/hash.go Normal file
View File

@@ -0,0 +1,23 @@
package core
import (
"crypto/md5"
"crypto/sha256"
"crypto/sha512"
"errors"
"hash"
)
// GetHashImpl gets an implementation of hash.Hash for the given hash type string
func GetHashImpl(hashType string) (hash.Hash, error) {
switch hashType {
case "sha256":
return sha256.New(), nil
case "sha512":
return sha512.New(), nil
case "md5":
return md5.New(), nil
}
// TODO: implement murmur2
return nil, errors.New("hash implementation not found")
}

View File

@@ -1,8 +1,8 @@
package core
import (
"crypto/sha256"
"encoding/hex"
"errors"
"io"
"os"
"path/filepath"
@@ -130,7 +130,10 @@ func (in *Index) updateFile(path string) error {
// Hash usage strategy (may change):
// Just use SHA256, overwrite existing hash regardless of what it is
// May update later to continue using the same hash that was already being used
h := sha256.New()
h, err := GetHashImpl("sha256")
if err != nil {
return err
}
if _, err := io.Copy(h, f); err != nil {
return err
}
@@ -310,3 +313,37 @@ func (in Index) GetAllMods() []string {
}
return list
}
// GetFilePath attempts to get the path of the destination index file as it is stored on disk
func (in Index) GetFilePath(f IndexFile) string {
return filepath.Join(filepath.Dir(in.indexFile), filepath.FromSlash(f.File))
}
// SaveFile attempts to read the file from disk
func (in Index) SaveFile(f IndexFile, dest io.Writer) error {
hashFormat := f.HashFormat
if hashFormat == "" {
hashFormat = in.HashFormat
}
src, err := os.Open(in.GetFilePath(f))
if err != nil {
return err
}
h, err := GetHashImpl(hashFormat)
if err != nil {
return err
}
w := io.MultiWriter(h, dest)
_, err = io.Copy(w, src)
if err != nil {
return err
}
calculatedHash := hex.EncodeToString(h.Sum(nil))
if calculatedHash != f.Hash {
return errors.New("hash of saved file is invalid")
}
return nil
}

View File

@@ -1,12 +1,13 @@
package core
import (
"crypto/sha256"
"encoding/hex"
"errors"
"io"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/BurntSushi/toml"
)
@@ -37,6 +38,7 @@ type ModDownload struct {
}
// The three possible values of Side (the side that the mod is on) are "server", "client", and "both".
//noinspection GoUnusedConst
const (
ServerSide = "server"
ClientSide = "client"
@@ -88,7 +90,10 @@ func (m Mod) Write() (string, string, error) {
}
defer f.Close()
h := sha256.New()
h, err := GetHashImpl("sha256")
if err != nil {
return "", "", err
}
w := io.MultiWriter(h, f)
enc := toml.NewEncoder(w)
@@ -109,3 +114,36 @@ func (m Mod) GetParsedUpdateData(updaterName string) (interface{}, bool) {
func (m Mod) GetFilePath() string {
return m.metaFile
}
// GetDestFilePath returns the path of the destination file of the mod
func (m Mod) GetDestFilePath() string {
return filepath.Join(filepath.Dir(m.metaFile), filepath.FromSlash(m.FileName))
}
// DownloadFile attempts to resolve and download the file
func (m Mod) DownloadFile(dest io.Writer) error {
resp, err := http.Get(m.Download.URL)
if err != nil {
return err
}
if resp.StatusCode != 200 {
_ = resp.Body.Close()
return errors.New("invalid status code " + strconv.Itoa(resp.StatusCode))
}
h, err := GetHashImpl(m.Download.HashFormat)
if err != nil {
return err
}
w := io.MultiWriter(h, dest)
_, err = io.Copy(w, resp.Body)
if err != nil {
return err
}
calculatedHash := hex.EncodeToString(h.Sum(nil))
if calculatedHash != m.Download.Hash {
return errors.New("hash of saved file is invalid")
}
return nil
}

View File

@@ -1,7 +1,6 @@
package core
import (
"crypto/sha256"
"encoding/hex"
"errors"
"io"
@@ -65,7 +64,10 @@ func (pack *Pack) UpdateIndexHash() error {
// Hash usage strategy (may change):
// Just use SHA256, overwrite existing hash regardless of what it is
// May update later to continue using the same hash that was already being used
h := sha256.New()
h, err := GetHashImpl("sha256")
if err != nil {
return err
}
if _, err := io.Copy(h, f); err != nil {
return err
}