nemunaire
8f7de926d3
We are now able, depending on configuration, to retrieve files from either WebDAV or local file system.
191 lines
5.5 KiB
Go
191 lines
5.5 KiB
Go
package fic
|
|
|
|
import (
|
|
"bufio"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
|
|
"github.com/dchest/blake2b"
|
|
)
|
|
|
|
var FilesDir string = "./FILES/"
|
|
var OptionalDigest bool = false
|
|
var StrongDigest bool = false
|
|
|
|
type EFile struct {
|
|
Id int64 `json:"id"`
|
|
origin string
|
|
Path string `json:"path"`
|
|
IdExercice int64 `json:"idExercice"`
|
|
Name string `json:"name"`
|
|
Checksum []byte `json:"checksum"`
|
|
Size int64 `json:"size"`
|
|
}
|
|
|
|
func GetFiles() ([]EFile, error) {
|
|
if rows, err := DBQuery("SELECT id_file, id_exercice, origin, path, name, cksum, size FROM exercice_files"); err != nil {
|
|
return nil, err
|
|
} else {
|
|
defer rows.Close()
|
|
|
|
var files = make([]EFile, 0)
|
|
for rows.Next() {
|
|
var f EFile
|
|
if err := rows.Scan(&f.Id, &f.IdExercice, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
|
return nil, err
|
|
}
|
|
files = append(files, f)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
}
|
|
|
|
func GetFileByPath(path string) (EFile, error) {
|
|
path = strings.TrimPrefix(path, FilesDir)
|
|
|
|
var f EFile
|
|
if err := DBQueryRow("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE path = ?", path).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
|
return f, err
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func (e Exercice) GetFiles() ([]EFile, error) {
|
|
if rows, err := DBQuery("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ?", e.Id); err != nil {
|
|
return nil, err
|
|
} else {
|
|
defer rows.Close()
|
|
|
|
var files = make([]EFile, 0)
|
|
for rows.Next() {
|
|
var f EFile
|
|
f.IdExercice = e.Id
|
|
if err := rows.Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
|
return nil, err
|
|
}
|
|
files = append(files, f)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return files, nil
|
|
}
|
|
}
|
|
|
|
func (e Exercice) GetFileByPath(path string) (EFile, error) {
|
|
path = strings.TrimPrefix(path, FilesDir)
|
|
|
|
var f EFile
|
|
if err := DBQueryRow("SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ? AND path = ?", e.Id, path).Scan(&f.Id, &f.origin, &f.Path, &f.Name, &f.Checksum, &f.Size); err != nil {
|
|
return f, err
|
|
}
|
|
|
|
return f, nil
|
|
}
|
|
|
|
func (e Exercice) ImportFile(filePath string, origin string, digest []byte) (interface{}, error) {
|
|
if digest == nil && !OptionalDigest {
|
|
return EFile{}, errors.New("No digest given.")
|
|
} else if fi, err := os.Stat(filePath); err != nil {
|
|
return EFile{}, err
|
|
} else if fd, err := os.Open(filePath); err != nil {
|
|
return EFile{}, err
|
|
} else {
|
|
defer fd.Close()
|
|
|
|
reader := bufio.NewReader(fd)
|
|
hash160 := sha1.New()
|
|
hash512 := blake2b.New512()
|
|
|
|
w := io.MultiWriter(hash160, hash512)
|
|
if _, err := io.Copy(w, reader); err != nil {
|
|
return EFile{}, err
|
|
}
|
|
result160 := hash160.Sum(nil)
|
|
result512 := hash512.Sum(nil)
|
|
|
|
if len(digest) != len(result512) {
|
|
if len(digest) != len(result160) {
|
|
return EFile{}, errors.New("Digests doesn't match: calculated: sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest))
|
|
} else if StrongDigest {
|
|
return EFile{}, errors.New("Invalid digests: SHA-1 checksums are no more accepted. Calculated sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest))
|
|
}
|
|
|
|
for k := range result160 {
|
|
if result160[k] != digest[k] {
|
|
return EFile{}, errors.New("Digests doesn't match: calculated: sha1:" + hex.EncodeToString(result160) + " & blake2b:" + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest))
|
|
}
|
|
}
|
|
} else {
|
|
for k := range result512 {
|
|
if result512[k] != digest[k] {
|
|
return EFile{}, errors.New("Digests doesn't match: calculated: " + hex.EncodeToString(result512) + " vs. given: " + hex.EncodeToString(digest))
|
|
}
|
|
}
|
|
}
|
|
|
|
dPath := strings.TrimPrefix(filePath, FilesDir)
|
|
if f, err := e.GetFileByPath(dPath); err != nil {
|
|
return e.AddFile(dPath, origin, path.Base(filePath), result512, fi.Size())
|
|
} else {
|
|
// Don't need to update Path and Name, because they are related to dPath
|
|
|
|
f.IdExercice = e.Id
|
|
f.origin = origin
|
|
f.Checksum = result512
|
|
f.Size = fi.Size()
|
|
|
|
if _, err := f.Update(); err != nil {
|
|
return nil, err
|
|
} else {
|
|
return f, nil
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (e Exercice) AddFile(path string, origin string, name string, checksum []byte, size int64) (EFile, error) {
|
|
if res, err := DBExec("INSERT INTO exercice_files (id_exercice, origin, path, name, cksum, size) VALUES (?, ?, ?, ?, ?, ?)", e.Id, origin, path, name, checksum, size); err != nil {
|
|
return EFile{}, err
|
|
} else if fid, err := res.LastInsertId(); err != nil {
|
|
return EFile{}, err
|
|
} else {
|
|
return EFile{fid, origin, path, e.Id, name, checksum, size}, nil
|
|
}
|
|
}
|
|
|
|
func (f EFile) Update() (int64, error) {
|
|
if res, err := DBExec("UPDATE exercice_files SET id_exercice = ?, origin = ?, path = ?, name = ?, cksum = ?, size = ? WHERE id_file = ?", f.IdExercice, f.origin, f.Path, f.Name, f.Checksum, f.Size, f.Id); err != nil {
|
|
return 0, err
|
|
} else if nb, err := res.RowsAffected(); err != nil {
|
|
return 0, err
|
|
} else {
|
|
return nb, err
|
|
}
|
|
}
|
|
|
|
func (f EFile) Delete() (int64, error) {
|
|
if res, err := DBExec("DELETE FROM exercice_files WHERE id_file = ?", f.Id); err != nil {
|
|
return 0, err
|
|
} else if nb, err := res.RowsAffected(); err != nil {
|
|
return 0, err
|
|
} else {
|
|
return nb, err
|
|
}
|
|
}
|
|
|
|
func (f EFile) GetOrigin() string {
|
|
return f.origin
|
|
}
|