Skip to content

Commit

Permalink
verify checksum in filedownload
Browse files Browse the repository at this point in the history
  • Loading branch information
JojiiOfficial committed Apr 9, 2020
1 parent 5f239ea commit 042b445
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 13 deletions.
45 changes: 33 additions & 12 deletions File.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ import (
"path/filepath"
"strconv"
"time"

"github.com/pkg/errors"
)

// FileAttributes attributes for a file
Expand Down Expand Up @@ -45,6 +47,7 @@ type FileResponseItem struct {
PublicName string `json:"pubname"`
Attributes FileAttributes `json:"attrib"`
Encryption string `json:"e"`
Checksum string `json:"checksum"`
}

// FileChanges file changes for updating a file
Expand Down Expand Up @@ -122,9 +125,10 @@ func (libdm LibDM) PublishFile(name string, id uint, publicName string, all bool
return resp, nil
}

// GetFile returns a readCloser for the request body == file content
// Body must be closed
func (libdm LibDM) GetFile(name string, id uint, namespace string) (*http.Response, string, error) {
// GetFile requests a filedownload and returns the response
// -> response, serverfilename, checksum, error
// The response body must be closed
func (libdm LibDM) GetFile(name string, id uint, namespace string) (*http.Response, string, string, error) {
resp, err := NewRequest(EPFileGet, &FileRequest{
Name: name,
FileID: id,
Expand All @@ -135,14 +139,14 @@ func (libdm LibDM) GetFile(name string, id uint, namespace string) (*http.Respon

// Check for error
if err != nil {
return nil, "", &ResponseErr{
return nil, "", "", &ResponseErr{
Err: err,
}
}

// Check response headers
if resp.Header.Get(HeaderStatus) == strconv.Itoa(int(ResponseError)) {
return nil, "", &ResponseErr{
return nil, "", "", &ResponseErr{
Response: &RestRequestResponse{
HTTPCode: resp.StatusCode,
Headers: &resp.Header,
Expand All @@ -152,47 +156,64 @@ func (libdm LibDM) GetFile(name string, id uint, namespace string) (*http.Respon
}
}

// Get filename from response headers
// Get filename from headers
serverFileName := resp.Header.Get(HeaderFileName)
// Get file checksum from headers
checksum := resp.Header.Get(HeaderChecksum)

// Check headers
if len(serverFileName) == 0 {
return nil, "", &ResponseErr{
return nil, "", "", &ResponseErr{
Err: ErrResponseFilenameInvalid,
}
}

return resp, serverFileName, nil
return resp, serverFileName, checksum, nil
}

var (
// ErrChecksumNotMatch error if the checksum of the downloaded
// file doesn't match with the checksum of the remote file
ErrChecksumNotMatch = errors.New("generated checksum not match")
)

// DownloadFile downloads and saves a file to the given localFilePath. If the file exists, it will be overwritten
func (libdm LibDM) DownloadFile(name string, id uint, namespace, localFilePath string, appendFilename ...bool) error {
// Download file from server
resp, name, err := libdm.GetFile(name, id, namespace)
resp, name, checksum, err := libdm.GetFile(name, id, namespace)
if err != nil {
return err
}
defer resp.Body.Close()

hash := crc32.NewIEEE()

// Append remote filename if desired
if len(appendFilename) > 0 && appendFilename[0] {
localFilePath = filepath.Join(localFilePath, name)
}

// Create loal file
f, err := os.Create(localFilePath)
defer f.Close()
if err != nil {
return err
}
defer f.Close()

w := io.MultiWriter(hash, f)

// Save file to local file
buff := make([]byte, 512)
_, err = io.CopyBuffer(f, resp.Body, buff)
buff := make([]byte, 10*1024)
_, err = io.CopyBuffer(w, resp.Body, buff)
if err != nil {
return err
}

// Check if the checksums are equal, if not return an error
if hex.EncodeToString(hash.Sum(nil)) != checksum {
return ErrChecksumNotMatch
}

return nil
}

Expand Down
10 changes: 10 additions & 0 deletions Response.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,20 +17,30 @@ const (
const (
// HeaderStatus headername for status in response
HeaderStatus string = "X-Response-Status"

// HeaderStatusMessage headername for status in response
HeaderStatusMessage string = "X-Response-Message"

// HeaderContentType contenttype of response
HeaderContentType string = "Content-Type"

// HeaderFileName filename header
HeaderFileName string = "X-Filename"

// HeaderRequest request content
HeaderRequest string = "Request"

// HeaderEncryption encryption header
HeaderEncryption string = "X-Encryption"

// HeaderContentLength request content length
HeaderContentLength string = "ContentLength"

// HeaderFileID fileid header
HeaderFileID string = "X-FileID"

// HeaderChecksum files checksum
HeaderChecksum string = "Checksum"
)

// LoginResponse response for login
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,7 @@ module github.com/DataManager-Go/libdatamanager

go 1.14

require github.com/jinzhu/gorm v1.9.12
require (
github.com/jinzhu/gorm v1.9.12
github.com/pkg/errors v0.9.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ github.com/lib/pq v1.1.1 h1:sJZmqHoEaY7f+NPP8pgLB/WxulyR3fewgCM2qaSlBb4=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/mattn/go-sqlite3 v2.0.1+incompatible h1:xQ15muvnzGBHpIpdrNi1DA5x0+TcBZzsIDwmw9uTHzw=
github.com/mattn/go-sqlite3 v2.0.1+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd h1:GGJVjV8waZKRHrgwvtH66z9ZGVurTD1MT0n1Bb+q4aM=
Expand Down

0 comments on commit 042b445

Please sign in to comment.