mirror of
https://github.com/packwiz/packwiz.git
synced 2025-10-14 06:54:32 +02:00
Implement pack importing/exporting for downloaded Curseforge packs
Abstract out hash implementations Implement file saving/downloading
This commit is contained in:
23
core/hash.go
Normal file
23
core/hash.go
Normal 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")
|
||||
}
|
@@ -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
|
||||
}
|
||||
|
42
core/mod.go
42
core/mod.go
@@ -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
|
||||
}
|
||||
|
@@ -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
|
||||
}
|
||||
|
Reference in New Issue
Block a user