2012-08-21 18:15:21 +02:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2013-04-01 14:05:04 +02:00
|
|
|
"git.gitorious.org/go-pkg/epubgo.git"
|
2013-04-15 00:59:19 +02:00
|
|
|
"github.com/gorilla/mux"
|
2013-04-01 14:05:04 +02:00
|
|
|
"io"
|
2012-08-21 18:15:21 +02:00
|
|
|
"labix.org/v2/mgo/bson"
|
|
|
|
"net/http"
|
2012-08-28 10:38:00 +02:00
|
|
|
"strconv"
|
2012-08-31 00:24:42 +02:00
|
|
|
"strings"
|
2012-08-21 18:15:21 +02:00
|
|
|
)
|
|
|
|
|
2012-08-28 10:38:00 +02:00
|
|
|
type chapter struct {
|
2012-08-31 00:24:42 +02:00
|
|
|
Label string
|
|
|
|
Link string
|
|
|
|
Depth int
|
2012-08-28 10:38:00 +02:00
|
|
|
Active bool
|
2012-08-31 00:24:42 +02:00
|
|
|
In []bool // one level in depth
|
|
|
|
Out []bool // one level out depth
|
2012-08-28 10:38:00 +02:00
|
|
|
}
|
|
|
|
|
2012-08-21 18:15:21 +02:00
|
|
|
type readData struct {
|
2012-08-31 00:24:42 +02:00
|
|
|
S Status
|
|
|
|
Book Book
|
|
|
|
Content string
|
2012-08-28 10:38:00 +02:00
|
|
|
Chapters []chapter
|
2012-08-31 00:24:42 +02:00
|
|
|
Next string
|
|
|
|
Prev string
|
|
|
|
Back string
|
2012-08-21 18:15:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
func cleanHtml(html string) string {
|
|
|
|
str := strings.Split(html, "<body")
|
|
|
|
if len(str) < 2 {
|
|
|
|
return html
|
|
|
|
}
|
|
|
|
str = strings.SplitN(str[1], ">", 2)
|
|
|
|
if len(str) < 2 {
|
|
|
|
return str[0]
|
|
|
|
}
|
|
|
|
|
|
|
|
return "<div " + str[0] + ">" + strings.Split(str[1], "</body>")[0] + "</div>"
|
|
|
|
}
|
|
|
|
|
2012-08-28 10:38:00 +02:00
|
|
|
func genLink(id string, base string, link string) string {
|
|
|
|
return base + id + "/" + link
|
|
|
|
}
|
|
|
|
|
|
|
|
func cleanLink(link string) string {
|
|
|
|
for i := 0; i < len(link); i++ {
|
|
|
|
if link[i] == '%' {
|
|
|
|
c, _ := strconv.ParseInt(link[i+1:i+3], 16, 0)
|
|
|
|
link = link[:i] + string(c) + link[i+3:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return link
|
|
|
|
}
|
|
|
|
|
2013-04-01 14:05:04 +02:00
|
|
|
func getNextPrev(e *epubgo.Epub, file string, id string, base string) (string, string) {
|
|
|
|
spine, err := e.Spine()
|
|
|
|
if err != nil {
|
|
|
|
return "", ""
|
|
|
|
}
|
|
|
|
|
2012-08-28 11:19:53 +02:00
|
|
|
prev := ""
|
|
|
|
next := ""
|
2013-04-01 14:05:04 +02:00
|
|
|
for err == nil {
|
2013-06-04 21:30:37 +02:00
|
|
|
if cleanLink(spine.URL()) == file {
|
2013-04-01 14:05:04 +02:00
|
|
|
break
|
2012-08-28 11:19:53 +02:00
|
|
|
}
|
2013-06-04 21:30:37 +02:00
|
|
|
prev = spine.URL()
|
2013-04-01 14:05:04 +02:00
|
|
|
err = spine.Next()
|
|
|
|
}
|
|
|
|
if err != nil {
|
|
|
|
return "", ""
|
|
|
|
}
|
|
|
|
|
2013-05-28 01:22:22 +02:00
|
|
|
if prev != "" {
|
|
|
|
prev = genLink(id, base, prev)
|
|
|
|
}
|
2013-04-01 14:05:04 +02:00
|
|
|
if spine.Next() == nil {
|
2013-06-04 21:30:37 +02:00
|
|
|
next = genLink(id, base, spine.URL())
|
2013-04-01 14:05:04 +02:00
|
|
|
}
|
|
|
|
return next, prev
|
|
|
|
}
|
|
|
|
|
|
|
|
func getChapters(e *epubgo.Epub, file string, id string, base string) []chapter {
|
|
|
|
nav, err := e.Navigation()
|
|
|
|
if err != nil {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
chapters := listChapters(nav, 0)
|
|
|
|
|
|
|
|
for i, c := range chapters {
|
|
|
|
chapters[i].Link = genLink(id, base, c.Link)
|
|
|
|
if cleanLink(c.Link) == file {
|
|
|
|
chapters[i].Active = true
|
2012-08-28 11:50:08 +02:00
|
|
|
}
|
2013-04-01 14:05:04 +02:00
|
|
|
}
|
|
|
|
return chapters
|
|
|
|
}
|
|
|
|
|
|
|
|
func listChapters(nav *epubgo.NavigationIterator, depth int) []chapter {
|
|
|
|
var chapters []chapter
|
|
|
|
var err error = nil
|
|
|
|
for err == nil {
|
|
|
|
var c chapter
|
|
|
|
c.Label = nav.Title()
|
2013-06-04 21:30:37 +02:00
|
|
|
c.Link = nav.URL()
|
2013-04-01 14:05:04 +02:00
|
|
|
c.Depth = depth
|
2012-08-28 12:24:11 +02:00
|
|
|
for c.Depth < depth {
|
|
|
|
c.Out = append(c.Out, true)
|
|
|
|
depth--
|
2012-08-28 11:50:08 +02:00
|
|
|
}
|
2012-08-28 10:38:00 +02:00
|
|
|
chapters = append(chapters, c)
|
2012-08-28 11:19:53 +02:00
|
|
|
|
2013-04-01 14:05:04 +02:00
|
|
|
if nav.HasChildren() {
|
|
|
|
nav.In()
|
|
|
|
children := listChapters(nav, depth+1)
|
|
|
|
children[0].In = []bool{true}
|
|
|
|
children[len(children)-1].Out = []bool{true}
|
|
|
|
chapters = append(chapters, children...)
|
|
|
|
nav.Out()
|
|
|
|
}
|
|
|
|
err = nav.Next()
|
2012-08-28 11:19:53 +02:00
|
|
|
}
|
2013-04-01 14:05:04 +02:00
|
|
|
chapters[0].In = []bool{true}
|
|
|
|
chapters[len(chapters)-1].Out = []bool{true}
|
|
|
|
return chapters
|
2012-08-28 10:38:00 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func readStartHandler(h handler) {
|
|
|
|
id := mux.Vars(h.r)["id"]
|
|
|
|
e, _ := openReadEpub(h)
|
2013-04-16 03:28:38 +02:00
|
|
|
if e == nil {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2012-09-12 00:19:19 +02:00
|
|
|
return
|
|
|
|
}
|
2013-04-16 03:28:38 +02:00
|
|
|
defer e.Close()
|
2012-09-12 00:19:19 +02:00
|
|
|
|
2013-04-16 03:28:38 +02:00
|
|
|
it, err := e.Spine()
|
2013-04-01 14:05:04 +02:00
|
|
|
if err != nil {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2013-04-01 14:05:04 +02:00
|
|
|
return
|
|
|
|
}
|
2013-09-23 16:27:31 +02:00
|
|
|
http.Redirect(h.w, h.r, "/read/"+id+"/"+it.URL(), http.StatusTemporaryRedirect)
|
2013-04-16 03:28:38 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func readHandler(h handler) {
|
|
|
|
id := mux.Vars(h.r)["id"]
|
|
|
|
file := mux.Vars(h.r)["file"]
|
|
|
|
e, book := openReadEpub(h)
|
2013-04-16 03:28:38 +02:00
|
|
|
if e == nil {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2012-09-12 00:19:19 +02:00
|
|
|
return
|
2012-08-30 20:49:58 +02:00
|
|
|
}
|
2013-04-16 03:28:38 +02:00
|
|
|
defer e.Close()
|
2012-09-12 00:19:19 +02:00
|
|
|
|
2013-04-16 03:28:38 +02:00
|
|
|
var data readData
|
2013-09-23 16:27:31 +02:00
|
|
|
data.S = GetStatus(h)
|
2013-04-16 03:28:38 +02:00
|
|
|
data.Book = book
|
|
|
|
if !book.Active {
|
|
|
|
data.Back = "/new/"
|
|
|
|
} else {
|
|
|
|
data.Back = "/book/" + id
|
|
|
|
}
|
|
|
|
|
2013-04-15 00:59:19 +02:00
|
|
|
data.Next, data.Prev = getNextPrev(e, file, id, "/read/")
|
|
|
|
data.Chapters = getChapters(e, file, id, "/read/")
|
2012-09-12 00:19:19 +02:00
|
|
|
data.Content = genLink(id, "/content/", file)
|
2013-09-23 16:27:31 +02:00
|
|
|
loadTemplate(h.w, "read", data)
|
2012-08-30 20:49:58 +02:00
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func openReadEpub(h handler) (*epubgo.Epub, Book) {
|
2013-04-16 03:28:38 +02:00
|
|
|
var book Book
|
2013-09-23 16:27:31 +02:00
|
|
|
id := mux.Vars(h.r)["id"]
|
2013-05-09 09:42:58 +02:00
|
|
|
if !bson.IsObjectIdHex(id) {
|
|
|
|
return nil, book
|
|
|
|
}
|
2013-09-23 16:27:31 +02:00
|
|
|
books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
|
2013-04-16 03:28:38 +02:00
|
|
|
if err != nil || len(books) == 0 {
|
|
|
|
return nil, book
|
|
|
|
}
|
|
|
|
|
|
|
|
book = books[0]
|
|
|
|
if !book.Active {
|
2013-09-23 16:27:31 +02:00
|
|
|
if !h.sess.IsAdmin() {
|
2013-04-16 03:28:38 +02:00
|
|
|
return nil, book
|
|
|
|
}
|
|
|
|
}
|
2013-09-23 16:27:31 +02:00
|
|
|
e, err := OpenBook(book.File, h.db)
|
2013-04-16 03:28:38 +02:00
|
|
|
if err != nil {
|
|
|
|
return nil, book
|
|
|
|
}
|
|
|
|
return e, book
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
func contentHandler(h handler) {
|
|
|
|
vars := mux.Vars(h.r)
|
2013-04-15 00:59:19 +02:00
|
|
|
id := vars["id"]
|
|
|
|
file := vars["file"]
|
2013-05-09 09:42:58 +02:00
|
|
|
if file == "" || !bson.IsObjectIdHex(id) {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2013-04-12 01:05:40 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2013-09-23 16:27:31 +02:00
|
|
|
books, _, err := h.db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)})
|
2012-09-12 00:19:19 +02:00
|
|
|
if err != nil || len(books) == 0 {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2012-09-12 00:19:19 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
book := books[0]
|
2012-09-14 00:34:13 +02:00
|
|
|
if !book.Active {
|
2013-09-23 16:27:31 +02:00
|
|
|
if !h.sess.IsAdmin() {
|
|
|
|
notFound(h)
|
2012-08-30 20:49:58 +02:00
|
|
|
return
|
|
|
|
}
|
2012-08-21 18:15:21 +02:00
|
|
|
}
|
2013-09-23 16:27:31 +02:00
|
|
|
e, err := OpenBook(book.File, h.db)
|
2013-04-12 01:05:40 +02:00
|
|
|
if err != nil {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2012-09-12 00:19:19 +02:00
|
|
|
return
|
|
|
|
}
|
2013-04-12 01:05:40 +02:00
|
|
|
defer e.Close()
|
2012-09-12 00:19:19 +02:00
|
|
|
|
2013-04-01 14:05:04 +02:00
|
|
|
html, err := e.OpenFile(file)
|
|
|
|
if err != nil {
|
2013-09-23 16:27:31 +02:00
|
|
|
notFound(h)
|
2013-04-01 14:05:04 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
defer html.Close()
|
2013-09-23 16:27:31 +02:00
|
|
|
io.Copy(h.w, html)
|
2012-08-21 18:15:21 +02:00
|
|
|
}
|