From a1ee320eba7fba76ee019770a425161d9ceac946 Mon Sep 17 00:00:00 2001 From: Las Zenow Date: Sun, 3 May 2020 09:35:17 +0000 Subject: [PATCH] Add hashes for each book Check if the uploaded book is already in the library --- lib/database/books.go | 21 ++++++++++++++++++--- lib/database/database.go | 2 ++ lib/database/ro.go | 4 ++++ lib/upload.go | 19 +++++++++++++++++-- 4 files changed, 41 insertions(+), 5 deletions(-) diff --git a/lib/database/books.go b/lib/database/books.go index 8466a6a..606f45f 100644 --- a/lib/database/books.go +++ b/lib/database/books.go @@ -1,6 +1,8 @@ package database import ( + log "github.com/cihub/seelog" + "strings" "time" @@ -17,9 +19,10 @@ type Book struct { Description string Tags []string `pg:"tags,array"` Date string - Lang string `pg:"type:varchar(3)"` - Isbn string `pg:"type:varchar(13)"` - FileSize int `pg:"type:integer"` + Lang string `pg:"type:varchar(3)"` + Isbn string `pg:"type:varchar(13)"` + FileSize int `pg:"type:integer"` + FileHash []byte Cover bool `pg:",notnull"` Active bool `pg:",notnull"` UploadDate time.Time `pg:"type:timestamp"` @@ -165,6 +168,18 @@ func (db *pgDB) IsBookActive(id string) bool { return active[0] } +// ExistsBookHash checks if the given hash matches the hash of any book in the lbirary +func (db *pgDB) ExistsBookHash(hash []byte) bool { + count, err := db.sql.Model(&Book{}). + Where("file_hash = ?", hash). + Count() + if err != nil { + log.Warnf("There was an error looking for the hash: %v", err) + return false + } + return count > 0 +} + type columnq struct { column string value string diff --git a/lib/database/database.go b/lib/database/database.go index 4cf5b6a..1df67bd 100644 --- a/lib/database/database.go +++ b/lib/database/database.go @@ -17,6 +17,7 @@ type DB interface { UpdateBook(id string, data map[string]interface{}) error ActiveBook(id string) error IsBookActive(id string) bool + ExistsBookHash(hash []byte) bool AddUser(name string, pass string) error AddRawUser(name string, hpass []byte, salt []byte, role string) error SetAdminUser(name string, pass string) error @@ -149,6 +150,7 @@ ALTER TABLE books ALTER COLUMN active SET DEFAULT false ; CREATE INDEX IF NOT EXISTS books_lang_idx ON books (lang); CREATE INDEX IF NOT EXISTS books_isbn_idx ON books (isbn); CREATE INDEX IF NOT EXISTS books_active_idx ON books (active); +CREATE INDEX IF NOT EXISTS books_file_hash_idx ON books (file_hash); diff --git a/lib/database/ro.go b/lib/database/ro.go index e0ecab2..a56735c 100644 --- a/lib/database/ro.go +++ b/lib/database/ro.go @@ -45,6 +45,10 @@ func (db *roDB) IsBookActive(id string) bool { return db.db.IsBookActive(id) } +func (db *roDB) ExistsBookHash(hash []byte) bool { + return db.db.ExistsBookHash(hash) +} + func (db *roDB) AddUser(name string, pass string) error { return errors.New("RO database") } diff --git a/lib/upload.go b/lib/upload.go index b255c41..c1b57d2 100644 --- a/lib/upload.go +++ b/lib/upload.go @@ -1,13 +1,14 @@ package trantor import ( - "net/http" - log "github.com/cihub/seelog" "crypto/rand" + "crypto/sha256" "encoding/base64" + "io" "mime/multipart" + "net/http" "github.com/meskio/epubgo" "gitlab.com/trantor/trantor/lib/database" @@ -41,6 +42,19 @@ func uploadWorker(database database.DB, store storage.Store) { func (req uploadRequest) processFile(db database.DB, store storage.Store) { defer req.file.Close() + h := sha256.New() + if _, err := io.Copy(h, req.file); err != nil { + log.Warn("Can't read uploaded file ", req.header.Filename, ": ", err) + db.UpdateSubmission(req.id, "There was a problem with the uploaded book, try again later.", nil) + return + } + fileHash := h.Sum(nil) + if db.ExistsBookHash(fileHash) { + log.Info("Uploaded file ", req.header.Filename, " already in the library.") + db.UpdateSubmission(req.id, "The uploaded book is already in the library (it could be in the moderation queue)", nil) + return + } + epub, err := epubgo.Load(req.file, req.header.Size) if err != nil { log.Warn("Not valid epub uploaded file ", req.header.Filename, ": ", err) @@ -61,6 +75,7 @@ func (req uploadRequest) processFile(db database.DB, store storage.Store) { } book.FileSize = int(size) + book.FileHash = fileHash book.Cover = GetCover(epub, book.ID, store) err = db.AddBook(book)