package main import ( "git.gitorious.org/go-pkg/epub.git" "labix.org/v2/mgo/bson" "net/http" "regexp" "strconv" "strings" ) type chapter struct { Label string Link string Depth int Active bool In []bool // one level in depth Out []bool // one level out depth } type readData struct { S Status Book Book Content string Chapters []chapter Next string Prev string Back string } func parseUrl(url string) (string, string, string) { exp, _ := regexp.Compile("^(\\/[^\\/]*\\/)([^\\/]*)\\/?(.*)?$") res := exp.FindStringSubmatch(url) base := res[1] id := res[2] file := "" if len(res) == 4 { file = res[3] } return base, id, file } func cleanHtml(html string) string { str := strings.Split(html, "", 2) if len(str) < 2 { return str[0] } return "
" + strings.Split(str[1], "")[0] + "
" } 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 } /* return next and prev urls from document and the list of chapters */ func chapterList(e *epub.Epub, file string, id string, base string) (string, string, []chapter) { var chapters []chapter prev := "" next := "" tit := e.Titerator(epub.TITERATOR_NAVMAP) defer tit.Close() activeIndx := -1 depth := 0 for ; tit.Valid(); tit.Next() { var c chapter c.Label = tit.Label() c.Link = genLink(id, base, tit.Link()) if cleanLink(tit.Link()) == file { c.Active = true activeIndx = len(chapters) } c.Depth = tit.Depth() for c.Depth > depth { c.In = append(c.In, true) depth++ } for c.Depth < depth { c.Out = append(c.Out, true) depth-- } chapters = append(chapters, c) } /* if is the same chapter check the previous */ i := activeIndx - 1 for i >= 0 && strings.Contains(chapters[i].Link, "#") { i-- } if i >= 0 { prev = chapters[i].Link } i = activeIndx + 1 for i < len(chapters) && strings.Contains(chapters[i].Link, "#") { i++ } if i < len(chapters) { next = chapters[i].Link } return next, prev, chapters } func readHandler(w http.ResponseWriter, r *http.Request) { base, id, file := parseUrl(r.URL.Path) books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) if err != nil || len(books) == 0 { http.NotFound(w, r) return } var data readData data.Book = books[0] var bookPath string if !data.Book.Active { sess := GetSession(r) if sess.User == "" { http.NotFound(w, r) return } data.Back = "/new/" bookPath = NEW_PATH + data.Book.Path } else { data.Back = "/book/" + id bookPath = BOOKS_PATH + data.Book.Path } e, _ := epub.Open(bookPath, 0) defer e.Close() if file == "" { it := e.Iterator(epub.EITERATOR_LINEAR) defer it.Close() http.Redirect(w, r, base+id+"/"+it.CurrUrl(), http.StatusTemporaryRedirect) return } data.S = GetStatus(w, r) data.Next, data.Prev, data.Chapters = chapterList(e, file, id, base) data.Content = genLink(id, "/content/", file) loadTemplate(w, "read", data) } func contentHandler(w http.ResponseWriter, r *http.Request) { _, id, file := parseUrl(r.URL.Path) books, _, err := db.GetBooks(bson.M{"_id": bson.ObjectIdHex(id)}) if err != nil || len(books) == 0 { http.NotFound(w, r) return } book := books[0] var bookPath string if !book.Active { sess := GetSession(r) if sess.User == "" { http.NotFound(w, r) return } bookPath = NEW_PATH + book.Path } else { bookPath = BOOKS_PATH + book.Path } e, _ := epub.Open(bookPath, 0) defer e.Close() if file == "" { http.NotFound(w, r) return } w.Write(e.Data(file)) }