// Server entry point // Copyright (C) 2022 Nguyễn Gia Phong // // This file is part of Phylactery. // // Phylactery is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as published // by the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // Phylactery is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with Phylactery. If not, see . package main import ( "archive/zip" "embed" "html/template" "log" "io" "net/http" "os" "path" "strconv" "strings" ) //go:embed static/* var static embed.FS //go:embed templates/*.html var templates embed.FS type Page struct { Index int Name string } type Archive struct { Path string Title string Entries []Page } func main() { http.Handle("/static/", http.FileServer(http.FS(static))) t, err := template.ParseFS(templates, "templates/*.html") if err != nil { log.Fatal(err) } lib := os.Getenv("PHYLACTERY_LIBRARY") http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { p := path.Clean(lib + r.URL.Path) stat, err := os.Stat(p) if err != nil { http.NotFound(w, r) return } if stat.IsDir() { // TODO } // TODO: LRU caching cbz, err := zip.OpenReader(p) if err != nil { http.Error(w, "invalid cbz", 406) return } defer cbz.Close() r.ParseForm() if entry, isImage := r.Form["entry"]; isImage { i, err := strconv.Atoi(entry[0]) if err != nil || i < 0 || i >= len(cbz.File) { http.NotFound(w, r) return } image, _ := cbz.File[i].Open() defer image.Close() io.Copy(w, image) return } var pages []Page for i, f := range cbz.File { image, _ := cbz.File[i].Open() defer image.Close() buf := make([]byte, 512) n, _ := image.Read(buf) mime := http.DetectContentType(buf[:n]) if strings.HasPrefix(mime, "image/") { pages = append(pages, Page{ i, f.Name }) } } archive := Archive{ r.URL.Path, stat.Name(), pages } t.ExecuteTemplate(w, "archive.html", archive) }) addr := os.Getenv("PHYLACTERY_ADDRESS") log.Println("Listening on", addr) log.Fatal(http.ListenAndServe(addr, nil)) }