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
|
||||
}
|
||||
|
||||
func settingsHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
if sess.User == "" {
|
||||
notFound(w, r)
|
||||
func settingsHandler(h handler) {
|
||||
if h.sess.User == "" {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
if r.Method == "POST" {
|
||||
current_pass := r.FormValue("currpass")
|
||||
pass1 := r.FormValue("password1")
|
||||
pass2 := r.FormValue("password2")
|
||||
if h.r.Method == "POST" {
|
||||
current_pass := h.r.FormValue("currpass")
|
||||
pass1 := h.r.FormValue("password1")
|
||||
pass2 := h.r.FormValue("password2")
|
||||
switch {
|
||||
case !db.UserValid(sess.User, current_pass):
|
||||
sess.Notify("Password error!", "The current password given don't match with the user password. Try again", "error")
|
||||
case !h.db.UserValid(h.sess.User, current_pass):
|
||||
h.sess.Notify("Password error!", "The current password given don't match with the user password. Try again", "error")
|
||||
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:
|
||||
db.SetPassword(sess.User, pass1)
|
||||
sess.Notify("Password updated!", "Your new password is correctly set.", "success")
|
||||
h.db.SetPassword(h.sess.User, pass1)
|
||||
h.sess.Notify("Password updated!", "Your new password is correctly set.", "success")
|
||||
}
|
||||
}
|
||||
|
||||
var data settingsData
|
||||
data.S = GetStatus(w, r)
|
||||
loadTemplate(w, "settings", data)
|
||||
data.S = GetStatus(h)
|
||||
loadTemplate(h.w, "settings", data)
|
||||
}
|
||||
|
||||
func deleteHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
func deleteHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var titles []string
|
||||
var isNew bool
|
||||
ids := strings.Split(mux.Vars(r)["ids"], "/")
|
||||
ids := strings.Split(mux.Vars(h.r)["ids"], "/")
|
||||
for _, idStr := range ids {
|
||||
if !bson.IsObjectIdHex(idStr) {
|
||||
continue
|
||||
}
|
||||
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
books, _, err := h.db.GetBooks(bson.M{"_id": id})
|
||||
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
|
||||
}
|
||||
book := books[0]
|
||||
DeleteBook(book)
|
||||
db.RemoveBook(id)
|
||||
DeleteBook(book, h.db)
|
||||
h.db.RemoveBook(id)
|
||||
|
||||
if !book.Active {
|
||||
isNew = true
|
||||
|
@ -68,33 +68,33 @@ func deleteHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
|||
titles = append(titles, book.Title)
|
||||
}
|
||||
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 {
|
||||
http.Redirect(w, r, "/new/", http.StatusFound)
|
||||
http.Redirect(h.w, h.r, "/new/", http.StatusFound)
|
||||
} 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) {
|
||||
idStr := mux.Vars(r)["id"]
|
||||
if !sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
|
||||
notFound(w, r)
|
||||
func editHandler(h handler) {
|
||||
idStr := mux.Vars(h.r)["id"]
|
||||
if !h.sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
books, _, err := h.db.GetBooks(bson.M{"_id": id})
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var data bookData
|
||||
data.Book = books[0]
|
||||
data.S = GetStatus(w, r)
|
||||
loadTemplate(w, "edit", data)
|
||||
data.S = GetStatus(h)
|
||||
loadTemplate(h.w, "edit", data)
|
||||
}
|
||||
|
||||
func cleanEmptyStr(s []string) []string {
|
||||
|
@ -107,21 +107,21 @@ func cleanEmptyStr(s []string) []string {
|
|||
return res
|
||||
}
|
||||
|
||||
func saveHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
idStr := mux.Vars(r)["id"]
|
||||
if !sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
|
||||
notFound(w, r)
|
||||
func saveHandler(h handler) {
|
||||
idStr := mux.Vars(h.r)["id"]
|
||||
if !h.sess.IsAdmin() || !bson.IsObjectIdHex(idStr) {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
title := r.FormValue("title")
|
||||
publisher := r.FormValue("publisher")
|
||||
date := r.FormValue("date")
|
||||
description := r.FormValue("description")
|
||||
author := cleanEmptyStr(r.Form["author"])
|
||||
subject := cleanEmptyStr(r.Form["subject"])
|
||||
lang := cleanEmptyStr(r.Form["lang"])
|
||||
title := h.r.FormValue("title")
|
||||
publisher := h.r.FormValue("publisher")
|
||||
date := h.r.FormValue("date")
|
||||
description := h.r.FormValue("description")
|
||||
author := cleanEmptyStr(h.r.Form["author"])
|
||||
subject := cleanEmptyStr(h.r.Form["subject"])
|
||||
lang := cleanEmptyStr(h.r.Form["lang"])
|
||||
book := map[string]interface{}{"title": title,
|
||||
"publisher": publisher,
|
||||
"date": date,
|
||||
|
@ -130,18 +130,18 @@ func saveHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
|||
"subject": subject,
|
||||
"lang": lang}
|
||||
book["keywords"] = keywords(book)
|
||||
err := db.UpdateBook(id, book)
|
||||
err := h.db.UpdateBook(id, book)
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
sess.Notify("Book Modified!", "", "success")
|
||||
sess.Save(w, r)
|
||||
if db.BookActive(id) {
|
||||
http.Redirect(w, r, "/book/"+idStr, http.StatusFound)
|
||||
h.sess.Notify("Book Modified!", "", "success")
|
||||
h.sess.Save(h.w, h.r)
|
||||
if h.db.BookActive(id) {
|
||||
http.Redirect(h.w, h.r, "/book/"+idStr, http.StatusFound)
|
||||
} 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
|
||||
}
|
||||
|
||||
func newHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
func newHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
err := r.ParseForm()
|
||||
err := h.r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(h.w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
page := 0
|
||||
if len(r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(r.Form["p"][0])
|
||||
if len(h.r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(h.r.Form["p"][0])
|
||||
if err != nil {
|
||||
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
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.Found = num
|
||||
if num-NEW_ITEMS_PAGE*page < NEW_ITEMS_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 {
|
||||
data.Books[i].B = b
|
||||
_, data.Books[i].TitleFound, _ = db.GetBooks(buildQuery("title:"+b.Title), 1)
|
||||
_, data.Books[i].AuthorFound, _ = db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1)
|
||||
_, data.Books[i].TitleFound, _ = h.db.GetBooks(buildQuery("title:"+b.Title), 1)
|
||||
_, data.Books[i].AuthorFound, _ = h.db.GetBooks(buildQuery("author:"+strings.Join(b.Author, " author:")), 1)
|
||||
}
|
||||
data.Page = page + 1
|
||||
if num > (page+1)*NEW_ITEMS_PAGE {
|
||||
|
@ -199,40 +199,40 @@ func newHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
|||
if page > 0 {
|
||||
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) {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
func storeHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var titles []string
|
||||
ids := strings.Split(mux.Vars(r)["ids"], "/")
|
||||
ids := strings.Split(mux.Vars(h.r)["ids"], "/")
|
||||
for _, idStr := range ids {
|
||||
if !bson.IsObjectIdHex(idStr) {
|
||||
continue
|
||||
}
|
||||
|
||||
id := bson.ObjectIdHex(idStr)
|
||||
books, _, err := db.GetBooks(bson.M{"_id": id})
|
||||
books, _, err := h.db.GetBooks(bson.M{"_id": id})
|
||||
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
|
||||
}
|
||||
book := books[0]
|
||||
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())
|
||||
continue
|
||||
}
|
||||
db.UpdateBook(id, bson.M{"active": true})
|
||||
h.db.UpdateBook(id, bson.M{"active": true})
|
||||
titles = append(titles, book.Title)
|
||||
}
|
||||
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)
|
||||
http.Redirect(w, r, "/new/", http.StatusFound)
|
||||
h.sess.Save(h.w, h.r)
|
||||
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/bson"
|
||||
"log"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func coverHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
func coverHandler(h handler) {
|
||||
vars := mux.Vars(h.r)
|
||||
if !bson.IsObjectIdHex(vars["id"]) {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
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 {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
|
||||
if !book.Active {
|
||||
sess := GetSession(r)
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fs := db.GetFS(FS_IMGS)
|
||||
fs := h.db.GetFS(FS_IMGS)
|
||||
var f *mgo.GridFile
|
||||
if vars["size"] == "small" {
|
||||
f, err = fs.OpenId(book.CoverSmall)
|
||||
|
@ -52,24 +50,24 @@ func coverHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
if err != nil {
|
||||
log.Println("Error while opening image:", err)
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
headers := w.Header()
|
||||
headers := h.w.Header()
|
||||
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) {
|
||||
imgId, smallId := coverFromMetadata(e, title)
|
||||
func GetCover(e *epubgo.Epub, title string, db *DB) (bson.ObjectId, bson.ObjectId) {
|
||||
imgId, smallId := coverFromMetadata(e, title, db)
|
||||
if imgId != "" {
|
||||
return imgId, smallId
|
||||
}
|
||||
|
||||
imgId, smallId = searchCommonCoverNames(e, title)
|
||||
imgId, smallId = searchCommonCoverNames(e, title, db)
|
||||
if imgId != "" {
|
||||
return imgId, smallId
|
||||
}
|
||||
|
@ -110,7 +108,7 @@ func GetCover(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) {
|
|||
img, err := e.OpenFile(url)
|
||||
if err == nil {
|
||||
defer img.Close()
|
||||
return storeImg(img, title)
|
||||
return storeImg(img, title, db)
|
||||
}
|
||||
}
|
||||
errNext = it.Next()
|
||||
|
@ -118,41 +116,41 @@ func GetCover(e *epubgo.Epub, title string) (bson.ObjectId, bson.ObjectId) {
|
|||
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")
|
||||
for _, meta := range metaList {
|
||||
if meta["name"] == "cover" {
|
||||
img, err := e.OpenFileId(meta["content"])
|
||||
if err == nil {
|
||||
defer img.Close()
|
||||
return storeImg(img, title)
|
||||
return storeImg(img, title, db)
|
||||
}
|
||||
}
|
||||
}
|
||||
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"} {
|
||||
img, err := e.OpenFile(p)
|
||||
if err == nil {
|
||||
defer img.Close()
|
||||
return storeImg(img, title)
|
||||
return storeImg(img, title, db)
|
||||
}
|
||||
}
|
||||
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 */
|
||||
fBig, err := createCoverFile(title)
|
||||
fBig, err := createCoverFile(title, db)
|
||||
if err != nil {
|
||||
log.Println("Error creating", title, ":", err.Error())
|
||||
return "", ""
|
||||
}
|
||||
defer fBig.Close()
|
||||
|
||||
fSmall, err := createCoverFile(title + "_small")
|
||||
fSmall, err := createCoverFile(title+"_small", db)
|
||||
if err != nil {
|
||||
log.Println("Error creating", title+"_small", ":", err.Error())
|
||||
return "", ""
|
||||
|
@ -189,7 +187,7 @@ func storeImg(img io.Reader, title string) (bson.ObjectId, bson.ObjectId) {
|
|||
return idBig, idSmall
|
||||
}
|
||||
|
||||
func createCoverFile(title string) (*mgo.GridFile, error) {
|
||||
func createCoverFile(title string, db *DB) (*mgo.GridFile, error) {
|
||||
fs := db.GetFS(FS_IMGS)
|
||||
return fs.Create(title + ".jpg")
|
||||
}
|
||||
|
|
|
@ -7,8 +7,6 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
var db *DB
|
||||
|
||||
type Book struct {
|
||||
Id string `bson:"_id"`
|
||||
Title string
|
||||
|
@ -58,6 +56,12 @@ func (d *DB) Close() {
|
|||
d.session.Close()
|
||||
}
|
||||
|
||||
func (d *DB) Copy() *DB {
|
||||
dbCopy := new(DB)
|
||||
dbCopy.session = d.session.Copy()
|
||||
return dbCopy
|
||||
}
|
||||
|
||||
func md5Pass(pass string) []byte {
|
||||
h := md5.New()
|
||||
hash := h.Sum(([]byte)(PASS_SALT + pass))
|
||||
|
|
40
news.go
40
news.go
|
@ -14,50 +14,50 @@ type newsEntry struct {
|
|||
Text string
|
||||
}
|
||||
|
||||
func newsHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
err := r.ParseForm()
|
||||
func newsHandler(h handler) {
|
||||
err := h.r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(h.w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
var data newsData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
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") {
|
||||
loadTxtTemplate(w, "news_rss.xml", data)
|
||||
loadTxtTemplate(h.w, "news_rss.xml", data)
|
||||
} else {
|
||||
loadTemplate(w, "news", data)
|
||||
loadTemplate(h.w, "news", data)
|
||||
}
|
||||
}
|
||||
|
||||
func editNewsHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
func editNewsHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var data statusData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
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) {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
func postNewsHandler(h handler) {
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
text := r.FormValue("text")
|
||||
db.AddNews(text)
|
||||
http.Redirect(w, r, "/news/", http.StatusFound)
|
||||
text := h.r.FormValue("text")
|
||||
h.db.AddNews(text)
|
||||
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)
|
||||
news := make([]newsEntry, len(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
|
||||
}
|
||||
|
||||
func readStartHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
id := mux.Vars(r)["id"]
|
||||
e, _ := openReadEpub(w, r, sess)
|
||||
func readStartHandler(h handler) {
|
||||
id := mux.Vars(h.r)["id"]
|
||||
e, _ := openReadEpub(h)
|
||||
if e == nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
defer e.Close()
|
||||
|
||||
it, err := e.Spine()
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
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) {
|
||||
id := mux.Vars(r)["id"]
|
||||
file := mux.Vars(r)["file"]
|
||||
e, book := openReadEpub(w, r, sess)
|
||||
func readHandler(h handler) {
|
||||
id := mux.Vars(h.r)["id"]
|
||||
file := mux.Vars(h.r)["file"]
|
||||
e, book := openReadEpub(h)
|
||||
if e == nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
defer e.Close()
|
||||
|
||||
var data readData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.Book = book
|
||||
if !book.Active {
|
||||
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.Chapters = getChapters(e, file, id, "/read/")
|
||||
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
|
||||
id := mux.Vars(r)["id"]
|
||||
id := mux.Vars(h.r)["id"]
|
||||
if !bson.IsObjectIdHex(id) {
|
||||
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 {
|
||||
return nil, book
|
||||
}
|
||||
|
||||
book = books[0]
|
||||
if !book.Active {
|
||||
if !sess.IsAdmin() {
|
||||
if !h.sess.IsAdmin() {
|
||||
return nil, book
|
||||
}
|
||||
}
|
||||
e, err := OpenBook(book.File)
|
||||
e, err := OpenBook(book.File, h.db)
|
||||
if err != nil {
|
||||
return nil, book
|
||||
}
|
||||
return e, book
|
||||
}
|
||||
|
||||
func contentHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
vars := mux.Vars(r)
|
||||
func contentHandler(h handler) {
|
||||
vars := mux.Vars(h.r)
|
||||
id := vars["id"]
|
||||
file := vars["file"]
|
||||
if file == "" || !bson.IsObjectIdHex(id) {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
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 {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
if !book.Active {
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
}
|
||||
e, err := OpenBook(book.File)
|
||||
e, err := OpenBook(book.File, h.db)
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
defer e.Close()
|
||||
|
||||
html, err := e.OpenFile(file)
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
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
|
||||
}
|
||||
|
||||
func searchHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
err := r.ParseForm()
|
||||
func searchHandler(h handler) {
|
||||
err := h.r.ParseForm()
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
http.Error(h.w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
req := strings.Join(r.Form["q"], " ")
|
||||
req := strings.Join(h.r.Form["q"], " ")
|
||||
page := 0
|
||||
if len(r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(r.Form["p"][0])
|
||||
if len(h.r.Form["p"]) != 0 {
|
||||
page, err = strconv.Atoi(h.r.Form["p"][0])
|
||||
if err != nil {
|
||||
page = 0
|
||||
}
|
||||
}
|
||||
items_page := itemsPage(r)
|
||||
res, num, _ := db.GetBooks(buildQuery(req), items_page, page*items_page)
|
||||
items_page := itemsPage(h.r)
|
||||
res, num, _ := h.db.GetBooks(buildQuery(req), items_page, page*items_page)
|
||||
|
||||
var data searchData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.S.Search = req
|
||||
data.Books = res
|
||||
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)
|
||||
}
|
||||
|
||||
format := r.Form["fmt"]
|
||||
format := h.r.Form["fmt"]
|
||||
if (len(format) > 0) && (format[0] == "rss") {
|
||||
loadTxtTemplate(w, "search_rss.xml", data)
|
||||
loadTxtTemplate(h.w, "search_rss.xml", data)
|
||||
} else {
|
||||
loadTemplate(w, "search", data)
|
||||
loadTemplate(h.w, "search", data)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ type Session struct {
|
|||
S *sessions.Session
|
||||
}
|
||||
|
||||
func GetSession(r *http.Request) (s *Session) {
|
||||
func GetSession(r *http.Request, db *DB) (s *Session) {
|
||||
s = new(Session)
|
||||
var err error
|
||||
s.S, err = sesStore.Get(r, "session")
|
||||
|
|
51
stats.go
51
stats.go
|
@ -9,16 +9,30 @@ import (
|
|||
"time"
|
||||
)
|
||||
|
||||
func InitStats() {
|
||||
statsChannel = make(chan statsRequest, CHAN_SIZE)
|
||||
go statsWorker()
|
||||
type handler struct {
|
||||
w http.ResponseWriter
|
||||
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) {
|
||||
sess := GetSession(r)
|
||||
function(w, r, sess)
|
||||
statsChannel <- statsRequest{bson.Now(), mux.Vars(r), sess, r}
|
||||
var h handler
|
||||
h.db = database.Copy()
|
||||
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
|
||||
}
|
||||
|
||||
func statsWorker() {
|
||||
func statsWorker(database *DB) {
|
||||
db := database.Copy()
|
||||
defer db.Close()
|
||||
|
||||
for req := range statsChannel {
|
||||
stats := make(map[string]interface{})
|
||||
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
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.S.Stats = true
|
||||
data.Hourly = getHourlyVisits()
|
||||
data.Daily = getDailyVisits()
|
||||
data.Monthly = getMonthlyVisits()
|
||||
data.Hourly = getHourlyVisits(h.db)
|
||||
data.Daily = getDailyVisits(h.db)
|
||||
data.Monthly = getMonthlyVisits(h.db)
|
||||
|
||||
loadTemplate(w, "stats", data)
|
||||
loadTemplate(h.w, "stats", data)
|
||||
}
|
||||
|
||||
type statsData struct {
|
||||
|
@ -67,7 +84,7 @@ type visitData struct {
|
|||
Count int
|
||||
}
|
||||
|
||||
func getHourlyVisits() []visitData {
|
||||
func getHourlyVisits(db *DB) []visitData {
|
||||
const numDays = 2
|
||||
var visits []visitData
|
||||
|
||||
|
@ -84,7 +101,7 @@ func getHourlyVisits() []visitData {
|
|||
return visits
|
||||
}
|
||||
|
||||
func getDailyVisits() []visitData {
|
||||
func getDailyVisits(db *DB) []visitData {
|
||||
const numDays = 30
|
||||
var visits []visitData
|
||||
|
||||
|
@ -101,7 +118,7 @@ func getDailyVisits() []visitData {
|
|||
return visits
|
||||
}
|
||||
|
||||
func getMonthlyVisits() []visitData {
|
||||
func getMonthlyVisits(db *DB) []visitData {
|
||||
const numDays = 365
|
||||
var visits []visitData
|
||||
|
||||
|
|
16
store.go
16
store.go
|
@ -10,7 +10,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
func OpenBook(id bson.ObjectId) (*epubgo.Epub, error) {
|
||||
func OpenBook(id bson.ObjectId, db *DB) (*epubgo.Epub, error) {
|
||||
fs := db.GetFS(FS_BOOKS)
|
||||
f, err := fs.OpenId(id)
|
||||
if err != nil {
|
||||
|
@ -24,7 +24,7 @@ func OpenBook(id bson.ObjectId) (*epubgo.Epub, error) {
|
|||
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)
|
||||
fw, err := fs.Create(name)
|
||||
if err != nil {
|
||||
|
@ -37,24 +37,24 @@ func StoreNewFile(name string, file io.Reader) (bson.ObjectId, int64, error) {
|
|||
return id, size, err
|
||||
}
|
||||
|
||||
func DeleteFile(id bson.ObjectId) error {
|
||||
func DeleteFile(id bson.ObjectId, db *DB) error {
|
||||
fs := db.GetFS(FS_BOOKS)
|
||||
return fs.RemoveId(id)
|
||||
}
|
||||
|
||||
func DeleteCover(id bson.ObjectId) error {
|
||||
func DeleteCover(id bson.ObjectId, db *DB) error {
|
||||
fs := db.GetFS(FS_IMGS)
|
||||
return fs.RemoveId(id)
|
||||
}
|
||||
|
||||
func DeleteBook(book Book) {
|
||||
func DeleteBook(book Book, db *DB) {
|
||||
if book.Cover != "" {
|
||||
DeleteCover(book.Cover)
|
||||
DeleteCover(book.Cover, db)
|
||||
}
|
||||
if book.CoverSmall != "" {
|
||||
DeleteCover(book.CoverSmall)
|
||||
DeleteCover(book.CoverSmall, db)
|
||||
}
|
||||
DeleteFile(book.File)
|
||||
DeleteFile(book.File, db)
|
||||
}
|
||||
|
||||
func cleanStr(str string) string {
|
||||
|
|
15
template.go
15
template.go
|
@ -22,15 +22,14 @@ type Status struct {
|
|||
Help bool
|
||||
}
|
||||
|
||||
func GetStatus(w http.ResponseWriter, r *http.Request) Status {
|
||||
func GetStatus(h handler) Status {
|
||||
var s Status
|
||||
sess := GetSession(r)
|
||||
s.BaseURL = "http://" + r.Host
|
||||
s.FullURL = s.BaseURL + r.RequestURI
|
||||
s.User = sess.User
|
||||
s.IsAdmin = sess.IsAdmin()
|
||||
s.Notif = sess.GetNotif()
|
||||
sess.Save(w, r)
|
||||
s.BaseURL = "http://" + h.r.Host
|
||||
s.FullURL = s.BaseURL + h.r.RequestURI
|
||||
s.User = h.sess.User
|
||||
s.IsAdmin = h.sess.IsAdmin()
|
||||
s.Notif = h.sess.GetNotif()
|
||||
h.sess.Save(h.w, h.r)
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
163
trantor.go
163
trantor.go
|
@ -13,41 +13,41 @@ type statusData struct {
|
|||
S Status
|
||||
}
|
||||
|
||||
func aboutHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
func aboutHandler(h handler) {
|
||||
var data statusData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
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
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.S.Help = true
|
||||
loadTemplate(w, "help", data)
|
||||
loadTemplate(h.w, "help", data)
|
||||
}
|
||||
|
||||
func logoutHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
sess.LogOut()
|
||||
sess.Notify("Log out!", "Bye bye "+sess.User, "success")
|
||||
sess.Save(w, r)
|
||||
log.Println("User", sess.User, "log out")
|
||||
http.Redirect(w, r, "/", http.StatusFound)
|
||||
func logoutHandler(h handler) {
|
||||
h.sess.LogOut()
|
||||
h.sess.Notify("Log out!", "Bye bye "+h.sess.User, "success")
|
||||
h.sess.Save(h.w, h.r)
|
||||
log.Println("User", h.sess.User, "log out")
|
||||
http.Redirect(h.w, h.r, "/", http.StatusFound)
|
||||
}
|
||||
|
||||
func loginHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
user := r.FormValue("user")
|
||||
pass := r.FormValue("pass")
|
||||
if db.UserValid(user, pass) {
|
||||
func loginHandler(h handler) {
|
||||
user := h.r.FormValue("user")
|
||||
pass := h.r.FormValue("pass")
|
||||
if h.db.UserValid(user, pass) {
|
||||
log.Println("User", user, "log in")
|
||||
sess.LogIn(user)
|
||||
sess.Notify("Successful login!", "Welcome "+user, "success")
|
||||
h.sess.LogIn(user)
|
||||
h.sess.Notify("Successful login!", "Welcome "+user, "success")
|
||||
} else {
|
||||
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)
|
||||
http.Redirect(w, r, r.Referer(), http.StatusFound)
|
||||
h.sess.Save(h.w, h.r)
|
||||
http.Redirect(h.w, h.r, h.r.Referer(), http.StatusFound)
|
||||
}
|
||||
|
||||
type bookData struct {
|
||||
|
@ -56,62 +56,61 @@ type bookData struct {
|
|||
Description []string
|
||||
}
|
||||
|
||||
func bookHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
idStr := mux.Vars(r)["id"]
|
||||
func bookHandler(h handler) {
|
||||
idStr := mux.Vars(h.r)["id"]
|
||||
if !bson.IsObjectIdHex(idStr) {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
var data bookData
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
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 {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
data.Book = books[0]
|
||||
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) {
|
||||
idStr := mux.Vars(r)["id"]
|
||||
func downloadHandler(h handler) {
|
||||
idStr := mux.Vars(h.r)["id"]
|
||||
if !bson.IsObjectIdHex(idStr) {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
|
||||
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 {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
book := books[0]
|
||||
|
||||
if !book.Active {
|
||||
sess := GetSession(r)
|
||||
if !sess.IsAdmin() {
|
||||
notFound(w, r)
|
||||
if !h.sess.IsAdmin() {
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
fs := db.GetFS(FS_BOOKS)
|
||||
fs := h.db.GetFS(FS_BOOKS)
|
||||
f, err := fs.OpenId(book.File)
|
||||
if err != nil {
|
||||
notFound(w, r)
|
||||
notFound(h)
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
headers := w.Header()
|
||||
headers := h.w.Header()
|
||||
headers["Content-Type"] = []string{"application/epub+zip"}
|
||||
headers["Content-Disposition"] = []string{"attachment; filename=\"" + f.Name() + "\""}
|
||||
|
||||
io.Copy(w, f)
|
||||
io.Copy(h.w, f)
|
||||
}
|
||||
|
||||
type indexData struct {
|
||||
|
@ -124,68 +123,68 @@ type indexData struct {
|
|||
News []newsEntry
|
||||
}
|
||||
|
||||
func indexHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
func indexHandler(h handler) {
|
||||
var data indexData
|
||||
|
||||
data.Tags, _ = db.GetTags(TAGS_DISPLAY)
|
||||
data.S = GetStatus(w, r)
|
||||
data.Tags, _ = h.db.GetTags(TAGS_DISPLAY)
|
||||
data.S = GetStatus(h)
|
||||
data.S.Home = true
|
||||
data.Books, data.Count, _ = db.GetBooks(bson.M{"active": true}, 6)
|
||||
data.VisitedBooks, _ = db.GetVisitedBooks(6)
|
||||
data.DownloadedBooks, _ = db.GetDownloadedBooks(6)
|
||||
data.News = getNews(1, DAYS_NEWS_INDEXPAGE)
|
||||
loadTemplate(w, "index", data)
|
||||
data.Books, data.Count, _ = h.db.GetBooks(bson.M{"active": true}, 6)
|
||||
data.VisitedBooks, _ = h.db.GetVisitedBooks(6)
|
||||
data.DownloadedBooks, _ = h.db.GetDownloadedBooks(6)
|
||||
data.News = getNews(1, DAYS_NEWS_INDEXPAGE, h.db)
|
||||
loadTemplate(h.w, "index", data)
|
||||
}
|
||||
|
||||
func notFound(w http.ResponseWriter, r *http.Request) {
|
||||
func notFound(h handler) {
|
||||
var data statusData
|
||||
|
||||
data.S = GetStatus(w, r)
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
loadTemplate(w, "404", data)
|
||||
data.S = GetStatus(h)
|
||||
h.w.WriteHeader(http.StatusNotFound)
|
||||
loadTemplate(h.w, "404", data)
|
||||
}
|
||||
|
||||
func main() {
|
||||
db = initDB()
|
||||
db := initDB()
|
||||
defer db.Close()
|
||||
|
||||
InitStats()
|
||||
InitUpload()
|
||||
InitStats(db)
|
||||
InitUpload(db)
|
||||
|
||||
setUpRouter()
|
||||
setUpRouter(db)
|
||||
panic(http.ListenAndServe(":"+PORT, nil))
|
||||
}
|
||||
|
||||
func setUpRouter() {
|
||||
func setUpRouter(db *DB) {
|
||||
r := mux.NewRouter()
|
||||
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.HandleFunc("/", GatherStats(indexHandler))
|
||||
r.HandleFunc("/book/{id:[0-9a-fA-F]+}", GatherStats(bookHandler))
|
||||
r.HandleFunc("/search/", GatherStats(searchHandler))
|
||||
r.HandleFunc("/upload/", GatherStats(uploadHandler)).Methods("GET")
|
||||
r.HandleFunc("/upload/", GatherStats(uploadPostHandler)).Methods("POST")
|
||||
r.HandleFunc("/login/", GatherStats(loginHandler)).Methods("POST")
|
||||
r.HandleFunc("/logout/", GatherStats(logoutHandler))
|
||||
r.HandleFunc("/new/", GatherStats(newHandler))
|
||||
r.HandleFunc("/store/{ids:([0-9a-fA-F]+/)+}", GatherStats(storeHandler))
|
||||
r.HandleFunc("/delete/{ids:([0-9a-fA-F]+/)+}", GatherStats(deleteHandler))
|
||||
r.HandleFunc("/read/{id:[0-9a-fA-F]+}", GatherStats(readStartHandler))
|
||||
r.HandleFunc("/read/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(readHandler))
|
||||
r.HandleFunc("/content/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(contentHandler))
|
||||
r.HandleFunc("/edit/{id:[0-9a-fA-F]+}", GatherStats(editHandler))
|
||||
r.HandleFunc("/save/{id:[0-9a-fA-F]+}", GatherStats(saveHandler)).Methods("POST")
|
||||
r.HandleFunc("/about/", GatherStats(aboutHandler))
|
||||
r.HandleFunc("/help/", GatherStats(helpHandler))
|
||||
r.HandleFunc("/download/{id:[0-9a-fA-F]+}/{epub:.*}", GatherStats(downloadHandler))
|
||||
r.HandleFunc("/cover/{id:[0-9a-fA-F]+}/{size}/{img:.*}", coverHandler)
|
||||
r.HandleFunc("/settings/", GatherStats(settingsHandler))
|
||||
r.HandleFunc("/stats/", GatherStats(statsHandler))
|
||||
r.HandleFunc("/news/", GatherStats(newsHandler))
|
||||
r.HandleFunc("/news/edit", GatherStats(editNewsHandler)).Methods("GET")
|
||||
r.HandleFunc("/news/edit", GatherStats(postNewsHandler)).Methods("POST")
|
||||
r.HandleFunc("/", GatherStats(indexHandler, db))
|
||||
r.HandleFunc("/book/{id:[0-9a-fA-F]+}", GatherStats(bookHandler, db))
|
||||
r.HandleFunc("/search/", GatherStats(searchHandler, db))
|
||||
r.HandleFunc("/upload/", GatherStats(uploadHandler, db)).Methods("GET")
|
||||
r.HandleFunc("/upload/", GatherStats(uploadPostHandler, db)).Methods("POST")
|
||||
r.HandleFunc("/login/", GatherStats(loginHandler, db)).Methods("POST")
|
||||
r.HandleFunc("/logout/", GatherStats(logoutHandler, db))
|
||||
r.HandleFunc("/new/", GatherStats(newHandler, db))
|
||||
r.HandleFunc("/store/{ids:([0-9a-fA-F]+/)+}", GatherStats(storeHandler, db))
|
||||
r.HandleFunc("/delete/{ids:([0-9a-fA-F]+/)+}", GatherStats(deleteHandler, db))
|
||||
r.HandleFunc("/read/{id:[0-9a-fA-F]+}", GatherStats(readStartHandler, db))
|
||||
r.HandleFunc("/read/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(readHandler, db))
|
||||
r.HandleFunc("/content/{id:[0-9a-fA-F]+}/{file:.*}", GatherStats(contentHandler, db))
|
||||
r.HandleFunc("/edit/{id:[0-9a-fA-F]+}", GatherStats(editHandler, db))
|
||||
r.HandleFunc("/save/{id:[0-9a-fA-F]+}", GatherStats(saveHandler, db)).Methods("POST")
|
||||
r.HandleFunc("/about/", GatherStats(aboutHandler, db))
|
||||
r.HandleFunc("/help/", GatherStats(helpHandler, db))
|
||||
r.HandleFunc("/download/{id:[0-9a-fA-F]+}/{epub:.*}", GatherStats(downloadHandler, db))
|
||||
r.HandleFunc("/cover/{id:[0-9a-fA-F]+}/{size}/{img:.*}", GatherStats(coverHandler, db))
|
||||
r.HandleFunc("/settings/", GatherStats(settingsHandler, db))
|
||||
r.HandleFunc("/stats/", GatherStats(statsHandler, db))
|
||||
r.HandleFunc("/news/", GatherStats(newsHandler, db))
|
||||
r.HandleFunc("/news/edit", GatherStats(editNewsHandler, db)).Methods("GET")
|
||||
r.HandleFunc("/news/edit", GatherStats(postNewsHandler, db)).Methods("POST")
|
||||
h := http.FileServer(http.Dir(IMG_PATH))
|
||||
r.Handle("/img/{img}", http.StripPrefix("/img/", h))
|
||||
h = http.FileServer(http.Dir(CSS_PATH))
|
||||
|
|
42
upload.go
42
upload.go
|
@ -6,13 +6,12 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func InitUpload() {
|
||||
func InitUpload(database *DB) {
|
||||
uploadChannel = make(chan uploadRequest, CHAN_SIZE)
|
||||
go uploadWorker()
|
||||
go uploadWorker(database)
|
||||
}
|
||||
|
||||
var uploadChannel chan uploadRequest
|
||||
|
@ -22,13 +21,16 @@ type uploadRequest struct {
|
|||
filename string
|
||||
}
|
||||
|
||||
func uploadWorker() {
|
||||
func uploadWorker(database *DB) {
|
||||
db := database.Copy()
|
||||
defer db.Close()
|
||||
|
||||
for req := range uploadChannel {
|
||||
processFile(req)
|
||||
processFile(req, db)
|
||||
}
|
||||
}
|
||||
|
||||
func processFile(req uploadRequest) {
|
||||
func processFile(req uploadRequest, db *DB) {
|
||||
defer req.file.Close()
|
||||
|
||||
epub, err := openMultipartEpub(req.file)
|
||||
|
@ -38,10 +40,10 @@ func processFile(req uploadRequest) {
|
|||
}
|
||||
defer epub.Close()
|
||||
|
||||
book := parseFile(epub)
|
||||
book := parseFile(epub, db)
|
||||
title, _ := book["title"].(string)
|
||||
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 {
|
||||
log.Println("Error storing book (", title, "):", err)
|
||||
return
|
||||
|
@ -57,16 +59,16 @@ func processFile(req uploadRequest) {
|
|||
log.Println("File uploaded:", req.filename)
|
||||
}
|
||||
|
||||
func uploadPostHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
||||
func uploadPostHandler(h handler) {
|
||||
problem := false
|
||||
|
||||
r.ParseMultipartForm(20000000)
|
||||
filesForm := r.MultipartForm.File["epub"]
|
||||
h.r.ParseMultipartForm(20000000)
|
||||
filesForm := h.r.MultipartForm.File["epub"]
|
||||
for _, f := range filesForm {
|
||||
file, err := f.Open()
|
||||
if err != nil {
|
||||
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
|
||||
continue
|
||||
}
|
||||
|
@ -75,19 +77,19 @@ func uploadPostHandler(w http.ResponseWriter, r *http.Request, sess *Session) {
|
|||
|
||||
if !problem {
|
||||
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 {
|
||||
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
|
||||
data.S = GetStatus(w, r)
|
||||
data.S = GetStatus(h)
|
||||
data.S.Upload = true
|
||||
loadTemplate(w, "upload", data)
|
||||
loadTemplate(h.w, "upload", data)
|
||||
}
|
||||
|
||||
type uploadData struct {
|
||||
|
@ -100,7 +102,7 @@ func openMultipartEpub(file multipart.File) (*epubgo.Epub, error) {
|
|||
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{}{}
|
||||
for _, m := range epub.MetadataFields() {
|
||||
data, err := epub.Metadata(m)
|
||||
|
@ -133,7 +135,7 @@ func parseFile(epub *epubgo.Epub) map[string]interface{} {
|
|||
}
|
||||
title, _ := book["title"].(string)
|
||||
book["file"] = nil
|
||||
cover, coverSmall := GetCover(epub, title)
|
||||
cover, coverSmall := GetCover(epub, title, db)
|
||||
if cover != "" {
|
||||
book["cover"] = cover
|
||||
book["coversmall"] = coverSmall
|
||||
|
|
Reference in a new issue