Database stops being a global variable
With it now every handler creates it's own copy of the session.
This commit is contained in:
parent
cef68a8f6e
commit
41b376992a
12 changed files with 318 additions and 299 deletions
150
admin.go
150
admin.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
48
cover.go
48
cover.go
|
@ -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")
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
40
news.go
|
@ -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 {
|
||||||
|
|
58
reader.go
58
reader.go
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
24
search.go
24
search.go
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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")
|
||||||
|
|
51
stats.go
51
stats.go
|
@ -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
|
||||||
|
|
||||||
|
|
16
store.go
16
store.go
|
@ -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 {
|
||||||
|
|
15
template.go
15
template.go
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
163
trantor.go
163
trantor.go
|
@ -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))
|
||||||
|
|
42
upload.go
42
upload.go
|
@ -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
|
||||||
|
|
Reference in a new issue