Database stops being a global variable

With it now every handler creates it's own copy of the session.
This commit is contained in:
Las Zenow 2013-09-23 16:27:31 +02:00
parent cef68a8f6e
commit 41b376992a
12 changed files with 318 additions and 299 deletions

150
admin.go
View file

@ -13,54 +13,54 @@ type settingsData struct {
S Status S Status
} }
func settingsHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func settingsHandler(h handler) {
if sess.User == "" { if h.sess.User == "" {
notFound(w, r) notFound(h)
return return
} }
if r.Method == "POST" { if h.r.Method == "POST" {
current_pass := r.FormValue("currpass") current_pass := h.r.FormValue("currpass")
pass1 := r.FormValue("password1") pass1 := h.r.FormValue("password1")
pass2 := r.FormValue("password2") pass2 := h.r.FormValue("password2")
switch { switch {
case !db.UserValid(sess.User, current_pass): case !h.db.UserValid(h.sess.User, current_pass):
sess.Notify("Password error!", "The current password given don't match with the user password. Try again", "error") h.sess.Notify("Password error!", "The current password given don't match with the user password. Try again", "error")
case pass1 != pass2: case pass1 != pass2:
sess.Notify("Passwords don't match!", "The new password and the confirmation password don't match. Try again", "error") h.sess.Notify("Passwords don't match!", "The new password and the confirmation password don't match. Try again", "error")
default: default:
db.SetPassword(sess.User, pass1) h.db.SetPassword(h.sess.User, pass1)
sess.Notify("Password updated!", "Your new password is correctly set.", "success") h.sess.Notify("Password updated!", "Your new password is correctly set.", "success")
} }
} }
var data settingsData var data settingsData
data.S = GetStatus(w, r) data.S = GetStatus(h)
loadTemplate(w, "settings", data) loadTemplate(h.w, "settings", data)
} }
func deleteHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func deleteHandler(h handler) {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
var titles []string var titles []string
var isNew bool var isNew bool
ids := strings.Split(mux.Vars(r)["ids"], "/") ids := strings.Split(mux.Vars(h.r)["ids"], "/")
for _, idStr := range ids { for _, idStr := range ids {
if !bson.IsObjectIdHex(idStr) { if !bson.IsObjectIdHex(idStr) {
continue continue
} }
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil { if err != nil {
sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error") h.sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error")
continue continue
} }
book := books[0] book := books[0]
DeleteBook(book) DeleteBook(book, h.db)
db.RemoveBook(id) h.db.RemoveBook(id)
if !book.Active { if !book.Active {
isNew = true isNew = true
@ -68,33 +68,33 @@ func deleteHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
titles = append(titles, book.Title) titles = append(titles, book.Title)
} }
if titles != nil { if titles != nil {
sess.Notify("Removed books!", "The books "+strings.Join(titles, ", ")+" are completly removed", "success") h.sess.Notify("Removed books!", "The books "+strings.Join(titles, ", ")+" are completly removed", "success")
} }
sess.Save(w, r) h.sess.Save(h.w, h.r)
if isNew { if isNew {
http.Redirect(w, r, "/new/", http.StatusFound) http.Redirect(h.w, h.r, "/new/", http.StatusFound)
} else { } else {
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(h.w, h.r, "/", http.StatusFound)
} }
} }
func editHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func editHandler(h handler) {
idStr := mux.Vars(r)["id"] idStr := mux.Vars(h.r)["id"]
if !sess.IsAdmin() || !bson.IsObjectIdHex(idStr) { if !h.sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
notFound(w, r) notFound(h)
return return
} }
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
var data bookData var data bookData
data.Book = books[0] data.Book = books[0]
data.S = GetStatus(w, r) data.S = GetStatus(h)
loadTemplate(w, "edit", data) loadTemplate(h.w, "edit", data)
} }
func cleanEmptyStr(s []string) []string { func cleanEmptyStr(s []string) []string {
@ -107,21 +107,21 @@ func cleanEmptyStr(s []string) []string {
return res return res
} }
func saveHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func saveHandler(h handler) {
idStr := mux.Vars(r)["id"] idStr := mux.Vars(h.r)["id"]
if !sess.IsAdmin() || !bson.IsObjectIdHex(idStr) { if !h.sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
notFound(w, r) notFound(h)
return return
} }
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
title := r.FormValue("title") title := h.r.FormValue("title")
publisher := r.FormValue("publisher") publisher := h.r.FormValue("publisher")
date := r.FormValue("date") date := h.r.FormValue("date")
description := r.FormValue("description") description := h.r.FormValue("description")
author := cleanEmptyStr(r.Form["author"]) author := cleanEmptyStr(h.r.Form["author"])
subject := cleanEmptyStr(r.Form["subject"]) subject := cleanEmptyStr(h.r.Form["subject"])
lang := cleanEmptyStr(r.Form["lang"]) lang := cleanEmptyStr(h.r.Form["lang"])
book := map[string]interface{}{"title": title, book := map[string]interface{}{"title": title,
"publisher": publisher, "publisher": publisher,
"date": date, "date": date,
@ -130,18 +130,18 @@ func saveHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
"subject": subject, "subject": subject,
"lang": lang} "lang": lang}
book["keywords"] = keywords(book) book["keywords"] = keywords(book)
err := db.UpdateBook(id, book) err := h.db.UpdateBook(id, book)
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
sess.Notify("Book Modified!", "", "success") h.sess.Notify("Book Modified!", "", "success")
sess.Save(w, r) h.sess.Save(h.w, h.r)
if db.BookActive(id) { if h.db.BookActive(id) {
http.Redirect(w, r, "/book/"+idStr, http.StatusFound) http.Redirect(h.w, h.r, "/book/"+idStr, http.StatusFound)
} else { } else {
http.Redirect(w, r, "/new/", http.StatusFound) http.Redirect(h.w, h.r, "/new/", http.StatusFound)
} }
} }
@ -159,28 +159,28 @@ type newData struct {
Prev string Prev string
} }
func newHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func newHandler(h handler) {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
err := r.ParseForm() err := h.r.ParseForm()
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(h.w, err.Error(), http.StatusInternalServerError)
return return
} }
page := 0 page := 0
if len(r.Form["p"]) != 0 { if len(h.r.Form["p"]) != 0 {
page, err = strconv.Atoi(r.Form["p"][0]) page, err = strconv.Atoi(h.r.Form["p"][0])
if err != nil { if err != nil {
page = 0 page = 0
} }
} }
res, num, _ := db.GetNewBooks(NEW_ITEMS_PAGE, page*NEW_ITEMS_PAGE) res, num, _ := h.db.GetNewBooks(NEW_ITEMS_PAGE, page*NEW_ITEMS_PAGE)
var data newData var data newData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.Found = num data.Found = num
if num-NEW_ITEMS_PAGE*page < NEW_ITEMS_PAGE { if num-NEW_ITEMS_PAGE*page < NEW_ITEMS_PAGE {
data.Books = make([]newBook, num-NEW_ITEMS_PAGE*page) data.Books = make([]newBook, num-NEW_ITEMS_PAGE*page)
@ -189,8 +189,8 @@ func newHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
} }
for i, b := range res { for i, b := range res {
data.Books[i].B = b data.Books[i].B = b
_, data.Books[i].TitleFound, _ = db.GetBooks(buildQuery("title:"+b.Title), 1) _, data.Books[i].TitleFound, _ = h.db.GetBooks(buildQuery("title:"+b.Title), 1)
_, data.Books[i].AuthorFound, _ = db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1) _, data.Books[i].AuthorFound, _ = h.db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1)
} }
data.Page = page + 1 data.Page = page + 1
if num > (page+1)*NEW_ITEMS_PAGE { if num > (page+1)*NEW_ITEMS_PAGE {
@ -199,40 +199,40 @@ func newHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
if page > 0 { if page > 0 {
data.Prev = "/new/?p=" + strconv.Itoa(page-1) data.Prev = "/new/?p=" + strconv.Itoa(page-1)
} }
loadTemplate(w, "new", data) loadTemplate(h.w, "new", data)
} }
func storeHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func storeHandler(h handler) {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
var titles []string var titles []string
ids := strings.Split(mux.Vars(r)["ids"], "/") ids := strings.Split(mux.Vars(h.r)["ids"], "/")
for _, idStr := range ids { for _, idStr := range ids {
if !bson.IsObjectIdHex(idStr) { if !bson.IsObjectIdHex(idStr) {
continue continue
} }
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil { if err != nil {
sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error") h.sess.Notify("Book not found!", "The book with id '"+idStr+"' is not there", "error")
continue continue
} }
book := books[0] book := books[0]
if err != nil { if err != nil {
sess.Notify("An error ocurred!", err.Error(), "error") h.sess.Notify("An error ocurred!", err.Error(), "error")
log.Println("Error storing book '", book.Title, "': ", err.Error()) log.Println("Error storing book '", book.Title, "': ", err.Error())
continue continue
} }
db.UpdateBook(id, bson.M{"active": true}) h.db.UpdateBook(id, bson.M{"active": true})
titles = append(titles, book.Title) titles = append(titles, book.Title)
} }
if titles != nil { if titles != nil {
sess.Notify("Store books!", "The books '"+strings.Join(titles, ", ")+"' are stored for public download", "success") h.sess.Notify("Store books!", "The books '"+strings.Join(titles, ", ")+"' are stored for public download", "success")
} }
sess.Save(w, r) h.sess.Save(h.w, h.r)
http.Redirect(w, r, "/new/", http.StatusFound) http.Redirect(h.w, h.r, "/new/", http.StatusFound)
} }

View file

@ -16,34 +16,32 @@ import (
"labix.org/v2/mgo" "labix.org/v2/mgo"
"labix.org/v2/mgo/bson" "labix.org/v2/mgo/bson"
"log" "log"
"net/http"
"regexp" "regexp"
"strings" "strings"
) )
func coverHandler(w http.ResponseWriter, r *http.Request) { func coverHandler(h handler) {
vars := mux.Vars(r) vars := mux.Vars(h.r)
if !bson.IsObjectIdHex(vars["id"]) { if !bson.IsObjectIdHex(vars["id"]) {
notFound(w, r) notFound(h)
return return
} }
id := bson.ObjectIdHex(vars["id"]) id := bson.ObjectIdHex(vars["id"])
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil || len(books) == 0 { if err != nil || len(books) == 0 {
notFound(w, r) notFound(h)
return return
} }
book := books[0] book := books[0]
if !book.Active { if !book.Active {
sess := GetSession(r) if !h.sess.IsAdmin() {
if !sess.IsAdmin() { notFound(h)
notFound(w, r)
return return
} }
} }
fs := db.GetFS(FS_IMGS) fs := h.db.GetFS(FS_IMGS)
var f *mgo.GridFile var f *mgo.GridFile
if vars["size"] == "small" { if vars["size"] == "small" {
f, err = fs.OpenId(book.CoverSmall) f, err = fs.OpenId(book.CoverSmall)
@ -52,24 +50,24 @@ func coverHandler(w http.ResponseWriter, r *http.Request) {
} }
if err != nil { if err != nil {
log.Println("Error while opening image:", err) log.Println("Error while opening image:", err)
notFound(w, r) notFound(h)
return return
} }
defer f.Close() defer f.Close()
headers := w.Header() headers := h.w.Header()
headers["Content-Type"] = []string{"image/jpeg"} headers["Content-Type"] = []string{"image/jpeg"}
io.Copy(w, f) io.Copy(h.w, f)
} }
func GetCover(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) { func GetCover(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) {
imgId, smallId := coverFromMetadata(e, title) imgId, smallId := coverFromMetadata(e, title, db)
if imgId != "" { if imgId != "" {
return imgId, smallId return imgId, smallId
} }
imgId, smallId = searchCommonCoverNames(e, title) imgId, smallId = searchCommonCoverNames(e, title, db)
if imgId != "" { if imgId != "" {
return imgId, smallId return imgId, smallId
} }
@ -110,7 +108,7 @@ func GetCover(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) {
img, err := e.OpenFile(url) img, err := e.OpenFile(url)
if err == nil { if err == nil {
defer img.Close() defer img.Close()
return storeImg(img, title) return storeImg(img, title, db)
} }
} }
errNext = it.Next() errNext = it.Next()
@ -118,41 +116,41 @@ func GetCover(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) {
return "", "" return "", ""
} }
func coverFromMetadata(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) { func coverFromMetadata(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) {
metaList, _ := e.MetadataAttr("meta") metaList, _ := e.MetadataAttr("meta")
for _, meta := range metaList { for _, meta := range metaList {
if meta["name"] == "cover" { if meta["name"] == "cover" {
img, err := e.OpenFileId(meta["content"]) img, err := e.OpenFileId(meta["content"])
if err == nil { if err == nil {
defer img.Close() defer img.Close()
return storeImg(img, title) return storeImg(img, title, db)
} }
} }
} }
return "", "" return "", ""
} }
func searchCommonCoverNames(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) { func searchCommonCoverNames(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) {
for _, p := range []string{"cover.jpg", "Images/cover.jpg", "images/cover.jpg", "cover.jpeg", "cover1.jpg", "cover1.jpeg"} { for _, p := range []string{"cover.jpg", "Images/cover.jpg", "images/cover.jpg", "cover.jpeg", "cover1.jpg", "cover1.jpeg"} {
img, err := e.OpenFile(p) img, err := e.OpenFile(p)
if err == nil { if err == nil {
defer img.Close() defer img.Close()
return storeImg(img, title) return storeImg(img, title, db)
} }
} }
return "", "" return "", ""
} }
func storeImg(img io.Reader, title string) (bson.ObjectId, bson.ObjectId) { func storeImg(img io.Reader, title string, db *DB) (bson.ObjectId, bson.ObjectId) {
/* open the files */ /* open the files */
fBig, err := createCoverFile(title) fBig, err := createCoverFile(title, db)
if err != nil { if err != nil {
log.Println("Error creating", title, ":", err.Error()) log.Println("Error creating", title, ":", err.Error())
return "", "" return "", ""
} }
defer fBig.Close() defer fBig.Close()
fSmall, err := createCoverFile(title + "_small") fSmall, err := createCoverFile(title+"_small", db)
if err != nil { if err != nil {
log.Println("Error creating", title+"_small", ":", err.Error()) log.Println("Error creating", title+"_small", ":", err.Error())
return "", "" return "", ""
@ -189,7 +187,7 @@ func storeImg(img io.Reader, title string) (bson.ObjectId, bson.ObjectId) {
return idBig, idSmall return idBig, idSmall
} }
func createCoverFile(title string) (*mgo.GridFile, error) { func createCoverFile(title string, db *DB) (*mgo.GridFile, error) {
fs := db.GetFS(FS_IMGS) fs := db.GetFS(FS_IMGS)
return fs.Create(title + ".jpg") return fs.Create(title + ".jpg")
} }

View file

@ -7,8 +7,6 @@ import (
"time" "time"
) )
var db *DB
type Book struct { type Book struct {
Id string `bson:"_id"` Id string `bson:"_id"`
Title string Title string
@ -58,6 +56,12 @@ func (d *DB) Close() {
d.session.Close() d.session.Close()
} }
func (d *DB) Copy() *DB {
dbCopy := new(DB)
dbCopy.session = d.session.Copy()
return dbCopy
}
func md5Pass(pass string) []byte { func md5Pass(pass string) []byte {
h := md5.New() h := md5.New()
hash := h.Sum(([]byte)(PASS_SALT + pass)) hash := h.Sum(([]byte)(PASS_SALT + pass))

40
news.go
View file

@ -14,50 +14,50 @@ type newsEntry struct {
Text string Text string
} }
func newsHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func newsHandler(h handler) {
err := r.ParseForm() err := h.r.ParseForm()
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(h.w, err.Error(), http.StatusInternalServerError)
return return
} }
var data newsData var data newsData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.News = true data.S.News = true
data.News = getNews(NUM_NEWS, 0) data.News = getNews(NUM_NEWS, 0, h.db)
format := r.Form["fmt"] format := h.r.Form["fmt"]
if (len(format) > 0) && (format[0] == "rss") { if (len(format) > 0) && (format[0] == "rss") {
loadTxtTemplate(w, "news_rss.xml", data) loadTxtTemplate(h.w, "news_rss.xml", data)
} else { } else {
loadTemplate(w, "news", data) loadTemplate(h.w, "news", data)
} }
} }
func editNewsHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func editNewsHandler(h handler) {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
var data statusData var data statusData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.News = true data.S.News = true
loadTemplate(w, "edit_news", data) loadTemplate(h.w, "edit_news", data)
} }
func postNewsHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func postNewsHandler(h handler) {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
text := r.FormValue("text") text := h.r.FormValue("text")
db.AddNews(text) h.db.AddNews(text)
http.Redirect(w, r, "/news/", http.StatusFound) http.Redirect(h.w, h.r, "/news/", http.StatusFound)
} }
func getNews(num int, days int) []newsEntry { func getNews(num int, days int, db *DB) []newsEntry {
dbnews, _ := db.GetNews(num, days) dbnews, _ := db.GetNews(num, days)
news := make([]newsEntry, len(dbnews)) news := make([]newsEntry, len(dbnews))
for i, n := range dbnews { for i, n := range dbnews {

View file

@ -129,35 +129,35 @@ func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter {
return chapters return chapters
} }
func readStartHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func readStartHandler(h handler) {
id := mux.Vars(r)["id"] id := mux.Vars(h.r)["id"]
e, _ := openReadEpub(w, r, sess) e, _ := openReadEpub(h)
if e == nil { if e == nil {
notFound(w, r) notFound(h)
return return
} }
defer e.Close() defer e.Close()
it, err := e.Spine() it, err := e.Spine()
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
http.Redirect(w, r, "/read/"+id+"/"+it.URL(), http.StatusTemporaryRedirect) http.Redirect(h.w, h.r, "/read/"+id+"/"+it.URL(), http.StatusTemporaryRedirect)
} }
func readHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func readHandler(h handler) {
id := mux.Vars(r)["id"] id := mux.Vars(h.r)["id"]
file := mux.Vars(r)["file"] file := mux.Vars(h.r)["file"]
e, book := openReadEpub(w, r, sess) e, book := openReadEpub(h)
if e == nil { if e == nil {
notFound(w, r) notFound(h)
return return
} }
defer e.Close() defer e.Close()
var data readData var data readData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.Book = book data.Book = book
if !book.Active { if !book.Active {
data.Back = "/new/" data.Back = "/new/"
@ -168,66 +168,66 @@ func readHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
data.Next, data.Prev = getNextPrev(e, file, id, "/read/") data.Next, data.Prev = getNextPrev(e, file, id, "/read/")
data.Chapters = getChapters(e, file, id, "/read/") data.Chapters = getChapters(e, file, id, "/read/")
data.Content = genLink(id, "/content/", file) data.Content = genLink(id, "/content/", file)
loadTemplate(w, "read", data) loadTemplate(h.w, "read", data)
} }
func openReadEpub(w http.ResponseWriter, r *http.Request, sess *Session) (*epubgo.Epub, Book) { func openReadEpub(h handler) (*epubgo.Epub, Book) {
var book Book var book Book
id := mux.Vars(r)["id"] id := mux.Vars(h.r)["id"]
if !bson.IsObjectIdHex(id) { if !bson.IsObjectIdHex(id) {
return nil, book return nil, book
} }
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if err != nil || len(books) == 0 { if err != nil || len(books) == 0 {
return nil, book return nil, book
} }
book = books[0] book = books[0]
if !book.Active { if !book.Active {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
return nil, book return nil, book
} }
} }
e, err := OpenBook(book.File) e, err := OpenBook(book.File, h.db)
if err != nil { if err != nil {
return nil, book return nil, book
} }
return e, book return e, book
} }
func contentHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func contentHandler(h handler) {
vars := mux.Vars(r) vars := mux.Vars(h.r)
id := vars["id"] id := vars["id"]
file := vars["file"] file := vars["file"]
if file == "" || !bson.IsObjectIdHex(id) { if file == "" || !bson.IsObjectIdHex(id) {
notFound(w, r) notFound(h)
return return
} }
books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
if err != nil || len(books) == 0 { if err != nil || len(books) == 0 {
notFound(w, r) notFound(h)
return return
} }
book := books[0] book := books[0]
if !book.Active { if !book.Active {
if !sess.IsAdmin() { if !h.sess.IsAdmin() {
notFound(w, r) notFound(h)
return return
} }
} }
e, err := OpenBook(book.File) e, err := OpenBook(book.File, h.db)
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
defer e.Close() defer e.Close()
html, err := e.OpenFile(file) html, err := e.OpenFile(file)
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
defer html.Close() defer html.Close()
io.Copy(w, html) io.Copy(h.w, html)
} }

View file

@ -35,25 +35,25 @@ type searchData struct {
Prev string Prev string
} }
func searchHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func searchHandler(h handler) {
err := r.ParseForm() err := h.r.ParseForm()
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(h.w, err.Error(), http.StatusInternalServerError)
return return
} }
req := strings.Join(r.Form["q"], " ") req := strings.Join(h.r.Form["q"], " ")
page := 0 page := 0
if len(r.Form["p"]) != 0 { if len(h.r.Form["p"]) != 0 {
page, err = strconv.Atoi(r.Form["p"][0]) page, err = strconv.Atoi(h.r.Form["p"][0])
if err != nil { if err != nil {
page = 0 page = 0
} }
} }
items_page := itemsPage(r) items_page := itemsPage(h.r)
res, num, _ := db.GetBooks(buildQuery(req), items_page, page*items_page) res, num, _ := h.db.GetBooks(buildQuery(req), items_page, page*items_page)
var data searchData var data searchData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.Search = req data.S.Search = req
data.Books = res data.Books = res
data.ItemsPage = items_page data.ItemsPage = items_page
@ -66,11 +66,11 @@ func searchHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
data.Prev = "/search/?q=" + req + "&p=" + strconv.Itoa(page-1) + "&num=" + strconv.Itoa(items_page) data.Prev = "/search/?q=" + req + "&p=" + strconv.Itoa(page-1) + "&num=" + strconv.Itoa(items_page)
} }
format := r.Form["fmt"] format := h.r.Form["fmt"]
if (len(format) > 0) && (format[0] == "rss") { if (len(format) > 0) && (format[0] == "rss") {
loadTxtTemplate(w, "search_rss.xml", data) loadTxtTemplate(h.w, "search_rss.xml", data)
} else { } else {
loadTemplate(w, "search", data) loadTemplate(h.w, "search", data)
} }
} }

View file

@ -21,7 +21,7 @@ type Session struct {
S *sessions.Session S *sessions.Session
} }
func GetSession(r *http.Request) (s *Session) { func GetSession(r *http.Request, db *DB) (s *Session) {
s = new(Session) s = new(Session)
var err error var err error
s.S, err = sesStore.Get(r, "session") s.S, err = sesStore.Get(r, "session")

View file

@ -9,16 +9,30 @@ import (
"time" "time"
) )
func InitStats() { type handler struct {
statsChannel = make(chan statsRequest, CHAN_SIZE) w http.ResponseWriter
go statsWorker() r *http.Request
sess *Session
db *DB
} }
func GatherStats(function func(http.ResponseWriter, *http.Request, *Session)) func(http.ResponseWriter, *http.Request) { func InitStats(database *DB) {
statsChannel = make(chan statsRequest, CHAN_SIZE)
go statsWorker(database)
}
func GatherStats(function func(handler), database *DB) func(http.ResponseWriter, *http.Request) {
return func(w http.ResponseWriter, r *http.Request) { return func(w http.ResponseWriter, r *http.Request) {
sess := GetSession(r) var h handler
function(w, r, sess) h.db = database.Copy()
statsChannel <- statsRequest{bson.Now(), mux.Vars(r), sess, r} defer h.db.Close()
h.w = w
h.r = r
h.sess = GetSession(r, h.db)
function(h)
statsChannel <- statsRequest{bson.Now(), mux.Vars(r), h.sess, r}
} }
} }
@ -31,7 +45,10 @@ type statsRequest struct {
r *http.Request r *http.Request
} }
func statsWorker() { func statsWorker(database *DB) {
db := database.Copy()
defer db.Close()
for req := range statsChannel { for req := range statsChannel {
stats := make(map[string]interface{}) stats := make(map[string]interface{})
appendFiles(req.r, stats) appendFiles(req.r, stats)
@ -44,15 +61,15 @@ func statsWorker() {
} }
} }
func statsHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func statsHandler(h handler) {
var data statsData var data statsData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.Stats = true data.S.Stats = true
data.Hourly = getHourlyVisits() data.Hourly = getHourlyVisits(h.db)
data.Daily = getDailyVisits() data.Daily = getDailyVisits(h.db)
data.Monthly = getMonthlyVisits() data.Monthly = getMonthlyVisits(h.db)
loadTemplate(w, "stats", data) loadTemplate(h.w, "stats", data)
} }
type statsData struct { type statsData struct {
@ -67,7 +84,7 @@ type visitData struct {
Count int Count int
} }
func getHourlyVisits() []visitData { func getHourlyVisits(db *DB) []visitData {
const numDays = 2 const numDays = 2
var visits []visitData var visits []visitData
@ -84,7 +101,7 @@ func getHourlyVisits() []visitData {
return visits return visits
} }
func getDailyVisits() []visitData { func getDailyVisits(db *DB) []visitData {
const numDays = 30 const numDays = 30
var visits []visitData var visits []visitData
@ -101,7 +118,7 @@ func getDailyVisits() []visitData {
return visits return visits
} }
func getMonthlyVisits() []visitData { func getMonthlyVisits(db *DB) []visitData {
const numDays = 365 const numDays = 365
var visits []visitData var visits []visitData

View file

@ -10,7 +10,7 @@ import (
"strings" "strings"
) )
func OpenBook(id bson.ObjectId) (*epubgo.Epub, error) { func OpenBook(id bson.ObjectId, db *DB) (*epubgo.Epub, error) {
fs := db.GetFS(FS_BOOKS) fs := db.GetFS(FS_BOOKS)
f, err := fs.OpenId(id) f, err := fs.OpenId(id)
if err != nil { if err != nil {
@ -24,7 +24,7 @@ func OpenBook(id bson.ObjectId) (*epubgo.Epub, error) {
return epubgo.Load(reader, int64(len(buff))) return epubgo.Load(reader, int64(len(buff)))
} }
func StoreNewFile(name string, file io.Reader) (bson.ObjectId, int64, error) { func StoreNewFile(name string, file io.Reader, db *DB) (bson.ObjectId, int64, error) {
fs := db.GetFS(FS_BOOKS) fs := db.GetFS(FS_BOOKS)
fw, err := fs.Create(name) fw, err := fs.Create(name)
if err != nil { if err != nil {
@ -37,24 +37,24 @@ func StoreNewFile(name string, file io.Reader) (bson.ObjectId, int64, error) {
return id, size, err return id, size, err
} }
func DeleteFile(id bson.ObjectId) error { func DeleteFile(id bson.ObjectId, db *DB) error {
fs := db.GetFS(FS_BOOKS) fs := db.GetFS(FS_BOOKS)
return fs.RemoveId(id) return fs.RemoveId(id)
} }
func DeleteCover(id bson.ObjectId) error { func DeleteCover(id bson.ObjectId, db *DB) error {
fs := db.GetFS(FS_IMGS) fs := db.GetFS(FS_IMGS)
return fs.RemoveId(id) return fs.RemoveId(id)
} }
func DeleteBook(book Book) { func DeleteBook(book Book, db *DB) {
if book.Cover != "" { if book.Cover != "" {
DeleteCover(book.Cover) DeleteCover(book.Cover, db)
} }
if book.CoverSmall != "" { if book.CoverSmall != "" {
DeleteCover(book.CoverSmall) DeleteCover(book.CoverSmall, db)
} }
DeleteFile(book.File) DeleteFile(book.File, db)
} }
func cleanStr(str string) string { func cleanStr(str string) string {

View file

@ -22,15 +22,14 @@ type Status struct {
Help bool Help bool
} }
func GetStatus(w http.ResponseWriter, r *http.Request) Status { func GetStatus(h handler) Status {
var s Status var s Status
sess := GetSession(r) s.BaseURL = "http://" + h.r.Host
s.BaseURL = "http://" + r.Host s.FullURL = s.BaseURL + h.r.RequestURI
s.FullURL = s.BaseURL + r.RequestURI s.User = h.sess.User
s.User = sess.User s.IsAdmin = h.sess.IsAdmin()
s.IsAdmin = sess.IsAdmin() s.Notif = h.sess.GetNotif()
s.Notif = sess.GetNotif() h.sess.Save(h.w, h.r)
sess.Save(w, r)
return s return s
} }

View file

@ -13,41 +13,41 @@ type statusData struct {
S Status S Status
} }
func aboutHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func aboutHandler(h handler) {
var data statusData var data statusData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.About = true data.S.About = true
loadTemplate(w, "about", data) loadTemplate(h.w, "about", data)
} }
func helpHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func helpHandler(h handler) {
var data statusData var data statusData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.Help = true data.S.Help = true
loadTemplate(w, "help", data) loadTemplate(h.w, "help", data)
} }
func logoutHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func logoutHandler(h handler) {
sess.LogOut() h.sess.LogOut()
sess.Notify("Log out!", "Bye bye "+sess.User, "success") h.sess.Notify("Log out!", "Bye bye "+h.sess.User, "success")
sess.Save(w, r) h.sess.Save(h.w, h.r)
log.Println("User", sess.User, "log out") log.Println("User", h.sess.User, "log out")
http.Redirect(w, r, "/", http.StatusFound) http.Redirect(h.w, h.r, "/", http.StatusFound)
} }
func loginHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func loginHandler(h handler) {
user := r.FormValue("user") user := h.r.FormValue("user")
pass := r.FormValue("pass") pass := h.r.FormValue("pass")
if db.UserValid(user, pass) { if h.db.UserValid(user, pass) {
log.Println("User", user, "log in") log.Println("User", user, "log in")
sess.LogIn(user) h.sess.LogIn(user)
sess.Notify("Successful login!", "Welcome "+user, "success") h.sess.Notify("Successful login!", "Welcome "+user, "success")
} else { } else {
log.Println("User", user, "bad user or password") log.Println("User", user, "bad user or password")
sess.Notify("Invalid login!", "user or password invalid", "error") h.sess.Notify("Invalid login!", "user or password invalid", "error")
} }
sess.Save(w, r) h.sess.Save(h.w, h.r)
http.Redirect(w, r, r.Referer(), http.StatusFound) http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound)
} }
type bookData struct { type bookData struct {
@ -56,62 +56,61 @@ type bookData struct {
Description []string Description []string
} }
func bookHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func bookHandler(h handler) {
idStr := mux.Vars(r)["id"] idStr := mux.Vars(h.r)["id"]
if !bson.IsObjectIdHex(idStr) { if !bson.IsObjectIdHex(idStr) {
notFound(w, r) notFound(h)
return return
} }
var data bookData var data bookData
data.S = GetStatus(w, r) data.S = GetStatus(h)
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil || len(books) == 0 { if err != nil || len(books) == 0 {
notFound(w, r) notFound(h)
return return
} }
data.Book = books[0] data.Book = books[0]
data.Description = strings.Split(data.Book.Description, "\n") data.Description = strings.Split(data.Book.Description, "\n")
loadTemplate(w, "book", data) loadTemplate(h.w, "book", data)
} }
func downloadHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func downloadHandler(h handler) {
idStr := mux.Vars(r)["id"] idStr := mux.Vars(h.r)["id"]
if !bson.IsObjectIdHex(idStr) { if !bson.IsObjectIdHex(idStr) {
notFound(w, r) notFound(h)
return return
} }
id := bson.ObjectIdHex(idStr) id := bson.ObjectIdHex(idStr)
books, _, err := db.GetBooks(bson.M{"_id": id}) books, _, err := h.db.GetBooks(bson.M{"_id": id})
if err != nil || len(books) == 0 { if err != nil || len(books) == 0 {
notFound(w, r) notFound(h)
return return
} }
book := books[0] book := books[0]
if !book.Active { if !book.Active {
sess := GetSession(r) if !h.sess.IsAdmin() {
if !sess.IsAdmin() { notFound(h)
notFound(w, r)
return return
} }
} }
fs := db.GetFS(FS_BOOKS) fs := h.db.GetFS(FS_BOOKS)
f, err := fs.OpenId(book.File) f, err := fs.OpenId(book.File)
if err != nil { if err != nil {
notFound(w, r) notFound(h)
return return
} }
defer f.Close() defer f.Close()
headers := w.Header() headers := h.w.Header()
headers["Content-Type"] = []string{"application/epub+zip"} headers["Content-Type"] = []string{"application/epub+zip"}
headers["Content-Disposition"] = []string{"attachment; filename=\"" + f.Name() + "\""} headers["Content-Disposition"] = []string{"attachment; filename=\"" + f.Name() + "\""}
io.Copy(w, f) io.Copy(h.w, f)
} }
type indexData struct { type indexData struct {
@ -124,68 +123,68 @@ type indexData struct {
News []newsEntry News []newsEntry
} }
func indexHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func indexHandler(h handler) {
var data indexData var data indexData
data.Tags, _ = db.GetTags(TAGS_DISPLAY) data.Tags, _ = h.db.GetTags(TAGS_DISPLAY)
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.Home = true data.S.Home = true
data.Books, data.Count, _ = db.GetBooks(bson.M{"active": true}, 6) data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, 6)
data.VisitedBooks, _ = db.GetVisitedBooks(6) data.VisitedBooks, _ = h.db.GetVisitedBooks(6)
data.DownloadedBooks, _ = db.GetDownloadedBooks(6) data.DownloadedBooks, _ = h.db.GetDownloadedBooks(6)
data.News = getNews(1, DAYS_NEWS_INDEXPAGE) data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db)
loadTemplate(w, "index", data) loadTemplate(h.w, "index", data)
} }
func notFound(w http.ResponseWriter, r *http.Request) { func notFound(h handler) {
var data statusData var data statusData
data.S = GetStatus(w, r) data.S = GetStatus(h)
w.WriteHeader(http.StatusNotFound) h.w.WriteHeader(http.StatusNotFound)
loadTemplate(w, "404", data) loadTemplate(h.w, "404", data)
} }
func main() { func main() {
db = initDB() db := initDB()
defer db.Close() defer db.Close()
InitStats() InitStats(db)
InitUpload() InitUpload(db)
setUpRouter() setUpRouter(db)
panic(http.ListenAndServe(":"+PORT, nil)) panic(http.ListenAndServe(":"+PORT, nil))
} }
func setUpRouter() { func setUpRouter(db *DB) {
r := mux.NewRouter() r := mux.NewRouter()
var notFoundHandler http.HandlerFunc var notFoundHandler http.HandlerFunc
notFoundHandler = GatherStats(func(w http.ResponseWriter, r *http.Request, sess *Session) { notFound(w, r) }) notFoundHandler = GatherStats(notFound, db)
r.NotFoundHandler = notFoundHandler r.NotFoundHandler = notFoundHandler
r.HandleFunc("/", GatherStats(indexHandler)) r.HandleFunc("/", GatherStats(indexHandler, db))
r.HandleFunc("/book/{id:[0-9a-fA-F]+}", GatherStats(bookHandler)) r.HandleFunc("/book/{id:[0-9a-fA-F]+}", GatherStats(bookHandler, db))
r.HandleFunc("/search/", GatherStats(searchHandler)) r.HandleFunc("/search/", GatherStats(searchHandler, db))
r.HandleFunc("/upload/", GatherStats(uploadHandler)).Methods("GET") r.HandleFunc("/upload/", GatherStats(uploadHandler, db)).Methods("GET")
r.HandleFunc("/upload/", GatherStats(uploadPostHandler)).Methods("POST") r.HandleFunc("/upload/", GatherStats(uploadPostHandler, db)).Methods("POST")
r.HandleFunc("/login/", GatherStats(loginHandler)).Methods("POST") r.HandleFunc("/login/", GatherStats(loginHandler, db)).Methods("POST")
r.HandleFunc("/logout/", GatherStats(logoutHandler)) r.HandleFunc("/logout/", GatherStats(logoutHandler, db))
r.HandleFunc("/new/", GatherStats(newHandler)) r.HandleFunc("/new/", GatherStats(newHandler, db))
r.HandleFunc("/store/{ids:([0-9a-fA-F]+/)+}", GatherStats(storeHandler)) r.HandleFunc("/store/{ids:([0-9a-fA-F]+/)+}", GatherStats(storeHandler, db))
r.HandleFunc("/delete/{ids:([0-9a-fA-F]+/)+}", GatherStats(deleteHandler)) r.HandleFunc("/delete/{ids:([0-9a-fA-F]+/)+}", GatherStats(deleteHandler, db))
r.HandleFunc("/read/{id:[0-9a-fA-F]+}", GatherStats(readStartHandler)) r.HandleFunc("/read/{id:[0-9a-fA-F]+}", GatherStats(readStartHandler, db))
r.HandleFunc("/read/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(readHandler)) r.HandleFunc("/read/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(readHandler, db))
r.HandleFunc("/content/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(contentHandler)) r.HandleFunc("/content/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(contentHandler, db))
r.HandleFunc("/edit/{id:[0-9a-fA-F]+}", GatherStats(editHandler)) r.HandleFunc("/edit/{id:[0-9a-fA-F]+}", GatherStats(editHandler, db))
r.HandleFunc("/save/{id:[0-9a-fA-F]+}", GatherStats(saveHandler)).Methods("POST") r.HandleFunc("/save/{id:[0-9a-fA-F]+}", GatherStats(saveHandler, db)).Methods("POST")
r.HandleFunc("/about/", GatherStats(aboutHandler)) r.HandleFunc("/about/", GatherStats(aboutHandler, db))
r.HandleFunc("/help/", GatherStats(helpHandler)) r.HandleFunc("/help/", GatherStats(helpHandler, db))
r.HandleFunc("/download/{id:[0-9a-fA-F]+}/{epub:.*}", GatherStats(downloadHandler)) r.HandleFunc("/download/{id:[0-9a-fA-F]+}/{epub:.*}", GatherStats(downloadHandler, db))
r.HandleFunc("/cover/{id:[0-9a-fA-F]+}/{size}/{img:.*}", coverHandler) r.HandleFunc("/cover/{id:[0-9a-fA-F]+}/{size}/{img:.*}", GatherStats(coverHandler, db))
r.HandleFunc("/settings/", GatherStats(settingsHandler)) r.HandleFunc("/settings/", GatherStats(settingsHandler, db))
r.HandleFunc("/stats/", GatherStats(statsHandler)) r.HandleFunc("/stats/", GatherStats(statsHandler, db))
r.HandleFunc("/news/", GatherStats(newsHandler)) r.HandleFunc("/news/", GatherStats(newsHandler, db))
r.HandleFunc("/news/edit", GatherStats(editNewsHandler)).Methods("GET") r.HandleFunc("/news/edit", GatherStats(editNewsHandler, db)).Methods("GET")
r.HandleFunc("/news/edit", GatherStats(postNewsHandler)).Methods("POST") r.HandleFunc("/news/edit", GatherStats(postNewsHandler, db)).Methods("POST")
h := http.FileServer(http.Dir(IMG_PATH)) h := http.FileServer(http.Dir(IMG_PATH))
r.Handle("/img/{img}", http.StripPrefix("/img/", h)) r.Handle("/img/{img}", http.StripPrefix("/img/", h))
h = http.FileServer(http.Dir(CSS_PATH)) h = http.FileServer(http.Dir(CSS_PATH))

View file

@ -6,13 +6,12 @@ import (
"io/ioutil" "io/ioutil"
"log" "log"
"mime/multipart" "mime/multipart"
"net/http"
"strings" "strings"
) )
func InitUpload() { func InitUpload(database *DB) {
uploadChannel = make(chan uploadRequest, CHAN_SIZE) uploadChannel = make(chan uploadRequest, CHAN_SIZE)
go uploadWorker() go uploadWorker(database)
} }
var uploadChannel chan uploadRequest var uploadChannel chan uploadRequest
@ -22,13 +21,16 @@ type uploadRequest struct {
filename string filename string
} }
func uploadWorker() { func uploadWorker(database *DB) {
db := database.Copy()
defer db.Close()
for req := range uploadChannel { for req := range uploadChannel {
processFile(req) processFile(req, db)
} }
} }
func processFile(req uploadRequest) { func processFile(req uploadRequest, db *DB) {
defer req.file.Close() defer req.file.Close()
epub, err := openMultipartEpub(req.file) epub, err := openMultipartEpub(req.file)
@ -38,10 +40,10 @@ func processFile(req uploadRequest) {
} }
defer epub.Close() defer epub.Close()
book := parseFile(epub) book := parseFile(epub, db)
title, _ := book["title"].(string) title, _ := book["title"].(string)
req.file.Seek(0, 0) req.file.Seek(0, 0)
id, size, err := StoreNewFile(title+".epub", req.file) id, size, err := StoreNewFile(title+".epub", req.file, db)
if err != nil { if err != nil {
log.Println("Error storing book (", title, "):", err) log.Println("Error storing book (", title, "):", err)
return return
@ -57,16 +59,16 @@ func processFile(req uploadRequest) {
log.Println("File uploaded:", req.filename) log.Println("File uploaded:", req.filename)
} }
func uploadPostHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func uploadPostHandler(h handler) {
problem := false problem := false
r.ParseMultipartForm(20000000) h.r.ParseMultipartForm(20000000)
filesForm := r.MultipartForm.File["epub"] filesForm := h.r.MultipartForm.File["epub"]
for _, f := range filesForm { for _, f := range filesForm {
file, err := f.Open() file, err := f.Open()
if err != nil { if err != nil {
log.Println("Can not open uploaded file", f.Filename, ":", err) log.Println("Can not open uploaded file", f.Filename, ":", err)
sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error") h.sess.Notify("Upload problem!", "There was a problem with book "+f.Filename, "error")
problem = true problem = true
continue continue
} }
@ -75,19 +77,19 @@ func uploadPostHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
if !problem { if !problem {
if len(filesForm) > 0 { if len(filesForm) > 0 {
sess.Notify("Upload successful!", "Thank you for your contribution", "success") h.sess.Notify("Upload successful!", "Thank you for your contribution", "success")
} else { } else {
sess.Notify("Upload problem!", "No books where uploaded.", "error") h.sess.Notify("Upload problem!", "No books where uploaded.", "error")
} }
} }
uploadHandler(w, r, sess) uploadHandler(h)
} }
func uploadHandler(w http.ResponseWriter, r *http.Request, sess *Session) { func uploadHandler(h handler) {
var data uploadData var data uploadData
data.S = GetStatus(w, r) data.S = GetStatus(h)
data.S.Upload = true data.S.Upload = true
loadTemplate(w, "upload", data) loadTemplate(h.w, "upload", data)
} }
type uploadData struct { type uploadData struct {
@ -100,7 +102,7 @@ func openMultipartEpub(file multipart.File) (*epubgo.Epub, error) {
return epubgo.Load(reader, int64(len(buff))) return epubgo.Load(reader, int64(len(buff)))
} }
func parseFile(epub *epubgo.Epub) map[string]interface{} { func parseFile(epub *epubgo.Epub, db *DB) map[string]interface{} {
book := map[string]interface{}{} book := map[string]interface{}{}
for _, m := range epub.MetadataFields() { for _, m := range epub.MetadataFields() {
data, err := epub.Metadata(m) data, err := epub.Metadata(m)
@ -133,7 +135,7 @@ func parseFile(epub *epubgo.Epub) map[string]interface{} {
} }
title, _ := book["title"].(string) title, _ := book["title"].(string)
book["file"] = nil book["file"] = nil
cover, coverSmall := GetCover(epub, title) cover, coverSmall := GetCover(epub, title, db)
if cover != "" { if cover != "" {
book["cover"] = cover book["cover"] = cover
book["coversmall"] = coverSmall book["coversmall"] = coverSmall