This repository has been archived on 2025-03-01. You can view files and clone it, but cannot push or open issues or pull requests.
trantor/lib/upload.go
Las Zenow 0f18a0e91d Don't continue working with an invalid epub
It produces a seg fault
2019-05-30 01:09:28 +00:00

167 lines
4.3 KiB
Go

package trantor
import (
"net/http"
log "github.com/cihub/seelog"
"crypto/rand"
"encoding/base64"
"mime/multipart"
"github.com/gorilla/mux"
"github.com/meskio/epubgo"
"gitlab.com/trantor/trantor/lib/database"
"gitlab.com/trantor/trantor/lib/parser"
"gitlab.com/trantor/trantor/lib/storage"
)
const (
uploadChanSize = 100
)
func InitUpload(database database.DB, store storage.Store) {
uploadChannel = make(chan uploadRequest, uploadChanSize)
go uploadWorker(database, store)
}
var uploadChannel chan uploadRequest
type uploadRequest struct {
file multipart.File
header *multipart.FileHeader
id int
}
func uploadWorker(database database.DB, store storage.Store) {
for req := range uploadChannel {
req.processFile(database, store)
}
}
func (req uploadRequest) processFile(db database.DB, store storage.Store) {
defer req.file.Close()
epub, err := epubgo.Load(req.file, req.header.Size)
if err != nil {
log.Warn("Not valid epub uploaded file ", req.header.Filename, ": ", err)
db.UpdateSubmission(req.id, "It is not a valid epub file", nil)
return
}
defer epub.Close()
book := parser.EpubMetadata(epub)
book.ID = GenID()
req.file.Seek(0, 0)
size, err := store.Store(book.ID, req.file, epubFile)
if err != nil {
log.Error("Error storing book (", book.ID, "): ", err)
db.UpdateSubmission(req.id, "There was a problem in our server", nil)
return
}
book.FileSize = int(size)
book.Cover = GetCover(epub, book.ID, store)
err = db.AddBook(book)
if err != nil {
log.Error("Error storing metadata (", book.ID, "): ", err)
db.UpdateSubmission(req.id, "There was a problem in our server", nil)
return
}
log.Info("File uploaded: ", req.header.Filename)
db.UpdateSubmission(req.id, "Waiting for moderation", &book)
}
func uploadPostHandler(h handler) {
const _2M int64 = (1 << 20) * 2
if h.ro {
h.sess.Notify("Upload failed!", "The library is in Read Only mode, no books can be uploaded", "error")
uploadHandler(h)
return
}
if err := h.r.ParseMultipartForm(_2M); nil != err {
log.Error("Can't parse form: ", err)
return
}
defer h.r.MultipartForm.RemoveAll()
filesForm := h.r.MultipartForm.File["epub"]
submissionID := GenID()
for _, f := range filesForm {
submission := database.Submission{
SubmissionID: submissionID,
Filename: f.Filename,
Status: "Waiting to be processed",
}
file, err := f.Open()
if err != nil {
log.Error("Can not open uploaded file ", f.Filename, ": ", err)
h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error")
submission.Status = "It was not possible to read the book"
h.db.AddSubmission(submission, h.sess.User)
continue
}
id, err := h.db.AddSubmission(submission, h.sess.User)
if err != nil {
log.Error("Can add submission to db for ", f.Filename, ": ", err)
}
uploadChannel <- uploadRequest{file, f, id}
}
http.Redirect(h.w, h.r, "/submission/"+submissionID, http.StatusFound)
}
func uploadHandler(h handler) {
var data struct{ S Status }
data.S = GetStatus(h)
data.S.Title = "Upload -- " + data.S.Title
data.S.Upload = true
h.load("upload", data)
}
func submissionHandler(h handler) {
var data submissionData
var err error
submissionID := mux.Vars(h.r)["submissionID"]
data.SubmissionID = submissionID
data.Submissions, err = h.db.GetSubmission(submissionID)
if err != nil {
log.Error("Can get submission ", submissionID, ": ", err)
}
data.S = GetStatus(h)
data.S.Title = "Submission -- " + data.S.Title
h.load("submission", data)
}
type submissionData struct {
S Status
SubmissionID string
Submissions []database.Submission
}
func submissionCommentHandler(h handler) {
submissionID := mux.Vars(h.r)["submissionID"]
bookID := mux.Vars(h.r)["id"]
comment := h.r.FormValue("comment")
err := h.db.UpdateSubmissionComment(submissionID, bookID, comment)
if err != nil {
log.Error("Adding comment (submission: ", submissionID, ", book: ", bookID, ") <", comment, ">: ", err)
h.sess.Notify("Error adding a comment!", "Can't add the comment rigt now. Try again later or report it to the site admins", "error")
} else {
h.sess.Notify("Comment added!", "", "success")
}
http.Redirect(h.w, h.r, "/submission/"+submissionID, http.StatusFound)
}
func GenID() string {
b := make([]byte, 12)
rand.Read(b)
return base64.URLEncoding.EncodeToString(b)
}