2016-01-13 19:25:25 +00:00
package fic
2016-01-07 17:43:02 +00:00
import (
2016-01-23 11:19:47 +00:00
"bufio"
2016-01-07 17:43:02 +00:00
"crypto/sha1"
2017-01-04 00:30:24 +00:00
"encoding/hex"
"errors"
2016-01-07 17:43:02 +00:00
"io"
"os"
"path"
2016-01-20 21:44:34 +00:00
"strings"
2017-11-24 19:08:14 +00:00
"github.com/dchest/blake2b"
2016-01-07 17:43:02 +00:00
)
2017-11-25 15:05:03 +00:00
var FilesDir string = "./FILES/"
var OptionalDigest bool = false
var StrongDigest bool = false
2016-01-20 21:44:34 +00:00
2016-01-07 17:43:02 +00:00
type EFile struct {
2016-01-23 11:19:47 +00:00
Id int64 ` json:"id" `
2016-01-20 21:44:34 +00:00
origin string
2016-01-13 19:25:25 +00:00
Path string ` json:"path" `
IdExercice int64 ` json:"idExercice" `
Name string ` json:"name" `
Checksum [ ] byte ` json:"checksum" `
2016-01-18 18:38:59 +00:00
Size int64 ` json:"size" `
2016-01-07 17:43:02 +00:00
}
2016-02-01 17:57:47 +00:00
func GetFiles ( ) ( [ ] EFile , error ) {
2017-11-24 19:08:14 +00:00
if rows , err := DBQuery ( "SELECT id_file, id_exercice, origin, path, name, cksum, size FROM exercice_files" ) ; err != nil {
2016-02-01 17:57:47 +00:00
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
}
}
2017-12-27 00:53:01 +00:00
func GetFile ( id int ) ( f EFile , err error ) {
err = DBQueryRow ( "SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_file = ?" , id ) . Scan ( & f . Id , & f . origin , & f . Path , & f . Name , & f . Checksum , & f . Size )
return f , err
}
2017-12-04 07:39:45 +00:00
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
}
2016-01-07 17:43:02 +00:00
func ( e Exercice ) GetFiles ( ) ( [ ] EFile , error ) {
2017-11-24 19:08:14 +00:00
if rows , err := DBQuery ( "SELECT id_file, origin, path, name, cksum, size FROM exercice_files WHERE id_exercice = ?" , e . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
} else {
defer rows . Close ( )
var files = make ( [ ] EFile , 0 )
for rows . Next ( ) {
var f EFile
2016-01-13 00:20:21 +00:00
f . IdExercice = e . Id
2016-01-20 21:44:34 +00:00
if err := rows . Scan ( & f . Id , & f . origin , & f . Path , & f . Name , & f . Checksum , & f . Size ) ; err != nil {
2016-01-07 17:43:02 +00:00
return nil , err
}
files = append ( files , f )
}
if err := rows . Err ( ) ; err != nil {
return nil , err
}
return files , nil
}
}
2017-12-04 07:39:45 +00:00
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
}
2017-12-27 00:53:01 +00:00
func checkFileHash ( filePath string , digest [ ] byte ) ( [ ] byte , int64 , error ) {
if digest == nil {
return [ ] byte { } , 0 , errors . New ( "No digest given." )
2017-01-04 00:30:24 +00:00
} else if fi , err := os . Stat ( filePath ) ; err != nil {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , err
2016-01-18 18:38:59 +00:00
} else if fd , err := os . Open ( filePath ) ; err != nil {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , err
2016-01-07 17:43:02 +00:00
} else {
defer fd . Close ( )
2016-01-23 11:19:47 +00:00
reader := bufio . NewReader ( fd )
2017-11-24 19:08:14 +00:00
hash160 := sha1 . New ( )
hash512 := blake2b . New512 ( )
2017-01-04 00:30:24 +00:00
2017-11-24 19:08:14 +00:00
w := io . MultiWriter ( hash160 , hash512 )
if _ , err := io . Copy ( w , reader ) ; err != nil {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , err
2017-01-04 00:30:24 +00:00
}
2017-11-24 19:08:14 +00:00
result160 := hash160 . Sum ( nil )
result512 := hash512 . Sum ( nil )
if len ( digest ) != len ( result512 ) {
if len ( digest ) != len ( result160 ) {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , errors . New ( "Digests doesn't match: calculated: sha1:" + hex . EncodeToString ( result160 ) + " & blake2b:" + hex . EncodeToString ( result512 ) + " vs. given: " + hex . EncodeToString ( digest ) )
2017-11-24 19:08:14 +00:00
} else if StrongDigest {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , 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 ) )
2017-11-24 19:08:14 +00:00
}
2017-01-04 00:30:24 +00:00
2017-11-24 19:08:14 +00:00
for k := range result160 {
if result160 [ k ] != digest [ k ] {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , errors . New ( "Digests doesn't match: calculated: sha1:" + hex . EncodeToString ( result160 ) + " & blake2b:" + hex . EncodeToString ( result512 ) + " vs. given: " + hex . EncodeToString ( digest ) )
2017-11-24 19:08:14 +00:00
}
}
} else {
for k := range result512 {
if result512 [ k ] != digest [ k ] {
2017-12-27 00:53:01 +00:00
return [ ] byte { } , fi . Size ( ) , errors . New ( "Digests doesn't match: calculated: " + hex . EncodeToString ( result512 ) + " vs. given: " + hex . EncodeToString ( digest ) )
2017-11-24 19:08:14 +00:00
}
2017-01-04 00:30:24 +00:00
}
}
2017-12-27 00:53:01 +00:00
return result512 , fi . Size ( ) , nil
}
}
func ( e Exercice ) ImportFile ( filePath string , origin string , digest [ ] byte ) ( interface { } , error ) {
if result512 , size , err := checkFileHash ( filePath , digest ) ; ! OptionalDigest && err != nil {
return EFile { } , err
} else {
2017-11-27 01:45:33 +00:00
dPath := strings . TrimPrefix ( filePath , FilesDir )
if f , err := e . GetFileByPath ( dPath ) ; err != nil {
2017-12-27 00:53:01 +00:00
return e . AddFile ( dPath , origin , path . Base ( filePath ) , result512 , size )
2017-11-27 01:45:33 +00:00
} 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
2017-12-27 00:53:01 +00:00
f . Size = size
2017-11-27 01:45:33 +00:00
if _ , err := f . Update ( ) ; err != nil {
return nil , err
} else {
return f , nil
}
}
2016-01-07 17:43:02 +00:00
}
}
2016-01-20 21:44:34 +00:00
func ( e Exercice ) AddFile ( path string , origin string , name string , checksum [ ] byte , size int64 ) ( EFile , error ) {
2017-11-24 19:08:14 +00:00
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 {
2016-01-07 17:43:02 +00:00
return EFile { } , err
} else if fid , err := res . LastInsertId ( ) ; err != nil {
return EFile { } , err
} else {
2016-01-20 21:44:34 +00:00
return EFile { fid , origin , path , e . Id , name , checksum , size } , nil
2016-01-07 17:43:02 +00:00
}
}
func ( f EFile ) Update ( ) ( int64 , error ) {
2017-11-24 19:08:14 +00:00
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 {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
func ( f EFile ) Delete ( ) ( int64 , error ) {
2016-01-13 00:20:21 +00:00
if res , err := DBExec ( "DELETE FROM exercice_files WHERE id_file = ?" , f . Id ) ; err != nil {
2016-01-07 17:43:02 +00:00
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2016-02-01 17:57:47 +00:00
2017-12-08 23:52:43 +00:00
func ( e Exercice ) WipeFiles ( ) ( int64 , error ) {
if res , err := DBExec ( "DELETE FROM exercice_files WHERE id_exercice = ?" , e . Id ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2017-12-27 00:53:01 +00:00
func ClearFiles ( ) ( int64 , error ) {
if res , err := DBExec ( "DELETE FROM exercice_files" ) ; err != nil {
return 0 , err
} else if nb , err := res . RowsAffected ( ) ; err != nil {
return 0 , err
} else {
return nb , err
}
}
2017-11-24 19:08:14 +00:00
func ( f EFile ) GetOrigin ( ) string {
2016-02-01 17:57:47 +00:00
return f . origin
}